diff --git a/configuration/finduserbyemail.sh b/configuration/finduserbyemail.sh index ae71c35c5e3..0cf231fe417 100755 --- a/configuration/finduserbyemail.sh +++ b/configuration/finduserbyemail.sh @@ -7,9 +7,12 @@ # for db in `echo "rs.slaveOk() # show dbs # quit()" | mongo --port $port | tail -n +3 | grep -v "^bye$" | awk '{print $1;}'`; do -# match=`echo "rs.slaveOk(); db.USERS.find({EMAIL: '$useremail'}); db.COMPETITORS.find({email: '$useremail'})" | mongo --quiet --port $port $i` -# if [ "$match" != "" ]; then -# echo ${i}: $match +# match_1=`echo "rs.slaveOk() +# db.USERS.find({EMAIL: \"$useremail\"})" | mongo --quiet --port $port $db` +# match_2=`echo "rs.slaveOk() +# db.COMPETITORS.find({email: \"$useremail\"})" | mongo --quiet --port $port $db` +# if [ "$match_1" != "" -o "$match_2" != "" ]; then +# echo ${db} on port $port: $match_1 $match_2 # fi # done #done diff --git a/configuration/mail_forward.py b/configuration/mail_forward.py index d986da6e81a..d1b5a152ad7 100644 --- a/configuration/mail_forward.py +++ b/configuration/mail_forward.py @@ -15,6 +15,7 @@ import boto3 import email import re import json +import magic from botocore.exceptions import ClientError from email.parser import Parser from email.policy import default @@ -33,7 +34,10 @@ def get_message_from_s3(bucket_name, object_key): def create_message(file): senderMap = json.loads(os.environ["MailSenderJSON"]) recipientMap = json.loads(os.environ["MailRecipientsJSON"]) - mailobject = email.message_from_string(file.decode('utf-8')) + # Check encoding, uses https://pypi.org/project/python-magic/, similar to unix "file" command. + m = magic.Magic(mime_encoding=True) + encoding = m.from_buffer(file) + mailobject = email.message_from_string(file.decode(encoding)) # Define sender, either from 'To'-Header or from 'Cc'-Header sender = None # Check 'To'-Header diff --git a/configuration/mail_forwarder_lambda.zip b/configuration/mail_forwarder_lambda.zip new file mode 100644 index 00000000000..2b9ad7a92f5 Binary files /dev/null and b/configuration/mail_forwarder_lambda.zip differ diff --git a/configuration/multi-instance/001-events.conf b/configuration/multi-instance/001-events.conf new file mode 100644 index 00000000000..864d57bad1d --- /dev/null +++ b/configuration/multi-instance/001-events.conf @@ -0,0 +1,168 @@ +Use Plain-SSL 172.31.30.84 127.0.0.1 8888 +## SERVER STATUS +Use Status ec2-34-250-136-229.eu-west-1.compute.amazonaws.com internal-server-status + +# USSailing +Use Home-SSL ussailing.sapsailing.com 127.0.0.1 8889 + +# Abeam (Japanese Partner) training system +Use Plain-SSL abeam-training.sapsailing.com 127.0.0.1 8890 + +# TracTrac Test +Use Plain-SSL tractractest.sapsailing.com 127.0.0.1 8891 +Use Home-SSL tractrac.sapsailing.com 127.0.0.1 8891 + +# SAP Extreme Sailing Team Training Server (Rasmus Koestner, rasmuskostner@gmail.com) +# Dismantled 2020-01-28 after checking back with Rasmus +#Use Home-SSL extreme-team.sapsailing.com 127.0.0.1 8892 + +# VSaW +Use Home-SSL vsaw.sapsailing.com 127.0.0.1 8893 + +# Bayerischer Yacht-Club (BYC) +Use Home-SSL byc.sapsailing.com 127.0.0.1 8894 + +# SwissTiming Test (swisstimingtest) (masnica.r@st-software.com Radek Masnica) +Use Plain-SSL swisstimingtest.sapsailing.com 127.0.0.1 8895 + +# IRISHDBSCDW3 +Use Home-SSL irishdbscdw3.sapsailing.com 127.0.0.1 8896 + +# first-seascape-germany: Dieter Hagen (Deutsche First & Seascape Klassenvereinigung e.V.) +Use Home-SSL first-seascape-germany.sapsailing.com 127.0.0.1 8897 + +# Luebecker Yacht-Club (LYC) +Use Home-SSL lyc.sapsailing.com 127.0.0.1 8898 + +# Keppel Bay Sailing Club (KBSC) +Use Home-SSL kbsc.sapsailing.com 127.0.0.1 8899 + +# Seebrucker Regattaverein am Chiemsee (SRV) +Use Home-SSL srv.sapsailing.com 127.0.0.1 8900 + +# Heinz Nixdorf Verein zur Foerderung des Segelsports e.V. (HNV) +Use Home-SSL hnv.sapsailing.com 127.0.0.1 8901 + +# Israeli Sailing Association / Carmel Sailing Society +Use Home-SSL isr.sapsailing.com 127.0.0.1 8902 +Use Home-SSL cyc.sapsailing.com 127.0.0.1 8902 + +# Sailtracks Test Server +Use Home-SSL sailtracks.sapsailing.com 127.0.0.1 8903 + +# Norwegian Sailing Federation +Use Home-SSL nor.sapsailing.com 127.0.0.1 8904 + +# Jojos Nacra Campaign (jpolgar@aol.com) +Use Plain-SSL jojopolgar.sapsailing.com 127.0.0.1 8905 + +# Segelvereinigung Rhein-Neckar +Use Home-SSL srn.sapsailing.com 127.0.0.1 8906 + +# Yacht-Club Luzern (Arnet, Ivo [mailto:ivo.arnet@itready.net]) +Use Home-SSL ycl.sapsailing.com 127.0.0.1 8907 + +# Segelzentrum der Universität Kiel (Hamann, Jan [mailto:jan.hamann@email.uni-kiel.de]) +Use Home-SSL segelzentrum.sapsailing.com 127.0.0.1 8908 + +# Robert Davis Sailing, Canadian Sailing Team (Robert Davis ) +Use Plain-SSL rdsailing.sapsailing.com 127.0.0.1 8909 + +# Keith Johnson Softalk Computer Services (Keith Johnson ) +Use Plain-SSL kjscs.sapsailing.com 127.0.0.1 8910 + +# KSSS (Royal Swedish Sailing Club, Stefan Rahm ) +Use Plain-SSL ksss.sapsailing.com 127.0.0.1 8911 + +# Sailing Academy South Africa (instructor@sailingacademy.co.za, Neil Ashton) +Use Plain-SSL sailingacademy.sapsailing.com 127.0.0.1 8912 + +# StarLab (Fabiano Avancini [mailto:fabiano.avancini@gmail.com], https://www.facebook.com/events/845403545622630/) +Use Plain-SSL starlab.sapsailing.com 127.0.0.1 8913 + +# SingaporeSailing (Lim Han Ee ) +Use Plain-SSL singaporesailing.sapsailing.com 127.0.0.1 8914 + +# Club Nautic de Sitges (pa.ubach@gmail.com; on behalf of; Pere-Andreu Ubach ) +Use Plain-SSL sitges.sapsailing.com 127.0.0.1 8915 + +# Akademischer Seglerverein Aachen (Axel Schmidt, axel.sebastian.schmidt@rwth-aachen.de) +Use Plain-SSL asvia.sapsailing.com 127.0.0.1 8916 + +# Schwartauer Segler-Verein, www.ssv-net.de, Alexander Probst, webmaster@alexprobst.de +Use Plain-SSL ssv.sapsailing.com 127.0.0.1 8917 + +# SailCanada (Canadian Sailing Federation, Ken Dool, ken@sailing.ca) +Use Plain-SSL sailcanada.sapsailing.com 127.0.0.1 8918 + +# PMYC (Porto Montenegro Yacht Club, Tony Browne ) +Use Plain-SSL pmyc.sapsailing.com 127.0.0.1 8919 + +# SSC (Segeberger Segel Club, Thomas Glas, th.glas@gmail.com) +Use Plain-SSL ssc.sapsailing.com 127.0.0.1 8920 + +# SailRacer (Ricardas Novosinskas ) +Use Plain-SSL sailracer.sapsailing.com 127.0.0.1 8922 + +# Galvestaure (Mantas Klimantavicius ) +Use Plain-SSL galvestaure.sapsailing.com 127.0.0.1 8923 + +# Tobias Schadewaldt +Use Plain-SSL schadewaldt.sapsailing.com 127.0.0.1 8924 + +# HSC Women's Team +Use Plain-SSL hsc-womensteam.sapsailing.com 127.0.0.1 8925 + +# aarhussejlklub.sapsailing.com (Fredrik Strange ) +Use Plain-SSL aarhussejlklub.sapsailing.com 127.0.0.1 8927 + +# d-labs.sapsailing.com (David Eickhoff ) +Use Plain-SSL d-labs.sapsailing.com 127.0.0.1 8928 + +# alarie505.sapsailing.com (Peter Alarie,alarie505@gmail.com) +Use Plain-SSL alarie505.sapsailing.com 127.0.0.1 8929 + +# schanzenberg.sapsailing.com (Segelzentrum Schanzenberg, Florian Mösch ) +Use Plain-SSL schanzenberg.sapsailing.com 127.0.0.1 8930 + +# phoenix.sapsailing.com (Team Phoenix, Douglas Edwards , Kristina Plattner ) +Use Plain-SSL phoenix.sapsailing.com 127.0.0.1 8931 + +# my.sapsailing.com (Self-Service Smartphone Tracking) +Use Home-SSL my.sapsailing.com 127.0.0.1 8932 + +# mdf.sapsailing.com (Medway Dragon Fleet, Chris Brealy ) +Use Home-SSL mdf.sapsailing.com 127.0.0.1 8933 + +# jonaswitt.sapsailing.com (Jonas Witt, jonas@sailnjord.com) +Use Plain-SSL jonaswitt.sapsailing.com 127.0.0.1 8934 + +# seascape.sapsailing.com (Dejan Presen ) +use Home-SSL seascape.sapsailing.com 127.0.0.1 8935 + +# Port 8936 (HTTP) freed up; + +# oakcliff.sapsailing.com (Patrick Burks, Director Oakcliff Sailing , Roy Craft ) +use Plain-SSL oakcliff.sapsailing.com 127.0.0.1 8937 + +# rheinwoche.sapsailing.com (Christoph Zander, praesident@h-boot.org, info@christophzander.de) +use Home-SSL rheinwoche.sapsailing.com 127.0.0.1 8938 + +# kyc.sapsailing.com (Kieler Yacht Club, Felix Weidling, fw@kyc.de) +use Plain-SSL kyc.sapsailing.com 127.0.0.1 8939 + +# schwielochsee.sapsailing.com (Segelclub Schwielochsee e.V., Maximilian Hartig, maximilian.hartig@sap.com, mh@sc-schwielochsee.de) +use Plain-SSL schwielochsee.sapsailing.com 127.0.0.1 8940 + +# formula18.sapsailing.com (Formula 18 Class Association, Dirk Bleiker ) +use Plain-SSL formula18.sapsailing.com 127.0.0.1 8941 + +# baldeneysee.sapsailing.com (Wettfahrtgemeinschaft der Segler am Baldeneysee, https://wfg-baldeneysee.org/, Christoph Zander, vorsitzender@etuf-segeln.de, administrator@wfg-baldeneysee.org) +use Home-SSL baldeneysee.sapsailing.com 127.0.0.1 8942 + +# Peter Wagner, AUT, Skype: peterwagner77, +4366087100213 +Use Home-SSL peter-training.sapsailing.com 127.0.0.1 8943 + +# Janek Balster, Schilkseer Yacht Club (SYC) +Use Home-SSL janek-training.sapsailing.com 127.0.0.1 8944 + diff --git a/configuration/multi-instance/TEMPLATE/env.sh b/configuration/multi-instance/TEMPLATE/env.sh new file mode 100755 index 00000000000..2d96a48374f --- /dev/null +++ b/configuration/multi-instance/TEMPLATE/env.sh @@ -0,0 +1,211 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + diff --git a/configuration/multi-instance/aarhussejlklub/env.sh b/configuration/multi-instance/aarhussejlklub/env.sh new file mode 100755 index 00000000000..921ede5fd15 --- /dev/null +++ b/configuration/multi-instance/aarhussejlklub/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=aarhussejlklub +SERVER_NAME=AARHUSSEJLKLUB +SERVER_PORT=8927 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/AARHUSSEJLKLUB" +EXPEDITION_PORT=2049 +TELNET_PORT=14927 diff --git a/configuration/multi-instance/abeam-training/env.sh b/configuration/multi-instance/abeam-training/env.sh new file mode 100755 index 00000000000..e634eb6cd16 --- /dev/null +++ b/configuration/multi-instance/abeam-training/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=abeam-training +SERVER_NAME=abeam-training +SERVER_PORT=8890 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/abeam-training?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2012 +TELNET_PORT=14890 diff --git a/configuration/multi-instance/alarie505/env.sh b/configuration/multi-instance/alarie505/env.sh new file mode 100755 index 00000000000..e8033a9b958 --- /dev/null +++ b/configuration/multi-instance/alarie505/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=alarie505 +SERVER_NAME=alarie505 +SERVER_PORT=8929 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/alarie505" +EXPEDITION_PORT=2051 +TELNET_PORT=14929 diff --git a/configuration/multi-instance/asvia/env.sh b/configuration/multi-instance/asvia/env.sh new file mode 100755 index 00000000000..76cc3353825 --- /dev/null +++ b/configuration/multi-instance/asvia/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=asvia +SERVER_NAME=ASVIA +SERVER_PORT=8916 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/ASVIA" +EXPEDITION_PORT=2038 +TELNET_PORT=14916 diff --git a/configuration/multi-instance/baldeneysee/env.sh b/configuration/multi-instance/baldeneysee/env.sh new file mode 100755 index 00000000000..5c8b2d6e959 --- /dev/null +++ b/configuration/multi-instance/baldeneysee/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=baldeneysee +SERVER_NAME=baldeneysee +SERVER_PORT=8942 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/baldeneysee?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2064 +TELNET_PORT=14942 diff --git a/configuration/multi-instance/byc/env.sh b/configuration/multi-instance/byc/env.sh new file mode 100755 index 00000000000..203815fcb84 --- /dev/null +++ b/configuration/multi-instance/byc/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=byc +SERVER_NAME=BYC +SERVER_PORT=8894 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/BYC?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2016 +TELNET_PORT=14894 diff --git a/configuration/multi-instance/copy-instance b/configuration/multi-instance/copy-instance new file mode 100755 index 00000000000..bedaae18ed8 --- /dev/null +++ b/configuration/multi-instance/copy-instance @@ -0,0 +1,14 @@ +#!/bin/bash +SERVER_NAME=$1 +SERVER_PORT=$2 +TELNET_PORT=$((SERVER_PORT+6000)) +EXPEDITION_PORT=$((2010+SERVER_PORT-8888)) +MONGODB_URI=$3 +cp -rp TEMPLATE $SERVER_NAME +ENV_SH=$SERVER_NAME/env.sh +echo "DEPLOY_TO=$SERVER_NAME" >>$ENV_SH +echo "SERVER_NAME=$SERVER_NAME" >>$ENV_SH +echo "SERVER_PORT=$SERVER_PORT" >>$ENV_SH +echo "MONGODB_URI=\"$MONGODB_URI\"" >>$ENV_SH +echo "EXPEDITION_PORT=$EXPEDITION_PORT" >>$ENV_SH +echo "TELNET_PORT=$TELNET_PORT" >>$ENV_SH diff --git a/configuration/multi-instance/first-seascape-germany/env.sh b/configuration/multi-instance/first-seascape-germany/env.sh new file mode 100755 index 00000000000..2cc85e8c237 --- /dev/null +++ b/configuration/multi-instance/first-seascape-germany/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=first-seascape-germany +SERVER_NAME=first-seascape-germany +SERVER_PORT=8897 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/first-seascape-germany?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2019 +TELNET_PORT=14897 diff --git a/configuration/multi-instance/formula18/env.sh b/configuration/multi-instance/formula18/env.sh new file mode 100755 index 00000000000..70a4ba70935 --- /dev/null +++ b/configuration/multi-instance/formula18/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=formula18 +SERVER_NAME=formula18 +SERVER_PORT=8941 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/formula18?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2063 +TELNET_PORT=14941 diff --git a/configuration/multi-instance/galvestaure/env.sh b/configuration/multi-instance/galvestaure/env.sh new file mode 100755 index 00000000000..40948161cba --- /dev/null +++ b/configuration/multi-instance/galvestaure/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=galvestaure +SERVER_NAME=galvestaure +SERVER_PORT=8923 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/galvestaure?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2045 +TELNET_PORT=14923 diff --git a/configuration/multi-instance/hnv/env.sh b/configuration/multi-instance/hnv/env.sh new file mode 100755 index 00000000000..b61a28815be --- /dev/null +++ b/configuration/multi-instance/hnv/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=hnv +SERVER_NAME=HNV +SERVER_PORT=8901 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/HNV?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2023 +TELNET_PORT=14901 diff --git a/configuration/multi-instance/hsc-womensteam/env.sh b/configuration/multi-instance/hsc-womensteam/env.sh new file mode 100755 index 00000000000..2dd0ca39cc9 --- /dev/null +++ b/configuration/multi-instance/hsc-womensteam/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=hsc-womensteam +SERVER_NAME=hsc-womensteam +SERVER_PORT=8925 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/hsc-womensteam" +EXPEDITION_PORT=2047 +TELNET_PORT=14925 diff --git a/configuration/multi-instance/irishdbscdw3/env.sh b/configuration/multi-instance/irishdbscdw3/env.sh new file mode 100755 index 00000000000..2c2959239d7 --- /dev/null +++ b/configuration/multi-instance/irishdbscdw3/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=irishdbscdw3 +SERVER_NAME=IRISHDBSCDW3 +SERVER_PORT=8896 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/irishdbscdw3" +EXPEDITION_PORT=2018 +TELNET_PORT=14896 diff --git a/configuration/multi-instance/isr/env.sh b/configuration/multi-instance/isr/env.sh new file mode 100755 index 00000000000..065e4da237a --- /dev/null +++ b/configuration/multi-instance/isr/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=isr +SERVER_NAME=ISR +SERVER_PORT=8902 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/ISR" +EXPEDITION_PORT=2024 +TELNET_PORT=14902 diff --git a/configuration/multi-instance/janek-training/env.sh b/configuration/multi-instance/janek-training/env.sh new file mode 100755 index 00000000000..99cfe929453 --- /dev/null +++ b/configuration/multi-instance/janek-training/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=janek-training +SERVER_NAME=janekbalster +SERVER_PORT=8944 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/janekbalster" +EXPEDITION_PORT=2066 +TELNET_PORT=14944 diff --git a/configuration/multi-instance/jojopolgar/env.sh b/configuration/multi-instance/jojopolgar/env.sh new file mode 100755 index 00000000000..3760b10fb45 --- /dev/null +++ b/configuration/multi-instance/jojopolgar/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=jojopolgar +SERVER_NAME=JOJOPOLGAR +SERVER_PORT=8905 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/JOJOPOLGAR?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2027 +TELNET_PORT=14905 diff --git a/configuration/multi-instance/jonaswitt/env.sh b/configuration/multi-instance/jonaswitt/env.sh new file mode 100755 index 00000000000..2d23fa576b7 --- /dev/null +++ b/configuration/multi-instance/jonaswitt/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=jonaswitt +SERVER_NAME=jonaswitt +SERVER_PORT=8934 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/jonaswitt?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2056 +TELNET_PORT=14934 diff --git a/configuration/multi-instance/kbsc/env.sh b/configuration/multi-instance/kbsc/env.sh new file mode 100755 index 00000000000..8917ed037e8 --- /dev/null +++ b/configuration/multi-instance/kbsc/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=kbsc +SERVER_NAME=KBSC +SERVER_PORT=8899 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/KBSC" +EXPEDITION_PORT=2021 +TELNET_PORT=14899 diff --git a/configuration/multi-instance/kjscs/env.sh b/configuration/multi-instance/kjscs/env.sh new file mode 100755 index 00000000000..b2a1f19027e --- /dev/null +++ b/configuration/multi-instance/kjscs/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=kjscs +SERVER_NAME=KJSCS +SERVER_PORT=8910 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/KJSCS?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2032 +TELNET_PORT=14910 diff --git a/configuration/multi-instance/ksss/env.sh b/configuration/multi-instance/ksss/env.sh new file mode 100755 index 00000000000..94110a4d00e --- /dev/null +++ b/configuration/multi-instance/ksss/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=ksss +SERVER_NAME=KSSS +SERVER_PORT=8911 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/KSSS" +EXPEDITION_PORT=2033 +TELNET_PORT=14911 diff --git a/configuration/multi-instance/kyc/env.sh b/configuration/multi-instance/kyc/env.sh new file mode 100755 index 00000000000..937e7af8e67 --- /dev/null +++ b/configuration/multi-instance/kyc/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=kyc +SERVER_NAME=kyc +SERVER_PORT=8939 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/kyc?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2061 +TELNET_PORT=14939 diff --git a/configuration/multi-instance/lyc/env.sh b/configuration/multi-instance/lyc/env.sh new file mode 100755 index 00000000000..8ece59e4492 --- /dev/null +++ b/configuration/multi-instance/lyc/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +SERVER_NAME=LYC +DEPLOY_TO=lyc +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/LYC?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2020 +SERVER_PORT=8898 +TELNET_PORT=14898 diff --git a/configuration/multi-instance/mdf/env.sh b/configuration/multi-instance/mdf/env.sh new file mode 100755 index 00000000000..96ddc3df040 --- /dev/null +++ b/configuration/multi-instance/mdf/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=mdf +SERVER_NAME=mdf +SERVER_PORT=8933 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/mdf" +EXPEDITION_PORT=2055 +TELNET_PORT=14933 diff --git a/configuration/multi-instance/my/env.sh b/configuration/multi-instance/my/env.sh new file mode 100755 index 00000000000..a65eaf32eb4 --- /dev/null +++ b/configuration/multi-instance/my/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=my +SERVER_NAME=my +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/my?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2054 +SERVER_PORT=8932 +TELNET_PORT=14932 diff --git a/configuration/multi-instance/nor/env.sh b/configuration/multi-instance/nor/env.sh new file mode 100755 index 00000000000..00dcb39800b --- /dev/null +++ b/configuration/multi-instance/nor/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=nor +SERVER_NAME=NOR +SERVER_PORT=8904 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/NOR?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2026 +TELNET_PORT=14904 diff --git a/configuration/multi-instance/oakcliff/env.sh b/configuration/multi-instance/oakcliff/env.sh new file mode 100755 index 00000000000..613dfc27235 --- /dev/null +++ b/configuration/multi-instance/oakcliff/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=oakcliff +SERVER_NAME=oakcliff +SERVER_PORT=8937 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/oakcliff?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2059 +TELNET_PORT=14937 diff --git a/configuration/multi-instance/peter-training/env.sh b/configuration/multi-instance/peter-training/env.sh new file mode 100755 index 00000000000..94eb3a24dbe --- /dev/null +++ b/configuration/multi-instance/peter-training/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=peter-training +SERVER_NAME=peterwagner +SERVER_PORT=8943 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/peterwagner?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2065 +TELNET_PORT=14943 diff --git a/configuration/multi-instance/phoenix/env.sh b/configuration/multi-instance/phoenix/env.sh new file mode 100755 index 00000000000..de361731ddf --- /dev/null +++ b/configuration/multi-instance/phoenix/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=phoenix +SERVER_NAME=phoenix +SERVER_PORT=8931 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/phoenix" +EXPEDITION_PORT=2053 +TELNET_PORT=14931 diff --git a/configuration/multi-instance/pmyc/env.sh b/configuration/multi-instance/pmyc/env.sh new file mode 100755 index 00000000000..c690ffa5468 --- /dev/null +++ b/configuration/multi-instance/pmyc/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=pmyc +SERVER_NAME=PMYC +SERVER_PORT=8919 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/PMYC" +EXPEDITION_PORT=2041 +TELNET_PORT=14919 diff --git a/configuration/multi-instance/rdsailing/env.sh b/configuration/multi-instance/rdsailing/env.sh new file mode 100755 index 00000000000..0b59731f0fc --- /dev/null +++ b/configuration/multi-instance/rdsailing/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=rdsailing +SERVER_NAME=RDSAILING +SERVER_PORT=8909 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/RDSAILING?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2031 +TELNET_PORT=14909 diff --git a/configuration/multi-instance/rheinwoche/env.sh b/configuration/multi-instance/rheinwoche/env.sh new file mode 100755 index 00000000000..726e33fd13d --- /dev/null +++ b/configuration/multi-instance/rheinwoche/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=rheinwoche +SERVER_NAME=rheinwoche2019 +SERVER_PORT=8938 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/rheinwoche2019?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2060 +TELNET_PORT=14938 diff --git a/configuration/multi-instance/sailcanada/env.sh b/configuration/multi-instance/sailcanada/env.sh new file mode 100755 index 00000000000..b3ee8fcf36a --- /dev/null +++ b/configuration/multi-instance/sailcanada/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=sailcanada +SERVER_NAME=SAILCANADA +SERVER_PORT=8918 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/SAILCANADA" +EXPEDITION_PORT=2040 +TELNET_PORT=14918 diff --git a/configuration/multi-instance/sailingacademy/env.sh b/configuration/multi-instance/sailingacademy/env.sh new file mode 100755 index 00000000000..92fd9c3440b --- /dev/null +++ b/configuration/multi-instance/sailingacademy/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=sailingacademy +SERVER_NAME=SAILINGACADEMY +SERVER_PORT=8912 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/SAILINGACADEMY" +EXPEDITION_PORT=2034 +TELNET_PORT=14912 diff --git a/configuration/multi-instance/sailracer/env.sh b/configuration/multi-instance/sailracer/env.sh new file mode 100755 index 00000000000..568a008fd8e --- /dev/null +++ b/configuration/multi-instance/sailracer/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=sailracer +SERVER_NAME=sailracer +SERVER_PORT=8922 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/sailracer?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2044 +TELNET_PORT=14922 diff --git a/configuration/multi-instance/sailtracks/env.sh b/configuration/multi-instance/sailtracks/env.sh new file mode 100755 index 00000000000..9d322d399ca --- /dev/null +++ b/configuration/multi-instance/sailtracks/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS" +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_EXCHANGE_NAME= + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +#REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=sailtracks +SERVER_NAME=sailtracks +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/Sailtracks?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2025 +SERVER_PORT=8903 +TELNET_PORT=14903 diff --git a/configuration/multi-instance/schadewaldt/env.sh b/configuration/multi-instance/schadewaldt/env.sh new file mode 100755 index 00000000000..d8f440a267c --- /dev/null +++ b/configuration/multi-instance/schadewaldt/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=schadewaldt +SERVER_NAME=schadewaldt +SERVER_PORT=8924 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/schadewaldt" +EXPEDITION_PORT=2046 +TELNET_PORT=14924 diff --git a/configuration/multi-instance/schanzenberg/env.sh b/configuration/multi-instance/schanzenberg/env.sh new file mode 100755 index 00000000000..9ef51797232 --- /dev/null +++ b/configuration/multi-instance/schanzenberg/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=schanzenberg +SERVER_NAME=schanzenberg +SERVER_PORT=8930 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/schanzenberg" +EXPEDITION_PORT=2052 +TELNET_PORT=14930 diff --git a/configuration/multi-instance/schwielochsee/env.sh b/configuration/multi-instance/schwielochsee/env.sh new file mode 100755 index 00000000000..65c37dc7ffe --- /dev/null +++ b/configuration/multi-instance/schwielochsee/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=schwielochsee +SERVER_NAME=schwielochsee +SERVER_PORT=8940 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/schwielochsee?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2062 +TELNET_PORT=14940 diff --git a/configuration/multi-instance/seascape/env.sh b/configuration/multi-instance/seascape/env.sh new file mode 100755 index 00000000000..8f57aa158db --- /dev/null +++ b/configuration/multi-instance/seascape/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=seascape +SERVER_NAME=SEASCAPE +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/seascape?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2057 +SERVER_PORT=8935 +TELNET_PORT=14935 diff --git a/configuration/multi-instance/segelzentrum/env.sh b/configuration/multi-instance/segelzentrum/env.sh new file mode 100755 index 00000000000..4fa80983543 --- /dev/null +++ b/configuration/multi-instance/segelzentrum/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=segelzentrum +SERVER_NAME=SEGELZENTRUM +SERVER_PORT=8908 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/SEGELZENTRUM?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2030 +TELNET_PORT=14908 diff --git a/configuration/multi-instance/singaporesailing/env.sh b/configuration/multi-instance/singaporesailing/env.sh new file mode 100755 index 00000000000..ec5615f707c --- /dev/null +++ b/configuration/multi-instance/singaporesailing/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=singaporesailing +SERVER_NAME=SINGAPORESAILING +SERVER_PORT=8914 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/SINGAPORESAILING" +EXPEDITION_PORT=2036 +TELNET_PORT=14914 diff --git a/configuration/multi-instance/sitges/env.sh b/configuration/multi-instance/sitges/env.sh new file mode 100755 index 00000000000..9b02699ef00 --- /dev/null +++ b/configuration/multi-instance/sitges/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=sitges +SERVER_NAME=SITGES +SERVER_PORT=8915 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/SITGES?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2037 +TELNET_PORT=14915 diff --git a/configuration/multi-instance/srn/env.sh b/configuration/multi-instance/srn/env.sh new file mode 100755 index 00000000000..402eda8fed4 --- /dev/null +++ b/configuration/multi-instance/srn/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=srn +SERVER_NAME=SRN +SERVER_PORT=8906 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/SRN?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2028 +TELNET_PORT=14906 diff --git a/configuration/multi-instance/srv/env.sh b/configuration/multi-instance/srv/env.sh new file mode 100755 index 00000000000..c7cb7f5fb0f --- /dev/null +++ b/configuration/multi-instance/srv/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=srv +SERVER_NAME=SRV +SERVER_PORT=8900 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/SRV?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2022 +TELNET_PORT=14900 diff --git a/configuration/multi-instance/ssc/env.sh b/configuration/multi-instance/ssc/env.sh new file mode 100755 index 00000000000..e619e4a10ad --- /dev/null +++ b/configuration/multi-instance/ssc/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=ssc +SERVER_NAME=SSC +SERVER_PORT=8920 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/SSC" +EXPEDITION_PORT=2042 +TELNET_PORT=14920 diff --git a/configuration/multi-instance/ssv/env.sh b/configuration/multi-instance/ssv/env.sh new file mode 100755 index 00000000000..c83791c3acc --- /dev/null +++ b/configuration/multi-instance/ssv/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=ssv +SERVER_NAME=SSV +SERVER_PORT=8917 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/SSV" +EXPEDITION_PORT=2039 +TELNET_PORT=14917 diff --git a/configuration/multi-instance/starlab/env.sh b/configuration/multi-instance/starlab/env.sh new file mode 100755 index 00000000000..0e623e6dfcc --- /dev/null +++ b/configuration/multi-instance/starlab/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=starlab +SERVER_NAME=STARLAB +SERVER_PORT=8913 +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/STARLAB?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2035 +TELNET_PORT=14913 diff --git a/configuration/multi-instance/swisstimingtest/env.sh b/configuration/multi-instance/swisstimingtest/env.sh new file mode 100755 index 00000000000..65f485a2775 --- /dev/null +++ b/configuration/multi-instance/swisstimingtest/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=swisstimingtest +SERVER_NAME=swisstimingtest +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/swisstimingtest?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2017 +SERVER_PORT=8895 +TELNET_PORT=14895 diff --git a/configuration/multi-instance/tractractest/env.sh b/configuration/multi-instance/tractractest/env.sh new file mode 100755 index 00000000000..bba8b0c361f --- /dev/null +++ b/configuration/multi-instance/tractractest/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=tractractest +SERVER_NAME=TracTracTest +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/TracTracTest?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2013 +SERVER_PORT=8891 +TELNET_PORT=14891 diff --git a/configuration/multi-instance/ussailing/env.sh b/configuration/multi-instance/ussailing/env.sh new file mode 100755 index 00000000000..e961dd3290a --- /dev/null +++ b/configuration/multi-instance/ussailing/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=ussailing +SERVER_NAME=USSAILING +SERVER_PORT=8889 +MONGODB_URI="mongodb://dbserver.internal.sapsailing.com:10202/USSAILING" +EXPEDITION_PORT=14889 +TELNET_PORT=2011 diff --git a/configuration/multi-instance/vsaw/env.sh b/configuration/multi-instance/vsaw/env.sh new file mode 100755 index 00000000000..ca5214be346 --- /dev/null +++ b/configuration/multi-instance/vsaw/env.sh @@ -0,0 +1,217 @@ +#!/bin/bash + +# This file contains the configuration for the Java server + +# ******************************************************* +# ATTENTION: Make sure to always also check the variables at the end +# of this file as there could be overwritten ones! +# ******************************************************* + +if [ -z $SERVER_NAME ]; then + SERVER_NAME=MASTER +fi + +# This is a default heap size only; the boot script of an instance (see +# configuration/sailing) will add a MEMORY assignment to this file in the +# server's directory that has a default value computed from the total +# memory installed in the machine and the number of server instances to +# start on that machine. This default can be overwritten by manually appending +# another MEMORY assignment at the end of the file or by defining an environment +# file with a MEMORY assignment which is then used in conjunction with refreshInstance.sh +# or by setting the MEMORY variable in the EC2 Instance Details section which will be appended +# at the end of the file. +MEMORY="20000m" + +# Message Queue hostname where to +# send messages for replicas (this server is master) +if [ -z $REPLICATION_HOST ]; then + REPLICATION_HOST=localhost +fi +# For the port, use 0 for the RabbitMQ default or a specific port that your RabbitMQ server is listening on +if [ -z $REPLICATION_PORT ]; then + REPLICATION_PORT=0 +fi +# The name of the message queuing fan-out exchange that this server will use in its role as replication master. +# Make sure this is unique so that no other master is writing to this exchange at any time. +if [ -z $REPLICATION_CHANNEL ]; then + REPLICATION_CHANNEL=sapsailinganalytics-master +fi + +if [ -z $TELNET_PORT ]; then + TELNET_PORT=14888 +fi +if [ -z $SERVER_PORT ]; then + SERVER_PORT=8888 +fi +if [ -z $MONGODB_HOST ]; then + MONGODB_HOST=10.0.75.1 +fi +if [ -z $MONGODB_PORT ]; then + MONGODB_PORT=27017 +fi +if [ -z $MONGODB_NAME ]; then + MONGODB_NAME=winddb +fi +if [ -z $EXPEDITION_PORT ]; then + EXPEDITION_PORT=2010 +fi + +# To start replication upon startup provide the fully-qualified names of the Replicable service classes +# for which to trigger replication. If you activate this make sure to +# set the REPLICATE_MASTER_EXCHANGE_NAME variable to the +# same channel the master is using in its REPLICATION_CHANNEL variable + +if [ -n "$AUTO_REPLICATE" ]; then + REPLICATE_ON_START=com.sap.sailing.server.impl.RacingEventServiceImpl,com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sse.filestorage.impl.FileStorageManagementServiceImpl,com.sap.sse.mail.impl.MailServiceImpl,com.sap.sailing.polars.impl.PolarDataServiceImpl,com.sap.sailing.domain.racelogtracking.impl.fixtracker.RegattaLogFixTrackerRegattaListener,com.sap.sailing.windestimation.integration.WindEstimationFactoryServiceImpl,com.sap.sailing.server.impl.com.sap.sailing.shared.server.impl.SharedSailingDataImpl +fi +# Host where the master Java instance is running +# Make sure firewall configurations allow access +# +# REPLICATE_MASTER_SERVLET_HOST= +# REPLICATE_MASTER_SERVLET_PORT= + +# Host where RabbitMQ is running +# REPLICATE_MASTER_QUEUE_HOST= +# Port that RabbitMQ is listening on (normally something like 5672); use 0 to connect to RabbitMQ's default port +if [ -z $REPLICATE_MASTER_QUEUE_PORT ]; then + REPLICATE_MASTER_QUEUE_PORT=0 +fi + +# Exchange name that the master from which to auto-replicate is using as +# its REPLICATION_CHANNEL variable, mapping to the master's replication.exchangeName +# system property. +# +# REPLICATE_MASTER_EXCHANGE_NAME= + +# Credentials for replication access to the master server +# Make sure, the user is granted the permission SERVER:REPLICATE: +# Credentials can be provided either as a combination of username and password, +# or alternatively as a single bearer token that was obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://master-server.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the master server using your web browser and then navigating to +# https://master-server.sapsailing.com/security/api/restsecurity/access_token +# +# REPLICATE_MASTER_USERNAME= +# REPLICATE_MASTER_PASSWORD= +# REPLICATE_MASTER_BEARER_TOKEN= + +# Automatic build and test configuration +DEPLOY_TO=server +BUILD_BEFORE_START=False +BUILD_FROM=master +COMPILE_GWT=True +RUN_TESTS=False +CODE_DIRECTORY=code + +# Specify an email adress that should be notified +# whenever a build or install has been completed +# +# BUILD_COMPLETE_NOTIFY= + +# Specify an email address that should be notified +# whenever the server has been started +# +# SERVER_STARTUP_NOTIFY= + +# Specify filename that is usually located at +# http://release.sapsailing.com/ that should +# be used as a base for the server +# +# INSTALL_FROM_RELEASE= + +# Specify name of file that can usually be found +# at http://release.sapsailing.com/environments +# +# USE_ENVIRONMENT= + +INSTANCE_ID="$SERVER_NAME:$SERVER_PORT" +if [[ ! -d $JAVA_HOME ]] && [[ -f "/usr/libexec/java_home" ]]; then + JAVA_HOME=`/usr/libexec/java_home` +fi +JAVA_BINARY="$JAVA_HOME/bin/java" +JAVA_VERSION_OUTPUT=$("$JAVA_BINARY" -version 2>&1) +JAVA_VERSION=$(echo "$JAVA_VERSION_OUTPUT" | sed 's/^.* version "\(.*\)\.\(.*\)\..*".*$/\1.\2/; 1q') +export JAVA_11_LOGGING_ARGS="-Xlog:gc+ergo*=trace:file=logs/gc_ergo.log:time:filecount=10,filesize=100000 -Xlog:gc*:file=logs/gc.log:time:filecount=10,filesize=100000" +export JAVA_11_ARGS="-Dosgi.java.profile=file://`pwd`/JavaSE-11.profile --add-modules=ALL-SYSTEM -Djavax.xml.bind.JAXBContextFactory=com.sun.xml.bind.v2.ContextFactory -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+UseZGC ${JAVA_11_LOGGING_ARGS}" +export JAVA_8_LOGGING_ARGS="-XX:+PrintAdaptiveSizePolicy -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:logs/gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M" +echo JAVA_VERSION detected: $JAVA_VERSION +if echo $JAVA_VERSION | grep -q "^11\."; then + echo Java 11 detected + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_11_ARGS +else + echo Java other than 11 detected + # options for use with SAP JVM only: + if echo "$JAVA_VERSION_OUTPUT" | grep -q "SAP Java"; then + ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -XX:+GCHistory -XX:GCHistoryFilename=logs/sapjvm_gc@PID.prf" + BUILD=$( echo "$JAVA_VERSION_OUTPUT" | grep "(build [^ ]*)" ) + MAJOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\1/' ) + MINOR=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\2/' ) + UPDATE=$( echo "$BUILD" | sed -e 's/^.*(build \([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)).*$/\3/' ) + echo "SAP JVM $MAJOR $MINOR $UPDATE detected" + if [ $MAJOR -ge 8 -a $MINOR -ge 1 -a $UPDATE -ge 45 ]; then + echo "Update 8.1.045 or later; using Java11 GC logging options" + LOGGING_ARGS="$JAVA_11_LOGGING_ARGS" + else + echo "Update before 8.1.045; using Java8 GC logging options" + LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + else + # non-SAP JVM 8 + export LOGGING_ARGS="$JAVA_8_LOGGING_ARGS" + fi + export JAVA_8_ARGS="-XX:ThreadPriorityPolicy=2 -XX:+UseG1GC ${LOGGING_ARGS}" + JAVA_VERSION_SPECIFIC_ARGS=$JAVA_8_ARGS +fi +ADDITIONAL_JAVA_ARGS="$JAVA_VERSION_SPECIFIC_ARGS $ADDITIONAL_JAVA_ARGS -Dpersistentcompetitors.clear=false -Drestore.tracked.races=true -Dpolardata.source.url=https://www.sapsailing.com -Dwindestimation.source.url=https://www.sapsailing.com -XX:MaxGCPauseMillis=500" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com, uncomment and fill in the following: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service +# Obtain the bearer token for user security-service-replicator by logging on to https://security-service.sapsailing.com and then +# getting https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +echo ADDITIONAL_JAVA_ARGS=${ADDITIONAL_JAVA_ARGS} +ON_AMAZON=`command -v ec2-metadata` + +# **** Overwritten environment variables **** +# live-master-server +REPLICATION_HOST=rabbit.internal.sapsailing.com +TELNET_PORT=14888 +SERVER_PORT=8888 +MONGODB_HOST=dbserver.internal.sapsailing.com +MONGODB_PORT=10202 +EXPEDITION_PORT=2010 +REPLICATE_ON_START= +REPLICATE_MASTER_SERVLET_HOST= +REPLICATE_MASTER_SERVLET_PORT= +REPLICATE_MASTER_QUEUE_HOST=rabbit.internal.sapsailing.com +REPLICATE_MASTER_QUEUE_PORT=5672 +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Xms$MEMORY -Dorg.eclipse.jetty.LEVEL=OFF -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -XX:ThreadPriorityPolicy=2" + +# To enable the use of the shared SecurityService and SharedSailingData from security-service.sapsailing.com: +ADDITIONAL_JAVA_ARGS="$ADDITIONAL_JAVA_ARGS -Dsecurity.sharedAcrossSubdomainsOf=sapsailing.com -Dsecurity.baseUrlForCrossDomainStorage=https://security-service.sapsailing.com -Dgwt.acceptableCrossDomainStorageRequestOriginRegexp=https?://(.*\.)?sapsailing\.com(:[0-9]*)?$" +REPLICATE_ON_START=com.sap.sse.security.impl.SecurityServiceImpl,com.sap.sailing.shared.server.impl.SharedSailingDataImpl +REPLICATE_MASTER_SERVLET_HOST=security-service.sapsailing.com +REPLICATE_MASTER_SERVLET_PORT=443 +REPLICATE_MASTER_EXCHANGE_NAME=security_service + +# Provide authentication credentials for a user on the security-service.sapsailing.com permitted to replicate, either by username/password... +#REPLICATE_MASTER_USERNAME=(user for replicator login on security-service.sapsailing.com server having SERVER:REPLICATE:<server-name> permission) +#REPLICATE_MASTER_PASSWORD=(password of the user for replication login on security-service.sapsailing.com) +# Or by bearer token, obtained, e.g., through +# curl -d "username=myuser&password=mysecretpassword" "https://security-service.sapsailing.com/security/api/restsecurity/access_token" | jq .access_token +# or by logging in to the security-service.sapsailing.com server with a user having the SERVER:REPLICATE:security-service and SERVER:READ_REPLICATOR:security-service +# permissions, using your web browser and then navigating to +# https://security-service.sapsailing.com/security/api/restsecurity/access_token +REPLICATE_MASTER_BEARER_TOKEN="Gecx+W/dwFKRAxFbIvC/IMafEnJ8kTQF+MlYNVhEwD4=" + +DEPLOY_TO=vsaw +SERVER_NAME=VSAW +MONGODB_URI="mongodb://mongo0.internal.sapsailing.com,mongo1.internal.sapsailing.com/VSAW?replicaSet=live&retryWrites=true" +EXPEDITION_PORT=2015 +SERVER_PORT=8893 +TELNET_PORT=14893 diff --git a/java/com.github.branflake2267.gwt-maps-api/META-INF/MANIFEST.MF b/java/com.github.branflake2267.gwt-maps-api/META-INF/MANIFEST.MF index a6546e4f114..7161c756e54 100644 --- a/java/com.github.branflake2267.gwt-maps-api/META-INF/MANIFEST.MF +++ b/java/com.github.branflake2267.gwt-maps-api/META-INF/MANIFEST.MF @@ -5,8 +5,8 @@ Bundle-SymbolicName: com.github.branflake2267.gwt-maps-api Bundle-Version: 3.10.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy -Require-Bundle: com.google.gwt.user;bundle-version="2.8.2";resolution:=optional, - com.google.gwt.dev;bundle-version="2.8.2";resolution:=optional, +Require-Bundle: com.google.gwt.user;bundle-version="2.9.0";resolution:=optional, + com.google.gwt.dev;bundle-version="2.9.0";resolution:=optional, com.google.gwt.ajaxloader;bundle-version="1.1.0";visibility:=reexport Automatic-Module-Name: com.github.branflake2267.gwt-maps-api Bundle-ClassPath: . diff --git a/java/com.google.gwt.ajaxloader/META-INF/MANIFEST.MF b/java/com.google.gwt.ajaxloader/META-INF/MANIFEST.MF index 26a8ad2bd32..eaa39d7a164 100644 --- a/java/com.google.gwt.ajaxloader/META-INF/MANIFEST.MF +++ b/java/com.google.gwt.ajaxloader/META-INF/MANIFEST.MF @@ -5,8 +5,8 @@ Bundle-SymbolicName: com.google.gwt.ajaxloader Bundle-Version: 1.1.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy -Require-Bundle: com.google.gwt.user;bundle-version="2.8.2";resolution:=optional, - com.google.gwt.dev;bundle-version="2.8.2";resolution:=optional +Require-Bundle: com.google.gwt.user;bundle-version="2.9.0";resolution:=optional, + com.google.gwt.dev;bundle-version="2.9.0";resolution:=optional Automatic-Module-Name: com.google.gwt.ajaxloader Bundle-ClassPath: . Export-Package: com.google.gwt.ajaxloader.client diff --git a/java/com.google.gwt.dev/META-INF/MANIFEST.MF b/java/com.google.gwt.dev/META-INF/MANIFEST.MF index 4f643aae3e5..c98112642a5 100644 --- a/java/com.google.gwt.dev/META-INF/MANIFEST.MF +++ b/java/com.google.gwt.dev/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: gwt-dev Bundle-SymbolicName: com.google.gwt.dev -Bundle-Version: 2.8.2 +Bundle-Version: 2.9.0 Bundle-Vendor: GOOGLE Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ClassPath: lib/gwt-dev.jar, diff --git a/java/com.google.gwt.dev/lib/gwt-dev.jar b/java/com.google.gwt.dev/lib/gwt-dev.jar index 30d16cb740e..8eedc0a980a 100644 Binary files a/java/com.google.gwt.dev/lib/gwt-dev.jar and b/java/com.google.gwt.dev/lib/gwt-dev.jar differ diff --git a/java/com.google.gwt.dev/pom.xml b/java/com.google.gwt.dev/pom.xml index 4f26a246167..6d88f6acbd1 100644 --- a/java/com.google.gwt.dev/pom.xml +++ b/java/com.google.gwt.dev/pom.xml @@ -8,6 +8,6 @@ 1.0.0-SNAPSHOT com.google.gwt.dev - 2.8.2 + 2.9.0 eclipse-plugin diff --git a/java/com.google.gwt.servlet/META-INF/MANIFEST.MF b/java/com.google.gwt.servlet/META-INF/MANIFEST.MF index 6d371319050..1300b8298b0 100644 --- a/java/com.google.gwt.servlet/META-INF/MANIFEST.MF +++ b/java/com.google.gwt.servlet/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: Dev Bundle-SymbolicName: com.google.gwt.servlet Automatic-Module-Name: com.google.gwt.servlet -Bundle-Version: 2.8.2 +Bundle-Version: 2.9.0 Bundle-Vendor: GOOGLE Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ClassPath: lib/gwt-servlet.jar, @@ -174,6 +174,5 @@ Export-Package: com.google.gwt.activity.shared, com.google.web.bindery.requestfactory.vm.impl, com.google.web.bindery.requestfactory.vm.testing, javaemul.internal, - javaemul.internal.annotations, - jsinterop.annotations + javaemul.internal.annotations Require-Bundle: javax.servlet;bundle-version="3.1.0" diff --git a/java/com.google.gwt.servlet/lib/gwt-servlet-deps.jar b/java/com.google.gwt.servlet/lib/gwt-servlet-deps.jar index 430b627cd97..8298757c962 100644 Binary files a/java/com.google.gwt.servlet/lib/gwt-servlet-deps.jar and b/java/com.google.gwt.servlet/lib/gwt-servlet-deps.jar differ diff --git a/java/com.google.gwt.servlet/lib/gwt-servlet.jar b/java/com.google.gwt.servlet/lib/gwt-servlet.jar index eee1e90525c..534920e0089 100644 Binary files a/java/com.google.gwt.servlet/lib/gwt-servlet.jar and b/java/com.google.gwt.servlet/lib/gwt-servlet.jar differ diff --git a/java/com.google.gwt.servlet/pom.xml b/java/com.google.gwt.servlet/pom.xml index e4095b23ea9..984bcca9b30 100644 --- a/java/com.google.gwt.servlet/pom.xml +++ b/java/com.google.gwt.servlet/pom.xml @@ -8,6 +8,6 @@ 1.0.0-SNAPSHOT com.google.gwt.servlet - 2.8.2 + 2.9.0 eclipse-plugin diff --git a/java/com.google.gwt.user/META-INF/MANIFEST.MF b/java/com.google.gwt.user/META-INF/MANIFEST.MF index 54be7d16939..bb88b791928 100755 --- a/java/com.google.gwt.user/META-INF/MANIFEST.MF +++ b/java/com.google.gwt.user/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: gwt-user Bundle-SymbolicName: com.google.gwt.user -Bundle-Version: 2.8.2 +Bundle-Version: 2.9.0 Bundle-Vendor: GOOGLE Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ClassPath: lib/gwt-user.jar, @@ -187,5 +187,5 @@ Export-Package: com.google.gwt.activity.shared, jsinterop.annotations Require-Bundle: javax.servlet;bundle-version="3.1.0", org.junit;bundle-version="4.8.2";resolution:=optional, - com.google.gwt.dev;bundle-version="2.8.2" + com.google.gwt.dev;bundle-version="2.9.0" Automatic-Module-Name: com.google.gwt.user diff --git a/java/com.google.gwt.user/lib/gwt-user.jar b/java/com.google.gwt.user/lib/gwt-user.jar index 4e8f0dedee2..2a261286233 100644 Binary files a/java/com.google.gwt.user/lib/gwt-user.jar and b/java/com.google.gwt.user/lib/gwt-user.jar differ diff --git a/java/com.google.gwt.user/pom.xml b/java/com.google.gwt.user/pom.xml index 1c2a3ce390d..157d55cc188 100644 --- a/java/com.google.gwt.user/pom.xml +++ b/java/com.google.gwt.user/pom.xml @@ -8,6 +8,6 @@ 1.0.0-SNAPSHOT com.google.gwt.user - 2.8.2 + 2.9.0 eclipse-plugin diff --git a/java/com.sap.sailing.dashboards.gwt/META-INF/MANIFEST.MF b/java/com.sap.sailing.dashboards.gwt/META-INF/MANIFEST.MF index de6b585902a..225dc4281e3 100644 --- a/java/com.sap.sailing.dashboards.gwt/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.dashboards.gwt/META-INF/MANIFEST.MF @@ -8,9 +8,9 @@ Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: com.sap.sailing.domain, com.sap.sailing.server.interface, - com.google.gwt.dev;bundle-version="2.8.2";resolution:=optional, - com.google.gwt.user;bundle-version="2.8.2";resolution:=optional, - com.google.gwt.servlet;bundle-version="2.8.2", + com.google.gwt.dev;bundle-version="2.9.0";resolution:=optional, + com.google.gwt.user;bundle-version="2.9.0";resolution:=optional, + com.google.gwt.servlet;bundle-version="2.9.0", com.sap.sse.common, com.sap.sse.debranding, com.sap.sailing.domain.common, diff --git a/java/com.sap.sailing.dashboards.gwt/WEB-INF/web.xml b/java/com.sap.sailing.dashboards.gwt/WEB-INF/web.xml index 48a75890c33..4330f74d6f9 100644 --- a/java/com.sap.sailing.dashboards.gwt/WEB-INF/web.xml +++ b/java/com.sap.sailing.dashboards.gwt/WEB-INF/web.xml @@ -37,6 +37,25 @@ ClientConfigurationServlet *.html + + Sailing ServiceWrite + SailingServiceWrite + com.sap.sailing.gwt.ui.server.SailingServiceWriteImpl + + + SailingServiceWrite + /service/sailingmaster + /service/sailingmaster/* + + + + LocaleInjectionFilter + com.sap.sse.security.ui.server.LocaleInjectionFilter + + + LocaleInjectionFilter + *.html + LocaleInjectionFilter diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/PolarSheetsXYDiagramData.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/PolarSheetsXYDiagramData.java deleted file mode 100644 index cc0513be00b..00000000000 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/PolarSheetsXYDiagramData.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.sap.sailing.domain.common; - -import java.io.Serializable; -import java.util.List; - -import com.sap.sse.common.Util.Pair; - -public interface PolarSheetsXYDiagramData extends Serializable { - - List> getPointsForAverageSpeedRegression(Tack tack, LegType legType); - -} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatDTO.java index fa069b1b2dd..284c67e5aaa 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/BoatDTO.java @@ -57,6 +57,10 @@ public class BoatDTO extends NamedSecuredObjectDTO implements WithID, Serializab return boatClass; } + public void setBoatClass(BoatClassDTO boatClass) { + this.boatClass = boatClass; + } + public String getDisplayName() { final StringBuilder sb = new StringBuilder(); final boolean hasSailId = sailId != null && !sailId.isEmpty(); diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PairingListTemplateDTO.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PairingListTemplateDTO.java index 1e1d46cd10e..b5ae22df4b2 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PairingListTemplateDTO.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/dto/PairingListTemplateDTO.java @@ -1,6 +1,10 @@ package com.sap.sailing.domain.common.dto; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import com.sap.sse.common.Util; public class PairingListTemplateDTO implements Serializable { @@ -15,7 +19,7 @@ public class PairingListTemplateDTO implements Serializable { private int[][] pairingListTemplate; private double quality; private double boatAssignmentQuality; - private Iterable selectedFlightNames; + private List selectedFlightNames; public PairingListTemplateDTO() { } @@ -50,7 +54,8 @@ public class PairingListTemplateDTO implements Serializable { this.boatAssignmentQuality = boatAssigmentQuality; this.quality = quality; this.pairingListTemplate = pairingListTemplate; - this.selectedFlightNames = selectedFlightNames; + this.selectedFlightNames = new ArrayList<>(); + Util.addAll(selectedFlightNames, this.selectedFlightNames); } public void setFlightCount(int flightCount) { @@ -69,7 +74,7 @@ public class PairingListTemplateDTO implements Serializable { this.boatChangeFactor = tolerance; } - public void setSelectedFlightNames(Iterable selectedFlightNames) { + public void setSelectedFlightNames(List selectedFlightNames) { this.selectedFlightNames = selectedFlightNames; } @@ -109,7 +114,7 @@ public class PairingListTemplateDTO implements Serializable { return boatChangeFactor; } - public Iterable getSelectedFlightNames() { + public List getSelectedFlightNames() { return selectedFlightNames; } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/PolarSheetsXYDiagramDataImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/PolarSheetsXYDiagramDataImpl.java deleted file mode 100644 index 89326f27c70..00000000000 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/PolarSheetsXYDiagramDataImpl.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.sap.sailing.domain.common.impl; - -import java.util.List; -import java.util.Map; - -import com.sap.sailing.domain.common.LegType; -import com.sap.sailing.domain.common.PolarSheetsXYDiagramData; -import com.sap.sailing.domain.common.Tack; -import com.sap.sse.common.Util.Pair; - -public class PolarSheetsXYDiagramDataImpl implements PolarSheetsXYDiagramData { - - private static final long serialVersionUID = 778667444303004468L; - - PolarSheetsXYDiagramDataImpl() { - } - - private Map, List>> pointsForAverageSpeedRegression; - - public PolarSheetsXYDiagramDataImpl( - Map, List>> regressionSpeedDataLists) { - pointsForAverageSpeedRegression = regressionSpeedDataLists; - } - - @Override - public List> getPointsForAverageSpeedRegression(Tack tack, LegType legType) { - return pointsForAverageSpeedRegression.get(new Pair(legType, tack)); - } -} diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/orc/ORCCertificate.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/orc/ORCCertificate.java index 8806dcb4163..38efd901d32 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/orc/ORCCertificate.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/orc/ORCCertificate.java @@ -117,7 +117,7 @@ public interface ORCCertificate extends WithID, Serializable { * The different division intervals are - in contrast to the intervals of the GPH - set by the Offshore Race Committee and not by the national association for a uniform handling. * The higher the value, the higher the overall performance, it is measured in meters. */ - double getCDL(); + Double getCDL(); /** * Returns the LOA (length over all) of the {@link Competitor} boat which this certificate belongs to. diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/orc/impl/ORCCertificateImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/orc/impl/ORCCertificateImpl.java index 0bc9a4a5e96..4ec187b5788 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/orc/impl/ORCCertificateImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/orc/impl/ORCCertificateImpl.java @@ -252,7 +252,7 @@ public class ORCCertificateImpl implements ORCCertificate { } @Override - public double getCDL() { + public Double getCDL() { return cdl; } diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.java index 18b9dbf7a11..bd99bf9c5e8 100755 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/tracking/impl/FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.java @@ -16,6 +16,7 @@ public class FlatSmartphoneUuidAndGPSFixMovingJsonSerializer { public static final String LON_DEG = "longitude"; public static final String LAT_DEG = "latitude"; public static final String TIME_MILLIS = "timestamp"; + public static final String TIME_ISO = "timestamp-iso"; public static final String SPEED_M_PER_S = "speed"; public static final String BEARING_DEG = "course"; } diff --git a/java/com.sap.sailing.domain.deckmanadapter/src/com/sap/sailing/domain/deckmanadapter/Record.java b/java/com.sap.sailing.domain.deckmanadapter/src/com/sap/sailing/domain/deckmanadapter/Record.java index 5895d489f7b..1f1e20afc4f 100755 --- a/java/com.sap.sailing.domain.deckmanadapter/src/com/sap/sailing/domain/deckmanadapter/Record.java +++ b/java/com.sap.sailing.domain.deckmanadapter/src/com/sap/sailing/domain/deckmanadapter/Record.java @@ -3,6 +3,7 @@ package com.sap.sailing.domain.deckmanadapter; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.Date; import java.util.Map; import com.sap.sailing.domain.common.Position; @@ -37,7 +38,11 @@ public class Record implements Timed, Positioned { public Record(Map fieldsAsString) throws ParseException { this.fieldsAsString = fieldsAsString; - timePoint = new MillisecondsTimePoint(dateFormat.parse(this.fieldsAsString.get(FieldType.date))); + final Date date; + synchronized (dateFormat) { + date = dateFormat.parse(this.fieldsAsString.get(FieldType.date)); + } + timePoint = new MillisecondsTimePoint(date); position = new DegreePosition(Double.valueOf(this.fieldsAsString.get(FieldType.latitude)), Double.valueOf(this.fieldsAsString.get(FieldType.longitude))); final SpeedWithBearing speed = new KnotSpeedWithBearingImpl(Double.valueOf(this.fieldsAsString.get(FieldType.sog)), diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java index 05b338aab95..547c8d8decd 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/MongoObjectFactory.java @@ -54,8 +54,6 @@ public interface MongoObjectFactory { */ void removeLeaderboard(String leaderboardName); - void renameLeaderboard(String oldName, String newName); - /** * Stores the group, if it doesn't exist or updates it. Leaderboards in the group, which aren't stored in the * database, will be stored. If the leaderboard group has an {@link LeaderboardGroup#getOverallLeaderboard() overall diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java index 78fbb75d3b2..c7ad70a8a7b 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/DomainObjectFactoryImpl.java @@ -337,10 +337,12 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { } public static TimePoint loadTimePoint(Document object, String fieldName) { - TimePoint result = null; + final TimePoint result; Number timePointAsNumber = (Number) object.get(fieldName); if (timePointAsNumber != null) { result = new MillisecondsTimePoint(timePointAsNumber.longValue()); + } else { + result = null; } return result; } @@ -351,12 +353,15 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { public static TimeRange loadTimeRange(Document object, FieldNames field) { Document timeRangeObj = (Document) object.get(field.name()); + final TimeRange result; if (timeRangeObj == null) { - return null; + result = null; + } else { + TimePoint from = loadTimePoint(timeRangeObj, FieldNames.FROM_MILLIS); + TimePoint to = loadTimePoint(timeRangeObj, FieldNames.TO_MILLIS); + result = new TimeRangeImpl(from, to); } - TimePoint from = loadTimePoint(timeRangeObj, FieldNames.FROM_MILLIS); - TimePoint to = loadTimePoint(timeRangeObj, FieldNames.TO_MILLIS); - return new TimeRangeImpl(from, to); + return result; } /** @@ -585,8 +590,6 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { + " for corresponding regatta leaderboard. Not loading regatta leaderboard."); } else { result = new RegattaLeaderboardImpl(regatta, resultDiscardingRule); - result.setName(leaderboardName); // this will temporarily set the display name; it will be adjusted later if - // a display name is found } return result; } @@ -1165,7 +1168,7 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { UUID id = (UUID) eventDBObject.get(FieldNames.EVENT_ID.name()); TimePoint startDate = loadTimePoint(eventDBObject, FieldNames.EVENT_START_DATE); TimePoint endDate = loadTimePoint(eventDBObject, FieldNames.EVENT_END_DATE); - if (endDate.before(startDate)) { + if (endDate != null && startDate != null && endDate.before(startDate)) { logger.warning("End date "+endDate+" of event "+name+" with ID "+id+" is before its start date "+ startDate+"; adjusting such that end date equals start date."); endDate = startDate; @@ -2631,23 +2634,24 @@ public class DomainObjectFactoryImpl implements DomainObjectFactory { public Collection loadAllCompetitors() { Map competitorsById = new HashMap<>(); MongoCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); - try { final JsonWriterSettings writerSettings = JsonWriterSettings.builder().outputMode(JsonMode.RELAXED).build(); for (Document o : collection.find()) { - JSONObject json = Helpers.toJSONObjectSafe(new JSONParser().parse(o.toJson(writerSettings))); - DynamicCompetitor c = competitorWithBoatRefDeserializer.deserialize(json); - // ensure that in case there should be multiple competitors with equal IDs in the DB - // only one will survive - if (competitorsById.containsKey(c.getId())) { - collection.deleteOne(o); - } else { - competitorsById.put(c.getId(), c); + try { + JSONObject json = Helpers.toJSONObjectSafe(new JSONParser().parse(o.toJson(writerSettings))); + DynamicCompetitor c = competitorWithBoatRefDeserializer.deserialize(json); + // ensure that in case there should be multiple competitors with equal IDs in the DB + // only one will survive + if (competitorsById.containsKey(c.getId())) { + collection.deleteOne(o); + } else { + competitorsById.put(c.getId(), c); + } + } catch (Exception e) { + logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load competitors: "+ + o.toString()); + logger.log(Level.SEVERE, "loadCompetitors", e); } } - } catch (Exception e) { - logger.log(Level.SEVERE, "Error connecting to MongoDB, unable to load competitors."); - logger.log(Level.SEVERE, "loadCompetitors", e); - } return competitorsById.values(); } diff --git a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java index f986b00ca84..d1080b3157e 100644 --- a/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.domain.persistence/src/com/sap/sailing/domain/persistence/impl/MongoObjectFactoryImpl.java @@ -497,14 +497,6 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { leaderboardCollection.deleteOne(query); } - @Override - public void renameLeaderboard(String oldName, String newName) { - MongoCollection leaderboardCollection = database.getCollection(CollectionNames.LEADERBOARDS.name()); - Document query = new Document(FieldNames.LEADERBOARD_NAME.name(), oldName); - Document renameUpdate = new Document("$set", new Document(FieldNames.LEADERBOARD_NAME.name(), newName)); - leaderboardCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).updateOne(query, renameUpdate); - } - @Override public void storeLeaderboardGroup(LeaderboardGroup leaderboardGroup) { MongoCollection leaderboardGroupCollection = database.getCollection(CollectionNames.LEADERBOARD_GROUPS.name()); @@ -1434,8 +1426,8 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { private void storeCompetitorWithoutBoat(Competitor competitor) { MongoCollection collection = database.getCollection(CollectionNames.COMPETITORS.name()); JSONObject json = competitorSerializer.serialize(competitor); - Document query = Document.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toString()); - Document entry = Document.parse(json.toString()); + Document query = Document.parse(CompetitorJsonSerializer.getCompetitorIdQuery(competitor).toJSONString()); + Document entry = Document.parse(json.toJSONString()); collection.withWriteConcern(WriteConcern.ACKNOWLEDGED).replaceOne(query, entry, new UpdateOptions().upsert(true)); } diff --git a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java index f0280bd3dc5..d476f76c453 100644 --- a/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java +++ b/java/com.sap.sailing.domain.racelogtrackingadapter/src/com/sap/sailing/domain/racelogtracking/impl/RaceLogRaceTracker.java @@ -99,7 +99,7 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl { private static final Logger logger = Logger.getLogger(LOGGER_AND_LOGAUTHOR_NAME); private final AbstractLogEventAuthor raceLogEventAuthor = new LogEventAuthorImpl(LOGGER_AND_LOGAUTHOR_NAME, 0); - private final Map, Object> visitors = new HashMap, Object>(); + private final Map, Object> visitors = new HashMap<>(); private final RaceLogConnectivityParams params; private final WindStore windStore; @@ -232,7 +232,6 @@ public class RaceLogRaceTracker extends AbstractRaceTrackerBaseImpl { // into the race log raceLog.add(new RaceLogEndOfTrackingEventImpl(MillisecondsTimePoint.now(), raceLogEventAuthor, raceLog.getCurrentPassId())); } - // remove listeners on logs for (Entry, Object> visitor : visitors.entrySet()) { visitor.getKey().removeListener(visitor.getValue()); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/WeakRaceLogChangedVisitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/WeakRaceLogChangedVisitor.java index 7940e5f8979..6c14291e9e3 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/WeakRaceLogChangedVisitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/race/impl/WeakRaceLogChangedVisitor.java @@ -1,16 +1,9 @@ package com.sap.sailing.domain.abstractlog.race.impl; -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Level; -import java.util.logging.Logger; - import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogChangedListener; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sse.util.WeakReferenceWithCleanerCallback; /** * A listener that unregisters itself from the race log's listeners if its notification target is no longer strongly @@ -23,32 +16,7 @@ import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; * */ public class WeakRaceLogChangedVisitor extends AbstractRaceLogChangedVisitor { - private static final Logger logger = Logger.getLogger(WeakRaceLogChangedVisitor.class.getName()); - private static ReferenceQueue queue = new ReferenceQueue(); - private static Map, WeakRaceLogChangedVisitor> referenceToVisitor = new ConcurrentHashMap, WeakRaceLogChangedVisitor>(); - static { - Thread t = new Thread(WeakRaceLogChangedVisitor.class.getSimpleName() + " weak reference cleaner") { - @Override - public void run() { - while (true) { - try { - Reference ref = queue.remove(); - WeakRaceLogChangedVisitor visitor = referenceToVisitor.remove(ref); - visitor.removeListener(); - } catch (InterruptedException e) { - logger.log(Level.SEVERE, "Error trying to clean weak reference", e); - } catch (Exception e2) { - logger.severe("Shouldn't have gotten here. Continuing..."); - } - } - } - }; - t.setDaemon(true); - t.start(); - } - - private final WeakReference listenerRef; - private final RaceLog removeFromThisRaceLogWhenListenerNoLongerStronglyReferenced; + private final WeakReferenceWithCleanerCallback listenerRef; /** * Remembers from which {@link RaceLog} to {@link RaceLog#removeListener(Object) remove} this visitor as a listener @@ -57,22 +25,14 @@ public class WeakRaceLogChangedVisitor extends AbstractRaceLogChangedVisitor { * has returned. */ public WeakRaceLogChangedVisitor(RaceLog removeFromThisRaceLogWhenListenerNoLongerStronglyReferenced, RaceLogChangedListener listener) { - this.removeFromThisRaceLogWhenListenerNoLongerStronglyReferenced = removeFromThisRaceLogWhenListenerNoLongerStronglyReferenced; - listenerRef = new WeakReference(listener, queue); - referenceToVisitor.put(listenerRef, this); + listenerRef = new WeakReferenceWithCleanerCallback<>(listener, ()->removeFromThisRaceLogWhenListenerNoLongerStronglyReferenced.removeListener(this)); } @Override protected void notifyListenerAboutEventAdded(RaceLogEvent event) { RaceLogChangedListener listener = listenerRef.get(); - if (listener == null) { - removeListener(); - } else { + if (listener != null) { listener.eventAdded(event); } } - - private void removeListener() { - removeFromThisRaceLogWhenListenerNoLongerStronglyReferenced.removeListener(this); - } } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogSetCompetitorTimeOnTimeFactorEvent.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogSetCompetitorTimeOnTimeFactorEvent.java index 31418971e2b..e982beb6066 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogSetCompetitorTimeOnTimeFactorEvent.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/RegattaLogSetCompetitorTimeOnTimeFactorEvent.java @@ -1,5 +1,8 @@ package com.sap.sailing.domain.abstractlog.regatta.events; public interface RegattaLogSetCompetitorTimeOnTimeFactorEvent extends RegattaLogSetCompetitorHandicapInfoEvent { + /** + * @return a {@link Double#isFinite(double) finite} value + */ Double getTimeOnTimeFactor(); } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogSetCompetitorTimeOnTimeFactorEventImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogSetCompetitorTimeOnTimeFactorEventImpl.java index 9c6aa9ecf5d..d549da61794 100755 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogSetCompetitorTimeOnTimeFactorEventImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/events/impl/RegattaLogSetCompetitorTimeOnTimeFactorEventImpl.java @@ -15,6 +15,9 @@ public class RegattaLogSetCompetitorTimeOnTimeFactorEventImpl extends RegattaLog public RegattaLogSetCompetitorTimeOnTimeFactorEventImpl(TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, Competitor competitor, Double timeOnTimeFactor) { super(createdAt, logicalTimePoint, author, pId, competitor); + if (!Double.isFinite(timeOnTimeFactor)) { + throw new IllegalArgumentException("A competitor's time-on-time factor must be a finite number. "+timeOnTimeFactor+" is not."); + } this.timeOnTimeFactor = timeOnTimeFactor; } diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogImpl.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogImpl.java index f67088771d8..ed748492f82 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogImpl.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/abstractlog/regatta/impl/RegattaLogImpl.java @@ -39,9 +39,7 @@ public class RegattaLogImpl extends AbstractLogImpl regattaLogDeviceMarkMappingEvents = new AllEventsOfTypeFinder<>(this, /* only unrevoked */ true, RegattaLogDeviceMappingEvent.class).analyze(); - for (RegattaLogEvent deviceMappingEvent : regattaLogDeviceMarkMappingEvents) { @SuppressWarnings("unchecked") // The list can only contain device mapping events WithID withID = ((RegattaLogDeviceMappingEvent) deviceMappingEvent).getMappedTo(); diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BaseCompetitorChangeListener.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BaseCompetitorChangeListener.java new file mode 100755 index 00000000000..10c083a770d --- /dev/null +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/BaseCompetitorChangeListener.java @@ -0,0 +1,52 @@ +package com.sap.sailing.domain.base; + +import java.net.URI; + +import com.sap.sse.common.Color; +import com.sap.sse.common.Duration; + +/** + * Default implementation of the {@link CompetitorChangeListener} interface with all methods doing nothing by default. + * + * @author Axel Uhl (D043530) + * + */ +public interface BaseCompetitorChangeListener extends CompetitorChangeListener { + @Override + default void nationalityChanged(WithNationality what, Nationality oldNationality, Nationality newNationality) { + } + + @Override + default void colorChanged(Color oldColor, Color newColor) { + } + + @Override + default void nameChanged(String oldName, String newName) { + } + + @Override + default void shortNameChanged(String oldShortName, String newShortName) { + } + + @Override + default void emailChanged(String oldEmail, String newEmail) { + } + + @Override + default void searchTagChanged(String oldSearchTag, String newSearchTag) { + } + + @Override + default void flagImageChanged(URI oldFlagImageURI, URI newFlagImageURI) { + } + + @Override + default void timeOnTimeFactorChanged(Double oldTimeOnTimeFactor, Double newTimeOnTimeFactor) { + } + + @Override + default void timeOnDistanceAllowancePerNauticalMileChanged(Duration oldTimeOnDistanceAllowancePerNauticalMile, + Duration newTimeOnDistanceAllowancePerNauticalMile) { + } + +} diff --git a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java index cadbf6d3a5f..004e58d29d4 100644 --- a/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java +++ b/java/com.sap.sailing.domain.shared.android/src/com/sap/sailing/domain/base/Competitor.java @@ -54,6 +54,7 @@ public interface Competitor extends NamedWithID, IsManagedByCache toRemove = new HashSet(); - RaceDefinition race = regatta.getRaceByName(raceID); - if (race != null) { - toRemove.add(race); - } - for (RaceDefinition raceToRemove : toRemove) { - regatta.removeRace(raceToRemove); - } - if (Util.isEmpty(regatta.getAllRaces())) { - raceIDToRegattaCache.remove(raceID); - } - } - } - @Override public Nationality getOrCreateNationality(String threeLetterIOCCode) { return baseDomainFactory.getOrCreateNationality(threeLetterIOCCode); diff --git a/java/com.sap.sailing.domain.test/resources/orc/03600000HUH.json b/java/com.sap.sailing.domain.test/resources/orc/03600000HUH.json new file mode 100644 index 00000000000..38a3e920af9 --- /dev/null +++ b/java/com.sap.sailing.domain.test/resources/orc/03600000HUH.json @@ -0,0 +1,3 @@ +{"rms":[ +{"NatAuth":"UKR","BIN":"UKR0267_Karina","CertNo":"0267_4","RefNo":"03600000HUH","SailNo":"UKR 267","YachtName":"Karina","Class":"Teliga 89","Builder":"im. L Teligi","Designer":"L. Teliga","Address3":"YC Obolon","C_Type":"CLUB","Family":"ORC","Division":"C","IssueDate":"2020-05-07T11:48:07.143Z","Age_Year":1975,"CrewWT":460,"LOA":8.95,"IMSL":7.354,"Draft":1.562,"MB":3.092,"Dspl_Measurement":3790,"Stability_Index":107.3,"Dynamic_Allowance":0.328,"GPH":725.4,"TMF_Inshore":0.8568,"ILCWA":787.8,"TMF_Offshore":0.849,"OSN":706.7,"CDL":6.694,"TN_Offshore_Low":0.8193,"TN_Offshore_Medium":1.0478,"TN_Offshore_High":1.1557,"TN_Inshore_Low":0.6372,"TN_Inshore_Medium":0.8543,"TN_Inshore_High":0.9652,"TND_Offshore_Low":823.9,"TND_Offshore_Medium":644.2,"TND_Offshore_High":584.1,"TND_Inshore_Low":1059.3,"TND_Inshore_Medium":790.1,"TND_Inshore_High":699.3,"OSN_Jibs":735.4,"TMF_Jibs":0.8158,"Pred_Up_TOD":708.3,"Pred_Down_TOD":650.3,"Pred_Up_TOT":0.8471,"Pred_Down_TOT":0.9227,"Dspl_Sailing":4377,"WSS":18.58,"Area_Main":17.88,"Area_Jib":33.38,"Area_Sym":71.46,"Area_ASym":56.06,"GPH_Jibs":757.5,"GPH_Jibs_TOT":0.7921,"Allowances":{"WindSpeeds":[6,8,10,12,14,16,20],"WindAngles":[52,60,75,90,110,120,135,150],"Beat":[1215.6,1032.2,921.7,859.4,840,835.1,853.2],"Run":[1102.9,886.5,746.4,655.8,596.9,564.7,518.9],"BeatAngle":[42.8,42,42.8,41.4,40.9,40.7,41.8],"GybeAngle":[148,152,150.5,162,180,180,180],"WL":[1159.2,959.4,834.1,757.6,718.4,699.9,686],"CR":[989.5,803.2,704.2,647.7,614.3,594,572.2],"OC":[1153.6,900.2,752.5,666.7,624.4,593.1,543.1],"NS":[1044.7,843.1,734.6,671.9,634.2,611.1,586],"OL":[1116.2,923.6,815.1,753.8,722.7,706.6,697.2],"R52":[796.9,680.2,617.6,591.6,581.2,577.6,579],"R60":[753.3,644.5,598.1,576.8,565.2,560.4,559.4],"R75":[723,622.2,584.2,564,549,537.5,528],"R90":[729.8,623.6,577.4,552.9,539.1,527.4,503.9],"R110":[729.1,608.7,564.9,538.7,516.9,499.7,477.8],"R120":[750.3,617.8,568.6,540.6,515,493.4,466],"R135":[817.4,671.3,588.5,556.1,530.2,505,465.1],"R150":[955.2,767.9,647,584.3,555.6,531.9,487.7]}} +]} \ No newline at end of file diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/orc/TestORCCertificateImporterJSON.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/orc/TestORCCertificateImporterJSON.java index 224447d1736..a8c368b3edd 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/orc/TestORCCertificateImporterJSON.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/orc/TestORCCertificateImporterJSON.java @@ -13,6 +13,11 @@ public class TestORCCertificateImporterJSON extends AbstractORCCertificateImport testSimpleLocalFileRead("GER2019.json", "GER20041179"); } + @Test + public void testReadingJSONWithSpecificBins() throws IOException, ParseException { + testSimpleLocalFileRead("03600000HUH.json", "03600000HUH"); + } + @FailIfNoValidOrcCertificates @Test public void testSimpleOnlineJSONFileRead() throws IOException, ParseException, InterruptedException { diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ConcurrencyTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ConcurrencyTest.java index c7bce133734..14a07367d17 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ConcurrencyTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ConcurrencyTest.java @@ -43,7 +43,7 @@ public class ConcurrencyTest extends OnlineTracTracBasedTest { super.setUp("event_20110815_RCSwedenCu", /* raceId */ "event_20110815_RCSwedenCu-Race8", /* liveUri */ null, - /* storedUri */ tractracTunnel ? new URI("tcp://"+tractracTunnelHost+":"+TracTracConnectionConstants.PORT_TUNNEL_STORED) : new URI("tcp://" + TracTracConnectionConstants.HOST_NAME + ":" + TracTracConnectionConstants.PORT_STORED), + /* storedUri */ new URI("tcp://" + TracTracConnectionConstants.HOST_NAME + ":4401"), new ReceiverType[] { ReceiverType.MARKPASSINGS, ReceiverType.RACECOURSE, ReceiverType.RAWPOSITIONS }); getTrackedRace().recordWind( @@ -72,7 +72,6 @@ public class ConcurrencyTest extends OnlineTracTracBasedTest { long duration = System.nanoTime()-start; logger.info("1 thread: "+duration+"ns"); logger.info("number of approximation points: "+approximation1.size()); - dp = new DouglasPeucker(teamAquaTrack, ThreadPoolUtil.INSTANCE.getDefaultBackgroundTaskThreadPoolExecutor()); start = System.nanoTime(); List approximation2 = dp.approximate(new MeterDistance(3), firstMarkPassing.getTimePoint(), lastMarkPassing.getTimePoint()); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CountryCodeTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CountryCodeTest.java index c0cf5842b3f..43cbe7de298 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CountryCodeTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/CountryCodeTest.java @@ -31,36 +31,36 @@ public class CountryCodeTest { public void convertHTML() throws IOException { InputStream is = Util.class.getResourceAsStream("countrycodes.csv"); assertNotNull(is); - BufferedReader br = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8"))); - String line; List matrix = new LinkedList(); - String[] row = null; - int column = 8; - Pattern p = Pattern.compile("]*> *(<[pP]>)?([^<]*)()? *"); - while ((line=br.readLine()) != null) { - if (line.contains("")) { - assertEquals(8, column); - column = 0; - row = new String[8]; - matrix.add(row); - } else { - if (line.contains("]*> *(<[pP]>)?([^<]*)()? *"); + while ((line = br.readLine()) != null) { + if (line.contains("")) { + assertEquals(8, column); + column = 0; + row = new String[8]; + matrix.add(row); + } else { + if (line.contains(" emptySet(), /* addOverallDetails */ false, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE, /* fillTotalPointsUncorrected */ false); - assertEquals(newName, dtoNew.getName()); + assertEquals(newName, dtoNew.getDisplayName()); } @Test public void testFlexibleLeaderboardDisplayNameChangeInvalidatesCache() throws NoWindException, InterruptedException, ExecutionException { final String name = "My Flexible Leaderboard"; - final String newName = "New Name of Flexible Leaderboard"; final String oldDisplayName = "D1"; final String newDisplayName = "D2"; final TimePoint now = MillisecondsTimePoint.now(); @@ -62,11 +61,6 @@ public class LeaderboardDTOCacheInvalidationTest { /* addOverallDetails */ false, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE, /* fillTotalPointsUncorrected */ false); assertEquals(name, seriesLbDtoBeforeDisplayNameIsSet.getRaceList().iterator().next().getName()); - l.setName(newName); - LeaderboardDTO seriesLbDtoBeforeDisplayNameIsSetAndAfterNameWasChanged = seriesLb.getLeaderboardDTO(now, Collections. emptySet(), - /* addOverallDetails */ false, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE, - /* fillTotalPointsUncorrected */ false); - assertEquals(newName, seriesLbDtoBeforeDisplayNameIsSetAndAfterNameWasChanged.getRaceList().iterator().next().getName()); l.setDisplayName(oldDisplayName); LeaderboardDTO dto = l.getLeaderboardDTO(now, Collections. emptySet(), /* addOverallDetails */ false, /* trackedRegattaRegistry */ null, DomainFactory.INSTANCE, diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java index 42889becb59..7ec56ede3bf 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/OnlineTracTracBasedTest.java @@ -91,7 +91,6 @@ public abstract class OnlineTracTracBasedTest extends AbstractTracTracLiveTest i super(); } - @Before public void setUp() throws Exception { domainFactory = new DomainFactoryImpl(new com.sap.sailing.domain.base.impl.DomainFactoryImpl(DomainFactory.TEST_RACE_LOG_RESOLVER)); diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TracTracIgnoreRandomInParamsURLTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TracTracIgnoreRandomInParamsURLTest.java index dfe9f0b0e7f..c95ecb8f4c0 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TracTracIgnoreRandomInParamsURLTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TracTracIgnoreRandomInParamsURLTest.java @@ -2,6 +2,7 @@ package com.sap.sailing.domain.test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import java.net.MalformedURLException; import java.net.URI; @@ -82,6 +83,6 @@ public class TracTracIgnoreRandomInParamsURLTest { new URI("tcp://event.tractrac.com:4400"), new URI("tcp://event.tractrac.com:4401")); Object id2 = TracTracRaceTrackerImpl.createID(new URL("http://event.tractrac.com/events/event_20150707_erEuropean/clientparams.php?event=event_20150707_erEuropean&race=777b1420-07c1-0132-0cec-60a44ce903c3&random=769909699"), new URI("tcp://event.tractrac.com:4412"), new URI("tcp://event.tractrac.com:4413")); - assertFalse(id1.equals(id2)); + assertTrue(id1.equals(id2)); // with the fix for bug 5308 we now assume that the live and stored URI are insignificant for the tracker ID } } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java index c29f55d2306..cb4eea04899 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/mock/MockedTrackedRace.java @@ -516,12 +516,12 @@ public class MockedTrackedRace implements DynamicTrackedRace { } @Override - public Double getTimeOnTimeFactor(Competitor competitor) { + public Double getTimeOnTimeFactor(Competitor competitor, Optional changeCallback) { return null; } @Override - public Duration getTimeOnDistanceAllowancePerNauticalMile(Competitor competitor) { + public Duration getTimeOnDistanceAllowancePerNauticalMile(Competitor competitor, Optional changeCallback) { return null; } diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/tractrac/JorgesTracTracParallelLoadingTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/tractrac/JorgesTracTracParallelLoadingTest.java index 97c89aaf175..a4faa2a5146 100755 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/tractrac/JorgesTracTracParallelLoadingTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/tractrac/JorgesTracTracParallelLoadingTest.java @@ -111,11 +111,11 @@ public class JorgesTracTracParallelLoadingTest { InputStream is = eventURI.toURL().openStream(); StringBuffer jsonContent = new StringBuffer(); String line = null; - BufferedReader reader = new BufferedReader(new InputStreamReader(is)); - while ((line = reader.readLine()) != null) { - jsonContent.append(line); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(is));) { + while ((line = reader.readLine()) != null) { + jsonContent.append(line); + } } - reader.close(); StringTokenizer it = new StringTokenizer(jsonContent.toString(), ","); while (it.hasMoreElements()) { String item = it.nextElement().toString(); diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java index 67db80c8ba2..2fe78b64931 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java @@ -334,14 +334,6 @@ public interface DomainFactory { */ Iterable getControlsForCourseArea(IEvent tracTracEvent, String tracTracCourseAreaName); - /** - * Since TracAPI 3.6.1 the TracAPI provides a course area name for {@link IRace} objects. Furthermore, the - * {@link IControl} control points can now tell their {@link IControl#getCourseArea() course area}. This allows us - * to fetch the {@link IControlPoint}s for a specific course area, thereby, e.g., restricting the marks of an event - * that we offer to the Race Manager app's course designer to those available on the course area. - */ - Iterable getControlPointsForCourseArea(IEvent tracTracEvent, String tracTracCourseAreaName); - /** * Looks for an {@link IControl} in the {@code candidates} that contains two {@link IControlPoint}s that map to the * {@code first} and {@code second} mark. diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java index 63c90d7fbcc..b499de8dcce 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java @@ -112,7 +112,6 @@ import com.tractrac.model.lib.api.event.IEvent; import com.tractrac.model.lib.api.event.IRace; import com.tractrac.model.lib.api.event.IRaceCompetitor; import com.tractrac.model.lib.api.route.IControl; -import com.tractrac.model.lib.api.route.IControlPoint; import com.tractrac.subscription.lib.api.IEventSubscriber; import com.tractrac.subscription.lib.api.IRaceSubscriber; import com.tractrac.subscription.lib.api.SubscriberInitializationException; @@ -703,15 +702,6 @@ public class DomainFactoryImpl implements DomainFactory { } } - @Override - public Iterable getControlPointsForCourseArea(IEvent tracTracEvent, String tracTracCourseAreaName) { - final Set result = new HashSet<>(); - for (final IControl control : getControlsForCourseArea(tracTracEvent, tracTracCourseAreaName)) { - result.addAll(control.getControlPoints()); - } - return result; - } - @Override public Iterable getControlsForCourseArea(IEvent tracTracEvent, String tracTracCourseAreaName) { final Set result = new HashSet<>(); diff --git a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java index eb87642d3b6..11d7f234250 100755 --- a/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java +++ b/java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracRaceTrackerImpl.java @@ -435,16 +435,20 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl // if regatta is still null, no previous assignment of any of the races in this TracTrac event to a Regatta was // found; // in this case, create a default regatta based on the TracTrac event data - this.regatta = effectiveRegatta == null ? domainFactory.getOrCreateDefaultRegatta( + final Regatta regattaInWhichToTryToRemoveExistingRace = effectiveRegatta == null ? domainFactory.getOrCreateDefaultRegatta( raceLogStore, regattaLogStore, tractracRace, trackedRegattaRegistry) : effectiveRegatta; - trackedRegatta = trackedRegattaRegistry.getOrCreateTrackedRegatta(this.regatta); // removeRace may detach the domain regatta from the domain factory if that // removed the last race; therefore, it's important to getOrCreate the // domain regatta *after* calling removeRace - final RaceDefinition raceDefinition = domainFactory.removeRace(tractracRace.getEvent(), tractracRace, this.regatta, trackedRegattaRegistry); + final RaceDefinition raceDefinition = domainFactory.removeRace(tractracRace.getEvent(), tractracRace, regattaInWhichToTryToRemoveExistingRace, trackedRegattaRegistry); if (raceDefinition != null) { - trackedRegattaRegistry.removeRace(this.regatta, raceDefinition); + trackedRegattaRegistry.removeRace(regattaInWhichToTryToRemoveExistingRace, raceDefinition); } + // Look up / create the Regatta and TrackedRegatta after they may potentially have been removed by the + // removeRace statements above: + this.regatta = effectiveRegatta == null ? domainFactory.getOrCreateDefaultRegatta( + raceLogStore, regattaLogStore, tractracRace, trackedRegattaRegistry) : effectiveRegatta; + trackedRegatta = trackedRegattaRegistry.getOrCreateTrackedRegatta(this.regatta); receivers = new HashSet(); for (Receiver receiver : domainFactory.getUpdateReceivers(getTrackedRegatta(), delayToLiveInMillis, simulator, windStore, this, trackedRegattaRegistry, raceLogResolver, leaderboardGroupResolver, tractracRace, @@ -510,8 +514,11 @@ public class TracTracRaceTrackerImpl extends AbstractRaceTrackerImpl } public static Object createID(URL paramURL, final URI liveURI, final URI storedURI) { - URL paramURLStrippedOfRandomParam = getParamURLStrippedOfRandomParam(paramURL); - return new Util.Triple(paramURLStrippedOfRandomParam, liveURI, storedURI); + // see also bug5380: no longer use liveURI and storedURI as part of the ID; the paramURL + // is sufficient for identifying the race, and differences in live/stored URI can be caused + // by TracTrac providing the same race through several load-balanced server instances that + // serve through different ports. + return getParamURLStrippedOfRandomParam(paramURL); } public static URL getParamURLStrippedOfRandomParam(URL paramURL) { diff --git a/java/com.sap.sailing.domain.windfinderadapter.test/src/com/sap/sailing/domain/windfinderadapter/impl/WindFinderReportParserTest.java b/java/com.sap.sailing.domain.windfinderadapter.test/src/com/sap/sailing/domain/windfinderadapter/impl/WindFinderReportParserTest.java index ccc205ddc77..6822f3d2e8b 100644 --- a/java/com.sap.sailing.domain.windfinderadapter.test/src/com/sap/sailing/domain/windfinderadapter/impl/WindFinderReportParserTest.java +++ b/java/com.sap.sailing.domain.windfinderadapter.test/src/com/sap/sailing/domain/windfinderadapter/impl/WindFinderReportParserTest.java @@ -25,7 +25,7 @@ import com.sap.sse.common.Util; public class WindFinderReportParserTest { private final String TEST_MESSAGE = "[{\"wg\":16,\"wd\":331,\"dtl\":\"2017-11-13T15:16:00+01:00\",\"dtl_s\":\"2017-11-13T15:15:30+01:00\",\"ws\":12,\"at\":7.0},{\"wg\":14,\"wd\":333,\"dtl\":\"2017-11-13T15:32:00+01:00\",\"dtl_s\":\"2017-11-13T15:31:30+01:00\",\"ws\":12,\"at\":7.0},{\"wg\":16,\"wd\":332,\"dtl\":\"2017-11-13T15:40:00+01:00\",\"dtl_s\":\"2017-11-13T15:39:30+01:00\",\"ws\":12,\"at\":7.0}]"; - + @Test public void testReadingOneFix() throws ParseException, NumberFormatException, java.text.ParseException { final JSONArray fullJson = (JSONArray) new JSONParser().parse(TEST_MESSAGE); diff --git a/java/com.sap.sailing.domain.windfinderadapter/src/com/sap/sailing/domain/windfinderadapter/impl/WindFinderReportParser.java b/java/com.sap.sailing.domain.windfinderadapter/src/com/sap/sailing/domain/windfinderadapter/impl/WindFinderReportParser.java index c7bfbe361cf..ffb9f686b70 100644 --- a/java/com.sap.sailing.domain.windfinderadapter/src/com/sap/sailing/domain/windfinderadapter/impl/WindFinderReportParser.java +++ b/java/com.sap.sailing.domain.windfinderadapter/src/com/sap/sailing/domain/windfinderadapter/impl/WindFinderReportParser.java @@ -4,6 +4,7 @@ import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; import org.json.simple.JSONArray; @@ -38,7 +39,11 @@ public class WindFinderReportParser { if (jsonOfSingleMeasurement.get("dtl") != null && jsonOfSingleMeasurement.get("ws") != null && jsonOfSingleMeasurement.get("wd") != null) { - result = new WindImpl(position, new MillisecondsTimePoint(dateFormat.parse(jsonOfSingleMeasurement.get("dtl").toString())), + final Date date; + synchronized (dateFormat) { + date = dateFormat.parse(jsonOfSingleMeasurement.get("dtl").toString()); + } + result = new WindImpl(position, new MillisecondsTimePoint(date), new KnotSpeedWithBearingImpl(Double.parseDouble(jsonOfSingleMeasurement.get("ws").toString()), new DegreeBearingImpl(Double.parseDouble(jsonOfSingleMeasurement.get("wd").toString())).reverse())); } else { diff --git a/java/com.sap.sailing.domain.windfinderadapter/src/com/sap/sailing/domain/windfinderadapter/impl/WindFinderTrackerFactoryImpl.java b/java/com.sap.sailing.domain.windfinderadapter/src/com/sap/sailing/domain/windfinderadapter/impl/WindFinderTrackerFactoryImpl.java index 71cc5c597a7..78cfefcb8d9 100644 --- a/java/com.sap.sailing.domain.windfinderadapter/src/com/sap/sailing/domain/windfinderadapter/impl/WindFinderTrackerFactoryImpl.java +++ b/java/com.sap.sailing.domain.windfinderadapter/src/com/sap/sailing/domain/windfinderadapter/impl/WindFinderTrackerFactoryImpl.java @@ -82,10 +82,12 @@ public class WindFinderTrackerFactoryImpl implements WindFinderTrackerFactory { public WindTracker createWindTracker(DynamicTrackedRegatta trackedRegatta, RaceDefinition race, boolean correctByDeclination, SecurityService optionalSecurityService) throws Exception { final WindTracker result; + // obtain the tracked race before synchronizing on the windTrackerPerRace; otherwise, a deadlock may + // occur. See also https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=5308#c11. + final DynamicTrackedRace trackedRace = trackedRegatta.getTrackedRace(race); synchronized (windTrackerPerRace) { final WindTracker existingWindTrackerForRace = getExistingWindTracker(race); if (existingWindTrackerForRace == null) { - final DynamicTrackedRace trackedRace = trackedRegatta.getTrackedRace(race); result = new WindFinderWindTracker(trackedRace, this); windTrackerPerRace.put(race, result); } else { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java index 059364e40a5..8e45c06379a 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/DomainFactory.java @@ -34,7 +34,6 @@ import com.sap.sailing.domain.tracking.impl.RaceAbortedHandler; import com.sap.sailing.domain.tracking.impl.StartTimeUpdateHandler; import com.sap.sse.common.IsManagedByCache; import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; import com.sap.sse.util.ObjectInputStreamResolvingAgainstCache; import com.sap.sse.util.ObjectInputStreamResolvingAgainstCache.ResolveListener; @@ -107,12 +106,8 @@ public interface DomainFactory extends SharedDomainFactory getCompetitorDTOList(Map competitors); - List getCompetitorDTOList(Iterable competitors); - List getCompetitorDTOList(List> competitors); - TrackedRaceDTO createTrackedRaceDTO(TrackedRace trackedRace); TrackedRaceStatisticsDTO createTrackedRaceStatisticsDTO(TrackedRace trackedRace, Leaderboard leaderboard, RaceColumn raceColumn, diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Series.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Series.java index e4005af4c2a..6929d382d25 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Series.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/Series.java @@ -57,10 +57,6 @@ public interface Series extends SeriesBase { RaceColumnInSeries addRaceColumn(int insertIndex, String raceColumnName, TrackedRegattaRegistry trackedRegattaRegistry); - void moveRaceColumnUp(String raceColumnName); - - void moveRaceColumnDown(String raceColumnName); - void removeRaceColumn(String raceColumnName); /** diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java index bdea08c7918..4d664839d4b 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/DomainFactoryImpl.java @@ -6,7 +6,6 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.logging.Logger; import com.sap.sailing.domain.base.Boat; @@ -79,7 +78,6 @@ import com.sap.sailing.geocoding.ReverseGeocoder; import com.sap.sse.common.Distance; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; -import com.sap.sse.common.Util.Pair; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.util.ObjectInputStreamResolvingAgainstCache; import com.sap.sse.util.ObjectInputStreamResolvingAgainstCache.ResolveListener; @@ -385,15 +383,6 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl getCompetitorDTOList(Map competitors) { - List result = new ArrayList<>(); - for (Entry competitorAndBoatEntry : competitors.entrySet()) { - result.add(convertToCompetitorAndBoatDTO(competitorAndBoatEntry.getKey(), competitorAndBoatEntry.getValue())); - } - return result; - } - @Override public List getCompetitorDTOList(Iterable competitors) { List result = new ArrayList<>(); @@ -403,15 +392,6 @@ public class DomainFactoryImpl extends SharedDomainFactoryImpl getCompetitorDTOList(List> competitors) { - List result = new ArrayList<>(); - for (Pair competitorAndBoat : competitors) { - result.add(convertToCompetitorAndBoatDTO(competitorAndBoat.getA(), competitorAndBoat.getB())); - } - return result; - } - @Override public void addUpdateHandlers(DynamicTrackedRace trackedRace, CourseDesignUpdateHandler courseDesignHandler, StartTimeUpdateHandler startTimeHandler, RaceAbortedHandler raceAbortedHandler, diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java index 856a046c93d..c09c689f197 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/RegattaImpl.java @@ -11,6 +11,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -844,13 +845,13 @@ public class RegattaImpl extends NamedImpl implements Regatta, RaceColumnListene } @Override - public Double getTimeOnTimeFactor(Competitor competitor) { - return regattaLikeHelper.getTimeOnTimeFactor(competitor); + public Double getTimeOnTimeFactor(Competitor competitor, Optional changeCallback) { + return regattaLikeHelper.getTimeOnTimeFactor(competitor, changeCallback); } @Override - public Duration getTimeOnDistanceAllowancePerNauticalMile(Competitor competitor) { - return regattaLikeHelper.getTimeOnDistanceAllowancePerNauticalMile(competitor); + public Duration getTimeOnDistanceAllowancePerNauticalMile(Competitor competitor, Optional changeCallback) { + return regattaLikeHelper.getTimeOnDistanceAllowancePerNauticalMile(competitor, changeCallback); } @Override diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SeriesImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SeriesImpl.java index 2725625ff7a..65f598fdbc0 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SeriesImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/base/impl/SeriesImpl.java @@ -209,57 +209,6 @@ public class SeriesImpl extends RenamableImpl implements Series, RaceColumnListe } } - @Override - public void moveRaceColumnUp(String raceColumnName) { - boolean didFirstColumnChange = false; // if it changes and the series starts scoring with zero, notify the change - // start at second element because first can't be moved up - for (int i=1; iname up. * @param name The name of the column to move. diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumns.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumns.java index a372c6cdf29..66c6c1c03e6 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumns.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/HasRaceColumns.java @@ -17,13 +17,15 @@ public interface HasRaceColumns { * Looks through all {@link #getRaceColumns() race columns} and their {@link RaceColumn#getFleets() fleets} and checks * if {@code trackedRace} is {@link RaceColumn#getTrackedRace(Fleet) linked} to that combination. If such a slot is found * that "slot" is returned by a pair specifying the non-{@code null} {@link RaceColumn} and {@code Fleet} pair. Otherwise, - * {@code null} is returned. + * {@code null} is returned. {@code null} is also returned if {@code trackedRace==null}. */ default Pair getRaceColumnAndFleet(TrackedRace trackedRace) { - for (final RaceColumn raceColumn : getRaceColumns()) { - for (final Fleet fleet : raceColumn.getFleets()) { - if (raceColumn.getTrackedRace(fleet) == trackedRace) { - return new Pair<>(raceColumn, fleet); + if (trackedRace != null) { + for (final RaceColumn raceColumn : getRaceColumns()) { + for (final Fleet fleet : raceColumn.getFleets()) { + if (raceColumn.getTrackedRace(fleet) == trackedRace) { + return new Pair<>(raceColumn, fleet); + } } } } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java index a6828543d29..eed2da720d6 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/LeaderboardCacheManager.java @@ -57,11 +57,6 @@ public class LeaderboardCacheManager { this.leaderboard = leaderboard; } - @Override - public void nameChanged(String oldName, String newName) { - removeFromCache(leaderboard); - } - @Override public void displayNameChanged(String oldDisplayName, String newDisplayName) { removeFromCache(leaderboard); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/RegattaLeaderboard.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/RegattaLeaderboard.java index bda2864f89a..1dea19fac13 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/RegattaLeaderboard.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/RegattaLeaderboard.java @@ -2,8 +2,7 @@ package com.sap.sailing.domain.leaderboard; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.regattalike.LeaderboardThatHasRegattaLike; -import com.sap.sse.common.Renamable; -public interface RegattaLeaderboard extends Renamable, LeaderboardThatHasRegattaLike { +public interface RegattaLeaderboard extends LeaderboardThatHasRegattaLike { Regatta getRegatta(); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java index 40388f606e6..17e29127cf7 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/AbstractLeaderboardWithCache.java @@ -1185,14 +1185,14 @@ public abstract class AbstractLeaderboardWithCache implements Leaderboard { // if trackedLeg is the first leg, compute the gap at the start of this leg; otherwise, compute gap // at the end of the previous leg final TimePoint timePoint = trackedLeg.getStartTime(); - final TrackedLegOfCompetitor tloc; if (course.getFirstWaypoint() == trackedLeg.getLeg().getFrom()) { - tloc = trackedLeg; + result = Duration.NULL; } else { - tloc = trackedLeg.getTrackedLeg().getTrackedRace().getTrackedLegFinishingAt(trackedLeg.getLeg().getFrom()) - .getTrackedLeg(trackedLeg.getCompetitor()); + final TrackedLegOfCompetitor tloc = trackedLeg.getTrackedLeg().getTrackedRace() + .getTrackedLegFinishingAt(trackedLeg.getLeg().getFrom()).getTrackedLeg(trackedLeg.getCompetitor()); + result = trackedLeg.getTrackedLeg().getTrackedRace().getRankingMetric().getLegGapToLegLeaderInOwnTime(tloc, + timePoint, rankingInfo, cache); } - result = trackedLeg.getTrackedLeg().getTrackedRace().getRankingMetric().getLegGapToLegLeaderInOwnTime(tloc, timePoint, rankingInfo, cache); return result; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java index bfd8582f184..5656c0d7856 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/DelegatingRegattaLeaderboardWithCompetitorElimination.java @@ -106,10 +106,6 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr return name; } - public void setName(String newName) { - getFullLeaderboard().setName(newName); - } - @Override public Iterable getCompetitors() { return new ObscuringIterable<>(getFullLeaderboard().getCompetitors(), eliminatedCompetitors.keySet()); @@ -331,8 +327,8 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr @Override public void addScoreCorrectionListener(ScoreCorrectionListener listener) { - if (fullLeaderboard != null) { - fullLeaderboard.addScoreCorrectionListener(listener); + if (getFullLeaderboard() != null) { + getFullLeaderboard().addScoreCorrectionListener(listener); } else { triggerWhenFullLeaderboardIsResolved.put(leaderboard->leaderboard.addScoreCorrectionListener(listener), true); } @@ -340,8 +336,8 @@ public class DelegatingRegattaLeaderboardWithCompetitorElimination extends Abstr @Override public void removeScoreCorrectionListener(ScoreCorrectionListener listener) { - if (fullLeaderboard != null) { - fullLeaderboard.removeScoreCorrectionListener(listener); + if (getFullLeaderboard() != null) { + getFullLeaderboard().removeScoreCorrectionListener(listener); } else { triggerWhenFullLeaderboardIsResolved.put(leaderboard->leaderboard.removeScoreCorrectionListener(listener), true); } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java index 8f1b851d203..d3c821a76ed 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/FlexibleLeaderboardImpl.java @@ -10,7 +10,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.logging.Level; +import java.util.Optional; import java.util.logging.Logger; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; @@ -71,7 +71,7 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements private static final long serialVersionUID = -5708971849158747846L; private final List races; private final ScoringScheme scoringScheme; - private String name; + private final String name; private transient RaceLogStore raceLogStore; /** @@ -154,25 +154,6 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements return name; } - /** - * @param newName must not be null - */ - public void setName(String newName) { - if (newName == null) { - throw new IllegalArgumentException("A leaderboard's name must not be null"); - } - final String oldName = this.name; - this.name = newName; - notifyLeaderboardChangeListeners(listener->{ - try { - listener.nameChanged(oldName, newName); - } catch (Exception e) { - logger.log(Level.WARNING, "Exception trying to notify listener "+listener+" about the name of leaderboard "+ - getName()+" changing from "+oldName+" to "+newName, e); - } - }); - } - @Override public FlexibleRaceColumn addRace(TrackedRace race, String columnName, boolean medalRace) { FlexibleRaceColumn column = addRaceColumn(columnName, medalRace, /* logAlreadyExistingColumn */false); @@ -364,13 +345,13 @@ public class FlexibleLeaderboardImpl extends AbstractLeaderboardImpl implements } @Override - public Double getTimeOnTimeFactor(Competitor competitor) { - return regattaLikeHelper.getTimeOnTimeFactor(competitor); + public Double getTimeOnTimeFactor(Competitor competitor, Optional changeCallback) { + return regattaLikeHelper.getTimeOnTimeFactor(competitor, changeCallback); } @Override - public Duration getTimeOnDistanceAllowancePerNauticalMile(Competitor competitor) { - return regattaLikeHelper.getTimeOnDistanceAllowancePerNauticalMile(competitor); + public Duration getTimeOnDistanceAllowancePerNauticalMile(Competitor competitor, Optional changeCallback) { + return regattaLikeHelper.getTimeOnDistanceAllowancePerNauticalMile(competitor, changeCallback); } private class RaceExecutionOrderCache extends AbstractRaceExecutionOrderProvider { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java index 3b10e05599c..87608a97479 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/impl/RegattaLeaderboardImpl.java @@ -43,14 +43,6 @@ public class RegattaLeaderboardImpl extends AbstractLeaderboardImpl implements R regatta.addRaceColumnListener(this); } - /** - * Updates the display name of this regatta leaderboard so that the regatta's name is no longer used as the default name. - */ - @Override - public void setName(String newName) { - setDisplayName(newName); - } - @Override public Regatta getRegatta() { return regatta; diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java index 8487efbf144..d56ee747e92 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/leaderboard/meta/MetaLeaderboardColumn.java @@ -326,18 +326,6 @@ public class MetaLeaderboardColumn extends SimpleAbstractRaceColumn implements R public void disableCompetitorRegistrationOnRaceLog(Fleet fleetByName) { } - /** - * When the leaderboard name changes, notify this to this object's {@link RaceColumnListener}s as a - * change of this race column's name, but only if no {@link Leaderboard#getDisplayName() display name} - * is set because that would take precedence over the regular name. - */ - @Override - public void nameChanged(String oldName, String newName) { - if (leaderboard.getDisplayName() == null) { - getRaceColumnListeners().notifyListenersAboutRaceColumnNameChanged(this, oldName, newName); - } - } - /** * When the leaderboard display name changes, notify this to this object's {@link RaceColumnListener}s as a * change of this race column's name diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCCertificatesCollectionJSON.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCCertificatesCollectionJSON.java index fd1451eab32..a2d08c5f41d 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCCertificatesCollectionJSON.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCCertificatesCollectionJSON.java @@ -63,6 +63,7 @@ public class ORCCertificatesCollectionJSON extends AbstractORCCertificatesCollec private static final String CIRCULAR_RANDOM = "CR"; private static final String NON_SPINNAKER = "NS"; private static final String WIND_SPEEDS = "WindSpeeds"; + private static final String WIND_ANGLES = "WindAngles"; /** * Pattern to recognize a true wind angle in the allowances section. Group 1 contains @@ -137,7 +138,7 @@ public class ORCCertificatesCollectionJSON extends AbstractORCCertificatesCollec sailNumber = entry.getValue() == null ? null : entry.getValue().toString(); break; case LOA: - length = new MeterDistance(((Number) entry.getValue()).doubleValue()); + length = entry.getValue() == null ? null : new MeterDistance(((Number) entry.getValue()).doubleValue()); break; case YACHT_NAME: boatName = entry.getValue() == null ? null : entry.getValue().toString(); @@ -146,17 +147,17 @@ public class ORCCertificatesCollectionJSON extends AbstractORCCertificatesCollec boatclass = (String) entry.getValue(); break; case GPH2: - gph = new SecondsDurationImpl(((Number) entry.getValue()).doubleValue()); + gph = entry.getValue() == null ? null : new SecondsDurationImpl(((Number) entry.getValue()).doubleValue()); break; case CDL2: - cdl = ((Number) entry.getValue()).doubleValue(); + cdl = entry.getValue() == null ? null : ((Number) entry.getValue()).doubleValue(); break; case ISSUE_DATE: Date date = DatatypeConverter.parseDateTime((String) entry.getValue()).getTime(); issueDate = new MillisecondsTimePoint(date); break; case ALLOWANCES: - final JSONObject allowances = (JSONObject) object.get(ALLOWANCES); + final JSONObject allowances = (JSONObject) entry.getValue(); // calculating the TWA and TWS before calculating the other dependent values in allowances object final Object windSpeedsObject = allowances.get(WIND_SPEEDS); if (windSpeedsObject != null) { @@ -189,27 +190,28 @@ public class ORCCertificatesCollectionJSON extends AbstractORCCertificatesCollec } // Now read the various allowances, assuming we find values for the TWS "bins" identified above for (final Object aKey : allowances.keySet()) { - final JSONArray array = (JSONArray) allowances.get(aKey); + final JSONArray twaArray = (JSONArray) allowances.get(aKey); if (((String) aKey).equals(BEAT_ANGLE)) { - for (int i = 0; i < array.size(); i++) { + for (int i = 0; i < twaArray.size(); i++) { beatAngles.put(new KnotSpeedImpl(trueWindSpeedArray[i]), - new DegreeBearingImpl(((Number) array.get(i)).doubleValue())); + new DegreeBearingImpl(((Number) twaArray.get(i)).doubleValue())); } continue; } if (((String) aKey).equals(GYBE_ANGLE)) { - for (int i = 0; i < array.size(); i++) { + for (int i = 0; i < twaArray.size(); i++) { gybeAngles.put(new KnotSpeedImpl(trueWindSpeedArray[i]), - new DegreeBearingImpl(((Number) array.get(i)).doubleValue())); + new DegreeBearingImpl(((Number) twaArray.get(i)).doubleValue())); } continue; } Map twsMap = new HashMap<>(); // ignore true wind angles key - if (!twaPattern.matcher((String) aKey).lookingAt()) { - for (int i = 0; i < array.size(); i++) { + if (!aKey.equals(WIND_SPEEDS) && !aKey.equals(WIND_ANGLES) && + !twaPattern.matcher((String) aKey).lookingAt()) { + for (int i = 0; i < twaArray.size(); i++) { twsMap.put(new KnotSpeedImpl(trueWindSpeedArray[i]), - new SecondsDurationImpl(((Number) array.get(i)).doubleValue())); + new SecondsDurationImpl(((Number) twaArray.get(i)).doubleValue())); } } switch ((String) aKey) { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCCertificatesCollectionRMS.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCCertificatesCollectionRMS.java index 304acf1f811..1efe6acff84 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCCertificatesCollectionRMS.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/orc/impl/ORCCertificatesCollectionRMS.java @@ -128,7 +128,9 @@ public class ORCCertificatesCollectionRMS extends AbstractORCCertificatesCollect String timeString = certificateValues.getValue(ISSUETIME); TimePoint issueDate; try { - issueDate = new MillisecondsTimePoint(timestampFormat.parse(dateString+" "+timeString+"+0000")); // assume UTC + synchronized (timestampFormat) { + issueDate = new MillisecondsTimePoint(timestampFormat.parse(dateString+" "+timeString+"+0000")); // assume UTC + } } catch (ParseException e) { issueDate = null; } diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/TimeOnTimeAndDistanceRankingMetric.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/TimeOnTimeAndDistanceRankingMetric.java index 7a186a65851..4bd1b96fcc3 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/TimeOnTimeAndDistanceRankingMetric.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/ranking/TimeOnTimeAndDistanceRankingMetric.java @@ -3,6 +3,9 @@ package com.sap.sailing.domain.ranking; import java.util.Comparator; import java.util.HashMap; import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; import java.util.function.Supplier; import com.sap.sailing.domain.base.Competitor; @@ -21,6 +24,7 @@ import com.sap.sse.common.Distance; import com.sap.sse.common.Duration; import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.MillisecondsDurationImpl; +import com.sap.sse.util.WeakReferenceWithCleanerCallback; /** * The basic concept of this ranking metric is to compare corrected reciproke VMG/VMC (measured in seconds per nautical @@ -54,6 +58,30 @@ public class TimeOnTimeAndDistanceRankingMetric extends NonPerformanceCurveRanki private final TimeOnDistanceAllowancePerNauticalMileMap timeOnDistanceFactorNauticalMile; + private final ConcurrentHashMap timeOnTimeFactorCache; + + /** + * For each value obtained and stored in {@link #timeOnTimeFactorCache}, an update callback is registered + * that is triggered when the time-on-time factor for that competitor may have changed. It is important to + * strongly reference these callbacks here to tie their object life cycle to that of this ranking metric. + * When this ranking metric becomes eligible for garbage collection then so do these callback objects. + * When used together with a {@link WeakReferenceWithCleanerCallback}, any listener / observer relations + * can be terminated at that point. + */ + private final ConcurrentHashMap timeOnTimeFactorCacheUpdateCallbacks; + + private final ConcurrentHashMap timeOnDistanceFactorInSecondsPerNauticalMileCache; + + /** + * For each value obtained and stored in {@link #timeOnTimeFactorCache}, an update callback is registered + * that is triggered when the time-on-time factor for that competitor may have changed. It is important to + * strongly reference these callbacks here to tie their object life cycle to that of this ranking metric. + * When this ranking metric becomes eligible for garbage collection then so do these callback objects. + * When used together with a {@link WeakReferenceWithCleanerCallback}, any listener / observer relations + * can be terminated at that point. + */ + private final ConcurrentHashMap timeOnDistanceFactorInSecondsPerNauticalMileCacheUpdateCallbacks; + /** * The regular constructor that can also be used as TimeOnTimeAndDistanceRankingMetric::new * to obtain a {@link RankingMetricConstructor} implementation. It uses the {@link TrackedRace}'s regatta @@ -61,10 +89,10 @@ public class TimeOnTimeAndDistanceRankingMetric extends NonPerformanceCurveRanki */ public TimeOnTimeAndDistanceRankingMetric(final TrackedRace trackedRace) { this(trackedRace, - c -> trackedRace.getTrackedRegatta().getRegatta().getTimeOnTimeFactor(c), - c -> trackedRace.getTrackedRegatta().getRegatta().getTimeOnDistanceAllowancePerNauticalMile(c)); + (TimeOnTimeAndDistanceRankingMetric totadrm)->(Competitor c) -> trackedRace.getTrackedRegatta().getRegatta().getTimeOnTimeFactor(c, Optional.of(totadrm.getTimeOnTimeFactorCacheUpdateCallback(c))), + (TimeOnTimeAndDistanceRankingMetric totadrm)->(Competitor c) -> trackedRace.getTrackedRegatta().getRegatta().getTimeOnDistanceAllowancePerNauticalMile(c, Optional.of(totadrm.getTimeOnDistanceAllowanceCacheUpdateCallback(c)))); } - + /** * Mostly to simplify testing; instead of obtaining the handicap numbers through the {@link TrackedRace} and * its regatta, handicap mappings can be passed directly and overrule anything defined for the competitor or @@ -72,11 +100,36 @@ public class TimeOnTimeAndDistanceRankingMetric extends NonPerformanceCurveRanki */ public TimeOnTimeAndDistanceRankingMetric(final TrackedRace trackedRace, TimeOnTimeFactorMapping timeOnTimeFactor, TimeOnDistanceAllowancePerNauticalMileMap timeOnDistanceFactorInSecondsPerNauticalMile) { - super(trackedRace); - this.timeOnTimeFactor = timeOnTimeFactor; - this.timeOnDistanceFactorNauticalMile = timeOnDistanceFactorInSecondsPerNauticalMile; + this(trackedRace, + // don't need the "this" pointer here; simply ignoring and passing through the functions provided as parameters + (TimeOnTimeAndDistanceRankingMetric totadrm)->timeOnTimeFactor, + (TimeOnTimeAndDistanceRankingMetric totadrm)->timeOnDistanceFactorInSecondsPerNauticalMile); } - + + private TimeOnTimeAndDistanceRankingMetric(final TrackedRace trackedRace, + Function timeOnTimeFactorMappingFunction, + Function timeOnDistanceFactorInSecondsPerNauticalMileFunction) { + super(trackedRace); + this.timeOnTimeFactor = timeOnTimeFactorMappingFunction.apply(this); + this.timeOnDistanceFactorNauticalMile = timeOnDistanceFactorInSecondsPerNauticalMileFunction.apply(this); + timeOnTimeFactorCache = new ConcurrentHashMap<>(); + timeOnDistanceFactorInSecondsPerNauticalMileCache = new ConcurrentHashMap<>(); + timeOnTimeFactorCacheUpdateCallbacks = new ConcurrentHashMap<>(); + timeOnDistanceFactorInSecondsPerNauticalMileCacheUpdateCallbacks = new ConcurrentHashMap<>(); + } + + private Runnable getTimeOnTimeFactorCacheUpdateCallback(Competitor competitor) { + final Runnable result = ()->timeOnTimeFactorCache.remove(competitor); + timeOnTimeFactorCacheUpdateCallbacks.put(competitor, result); + return result; + } + + private Runnable getTimeOnDistanceAllowanceCacheUpdateCallback(Competitor competitor) { + final Runnable result = ()->timeOnDistanceFactorInSecondsPerNauticalMileCache.remove(competitor); + timeOnDistanceFactorInSecondsPerNauticalMileCacheUpdateCallbacks.put(competitor, result); + return result; + } + @Override public RankingMetrics getType() { return RankingMetrics.TIME_ON_TIME_AND_DISTANCE; @@ -185,11 +238,11 @@ public class TimeOnTimeAndDistanceRankingMetric extends NonPerformanceCurveRanki } double getTimeOnTimeFactor(Competitor competitor) { - return timeOnTimeFactor.apply(competitor); + return timeOnTimeFactorCache.computeIfAbsent(competitor, timeOnTimeFactor); } Duration getTimeOnDistanceFactorInSecondsPerNauticalMile(Competitor competitor) { - return timeOnDistanceFactorNauticalMile.apply(competitor); + return timeOnDistanceFactorInSecondsPerNauticalMileCache.computeIfAbsent(competitor, timeOnDistanceFactorNauticalMile); } @Override diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/BaseRegattaLikeImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/BaseRegattaLikeImpl.java index 47afe1d0d68..b8811708269 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/BaseRegattaLikeImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/BaseRegattaLikeImpl.java @@ -2,18 +2,29 @@ package com.sap.sailing.domain.regattalike; import java.io.IOException; import java.io.ObjectInputStream; +import java.lang.ref.WeakReference; import java.util.HashSet; +import java.util.Optional; import java.util.Set; +import java.util.logging.Logger; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRevokeEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorHandicapInfoEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogSetCompetitorTimeOnTimeFactorEvent; +import com.sap.sailing.domain.abstractlog.regatta.impl.BaseRegattaLogEventVisitor; import com.sap.sailing.domain.abstractlog.regatta.impl.CompetitorTimeOnDistanceAllowancePerNauticalMileFinder; import com.sap.sailing.domain.abstractlog.regatta.impl.CompetitorTimeOnTimeFactorFinder; import com.sap.sailing.domain.abstractlog.regatta.impl.RegattaLogEventListener; +import com.sap.sailing.domain.base.BaseCompetitorChangeListener; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.common.CompetitorRegistrationType; import com.sap.sailing.domain.regattalog.RegattaLogStore; import com.sap.sse.common.Duration; +import com.sap.sse.common.Util; +import com.sap.sse.util.WeakReferenceWithCleanerCallback; public abstract class BaseRegattaLikeImpl implements IsRegattaLike { private static final long serialVersionUID = -5629172342837950344L; @@ -77,9 +88,229 @@ public abstract class BaseRegattaLikeImpl implements IsRegattaLike { listeners = new HashSet<>(); regattaLog.addListener(new RegattaLogEventForwarder(identifier)); } + + /** + * Registers a competitor change listener that watches a {@link Competitor} for changes for a specific competitor. + * If such a change is observed, a {@link Runnable} callback can be invoked by subclass implementations. The + * reference to the {@link Runnable} callback passed to the constructor is implemented as a {@link WeakReference + * weak reference}, therefore not keeping the callback from getting garbage collected. Conversely, when the callback + * becomes eligible for garbage collection, and hence the weak reference is cleared and enqueued, this object will + * remove itself as listener from the {@link Competitor} and hence no garbage will be left behind. + *

+ * + * It is therefore a good idea to couple the {@link Runnable} callback's object life cycle to that of the object it + * will cater to when it receives the updates, for example by introducing a strong reference from the actual + * receiver of the update to the {@link Runnable} or using the actual update receiver as the callback by having its + * type implement the {@link Runnable} interface. + *

+ * + * @author Axel Uhl (D043530) + * + */ + private abstract static class CompetitorHandicapValueChangeListener implements BaseCompetitorChangeListener { + private static final long serialVersionUID = -7462757662510693195L; + private final WeakReferenceWithCleanerCallback callback; + + public CompetitorHandicapValueChangeListener(Runnable callback, Competitor competitor) { + competitor.addCompetitorChangeListener(this); + this.callback = new WeakReferenceWithCleanerCallback(callback, ()->{ + // unregister this listener from the regatta log when the callback is no longer strongly reachable: + competitor.removeCompetitorChangeListener(this); + }); + } + + protected void tryToNotifyCallback() { + final Runnable theCallback = callback.get(); + if (theCallback != null) { + theCallback.run(); + } + } + } + + /** + * Registers a competitor change listener that watches a {@link Competitor} for time-on-time factor changes for a specific + * competitor. If such a change is observed, a {@link Runnable} callback is invoked. The reference + * to the {@link Runnable} callback passed to the constructor is implemented as a {@link WeakReference weak reference}, + * therefore not keeping the callback from getting garbage collected. Conversely, when the callback becomes eligible for + * garbage collection, and hence the weak reference is cleared and enqueued, this object will remove itself as listener + * from the {@link Competitor} and hence no garbage will be left behind.

+ * + * It is therefore a good idea to couple the {@link Runnable} callback's object life cycle to that of the object it will + * cater to when it receives the updates, for example by introducing a strong reference from the actual receiver of the + * update to the {@link Runnable} or using the actual update receiver as the callback by having its type implement the + * {@link Runnable} interface.

+ * + * @author Axel Uhl (D043530) + * + */ + private static class CompetitorTimeOnTimeFactorChangeListener extends CompetitorHandicapValueChangeListener { + private static final long serialVersionUID = -7462757662510693195L; + + public CompetitorTimeOnTimeFactorChangeListener(Runnable callback, Competitor competitor) { + super(callback, competitor); + } + + @Override + public void timeOnTimeFactorChanged(Double oldTimeOnTimeFactor, Double newTimeOnTimeFactor) { + if (!Util.equalsWithNull(oldTimeOnTimeFactor, newTimeOnTimeFactor)) { + tryToNotifyCallback(); + } + } + } + + /** + * Registers a competitor change listener that watches a {@link Competitor} for time-on-time factor changes for a specific + * competitor. If such a change is observed, a {@link Runnable} callback is invoked. The reference + * to the {@link Runnable} callback passed to the constructor is implemented as a {@link WeakReference weak reference}, + * therefore not keeping the callback from getting garbage collected. Conversely, when the callback becomes eligible for + * garbage collection, and hence the weak reference is cleared and enqueued, this object will remove itself as listener + * from the {@link Competitor} and hence no garbage will be left behind.

+ * + * It is therefore a good idea to couple the {@link Runnable} callback's object life cycle to that of the object it will + * cater to when it receives the updates, for example by introducing a strong reference from the actual receiver of the + * update to the {@link Runnable} or using the actual update receiver as the callback by having its type implement the + * {@link Runnable} interface.

+ * + * @author Axel Uhl (D043530) + * + */ + private static class CompetitorTimeOnDistanceFactorChangeListener extends CompetitorHandicapValueChangeListener { + private static final long serialVersionUID = -7462757662510693195L; + + public CompetitorTimeOnDistanceFactorChangeListener(Runnable callback, Competitor competitor) { + super(callback, competitor); + } + + @Override + public void timeOnDistanceAllowancePerNauticalMileChanged(Duration oldTimeOnDistanceAllowancePerNauticalMile, + Duration newTimeOnDistanceAllowancePerNauticalMile) { + if (!Util.equalsWithNull(oldTimeOnDistanceAllowancePerNauticalMile, newTimeOnDistanceAllowancePerNauticalMile)) { + tryToNotifyCallback(); + } + } + } + + /** + * Registers a regatta log change listener that watches a {@link RegattaLog} for handicap value changes for a specific + * competitor. If such events (or their revocation) are observed, a {@link Runnable} callback is invoked. The reference + * to the {@link Runnable} callback passed to the constructor is implemented as a {@link WeakReference weak reference}, + * therefore not keeping the callback from getting garbage collected. Conversely, when the callback becomes eligible for + * garbage collection, and hence the weak reference is cleared and enqueued, this object will remove itself as listener + * from the {@link RegattaLog} and hence no garbage will be left behind.

+ * + * It is therefore a good idea to couple the {@link Runnable} callback's object life cycle to that of the object it will + * cater to when it receives the updates, for example by introducing a strong reference from the actual receiver of the + * update to the {@link Runnable} or using the actual update receiver as the callback by having its type implement the + * {@link Runnable} interface.

+ * + * @author Axel Uhl (D043530) + * + */ + private static class RegattaLogCompetitorHandicapValueChangeListener extends BaseRegattaLogEventVisitor { + private static final Logger logger = Logger + .getLogger(BaseRegattaLikeImpl.RegattaLogCompetitorTimeOnTimeFactorChangeListener.class.getName()); + + private final WeakReferenceWithCleanerCallback callback; + protected final Competitor competitorToLookFor; + private final RegattaLog logToObserve; + private final Class regattaLogEventClass; + + public RegattaLogCompetitorHandicapValueChangeListener(Runnable callback, RegattaLog logToObserve, Competitor competitorToLookFor, + Class regattaLogEventClass) { + this.logToObserve = logToObserve; + this.regattaLogEventClass = regattaLogEventClass; + logToObserve.addListener(this); + this.callback = new WeakReferenceWithCleanerCallback(callback, ()->{ + // unregister this listener from the regatta log when the callback is no longer strongly reachable: + logToObserve.removeListener(this); + }); + this.competitorToLookFor = competitorToLookFor; + } + + @Override + public void visit(RegattaLogRevokeEvent event) { + final RegattaLogEvent revokedEvent = logToObserve.getEventById(event.getRevokedEventId()); + if (revokedEvent == null) { + logger.warning("Unable to find revoked event with ID "+event.getRevokedEventId()); + } else if (regattaLogEventClass.isInstance(revokedEvent) && + ((RegattaLogSetCompetitorHandicapInfoEvent) revokedEvent).getCompetitor() == competitorToLookFor) { + tryToNotifyCallback(); + } + } + + protected void tryToNotifyCallback() { + final Runnable theCallback = callback.get(); + if (theCallback != null) { + theCallback.run(); + } + } + } + + /** + * Registers a regatta log change listener that watches a {@link RegattaLog} for time-on-time factor changes for a specific + * competitor. If such events (or their revocation) is observed, a {@link Runnable} callback is invoked. The reference + * to the {@link Runnable} callback passed to the constructor is implemented as a {@link WeakReference weak reference}, + * therefore not keeping the callback from getting garbage collected. Conversely, when the callback becomes eligible for + * garbage collection, and hence the weak reference is cleared and enqueued, this object will remove itself as listener + * from the {@link RegattaLog} and hence no garbage will be left behind.

+ * + * It is therefore a good idea to couple the {@link Runnable} callback's object life cycle to that of the object it will + * cater to when it receives the updates, for example by introducing a strong reference from the actual receiver of the + * update to the {@link Runnable} or using the actual update receiver as the callback by having its type implement the + * {@link Runnable} interface.

+ * + * @author Axel Uhl (D043530) + * + */ + private static class RegattaLogCompetitorTimeOnTimeFactorChangeListener extends RegattaLogCompetitorHandicapValueChangeListener { + public RegattaLogCompetitorTimeOnTimeFactorChangeListener(Runnable callback, RegattaLog logToObserve, Competitor competitorToLookFor) { + super(callback, logToObserve, competitorToLookFor, RegattaLogSetCompetitorTimeOnTimeFactorEvent.class); + } + + @Override + public void visit(RegattaLogSetCompetitorTimeOnTimeFactorEvent event) { + if (event.getCompetitor() == competitorToLookFor) { + tryToNotifyCallback(); + } + } + } + + /** + * Registers a regatta log change listener that watches a {@link RegattaLog} for time-on-distance allowance changes for a specific + * competitor. If such events (or their revocation) is observed, a {@link Runnable} callback is invoked. The reference + * to the {@link Runnable} callback passed to the constructor is implemented as a {@link WeakReference weak reference}, + * therefore not keeping the callback from getting garbage collected. Conversely, when the callback becomes eligible for + * garbage collection, and hence the weak reference is cleared and enqueued, this object will remove itself as listener + * from the {@link RegattaLog} and hence no garbage will be left behind.

+ * + * It is therefore a good idea to couple the {@link Runnable} callback's object life cycle to that of the object it will + * cater to when it receives the updates, for example by introducing a strong reference from the actual receiver of the + * update to the {@link Runnable} or using the actual update receiver as the callback by having its type implement the + * {@link Runnable} interface.

+ * + * TODO factor such that most of this can also be used for the ToT stuff... + * + * @author Axel Uhl (D043530) + * + */ + private static class RegattaLogCompetitorTimeOnDistanceAllowanceChangeListener extends RegattaLogCompetitorHandicapValueChangeListener { + public RegattaLogCompetitorTimeOnDistanceAllowanceChangeListener(Runnable callback, RegattaLog logToObserve, Competitor competitorToLookFor) { + super(callback, logToObserve, competitorToLookFor, RegattaLogSetCompetitorTimeOnTimeFactorEvent.class); + } + + @Override + public void visit(RegattaLogSetCompetitorTimeOnDistanceAllowancePerNauticalMileEvent event) { + if (event.getCompetitor() == competitorToLookFor) { + tryToNotifyCallback(); + } + } + } + @Override - public Double getTimeOnTimeFactor(Competitor competitor) { + public Double getTimeOnTimeFactor(Competitor competitor, Optional changeCallback) { + changeCallback.ifPresent(callback->new RegattaLogCompetitorTimeOnTimeFactorChangeListener(callback, getRegattaLog(), competitor)); + changeCallback.ifPresent(callback->new CompetitorTimeOnTimeFactorChangeListener(callback, competitor)); final Double timeOnTimeFactorFromRegattaLog = getTimeOnTimeFactorFromRegattaLog(competitor); final Double result; if (timeOnTimeFactorFromRegattaLog == null) { @@ -96,7 +327,9 @@ public abstract class BaseRegattaLikeImpl implements IsRegattaLike { } @Override - public Duration getTimeOnDistanceAllowancePerNauticalMile(Competitor competitor) { + public Duration getTimeOnDistanceAllowancePerNauticalMile(Competitor competitor, Optional changeCallback) { + changeCallback.ifPresent(callback->new RegattaLogCompetitorTimeOnDistanceAllowanceChangeListener(callback, getRegattaLog(), competitor)); + changeCallback.ifPresent(callback->new CompetitorTimeOnDistanceFactorChangeListener(callback, competitor)); final Duration timeOnDistanceAllowancePerNauticalMileFromRegattaLog = getTimeOnDistanceAllowancePerNauticalMileFromRegattaLog(competitor); final Duration result; if (timeOnDistanceAllowancePerNauticalMileFromRegattaLog == null) { diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/IsRegattaLike.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/IsRegattaLike.java index 806de03b76b..c81c90a1afd 100644 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/IsRegattaLike.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/regattalike/IsRegattaLike.java @@ -1,6 +1,7 @@ package com.sap.sailing.domain.regattalike; import java.io.Serializable; +import java.util.Optional; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.base.Competitor; @@ -59,17 +60,24 @@ public interface IsRegattaLike extends Serializable { * regatta log}, accommodating for the fact that in between regattas competitors may get a new, different rating, * resulting in different handicaps for different regattas. * - * @see #getTimeOnDistanceAllowancePerNauticalMile(Competitor) + * @param changeCallback + * an optional callback listener that will be {@link Runnable#run() invoked} when the + * {@code competitor}'s time-on-time factor changes for any reason. Only a weak reference will be + * established to the {@link Runnable} so that if the callback or the objects it references become + * eligible for garbage collection then any registration that is made internally in order to satisfy the + * callback will automatically be cleared. + * + * @see #getTimeOnDistanceAllowancePerNauticalMile(Competitor, Optional) */ - Double getTimeOnTimeFactor(Competitor competitor); + Double getTimeOnTimeFactor(Competitor competitor, Optional changeCallback); /** * The time-on-distance time allowance for the competitor, used in handicap regattas. If * null, no time-on-distance allowance is defined for the competitor. For a simple * time-on-distance scheme, the factor is multiplied with the (windward) course length and the result is subtracted * from the actual time sailed to obtain the corrected time. For a "performance line" system, the actual time sailed - * will be multiplied with the {@link #getTimeOnTimeFactor(Competitor) time-on-time factor} before subtracting the - * time-on-distance allowance. + * will be multiplied with the {@link #getTimeOnTimeFactor(Competitor, Optional) time-on-time factor} before + * subtracting the time-on-distance allowance. *

* * The default allowance is obtained from the {@link Competitor#getTimeOnDistanceAllowancePerNauticalMile() @@ -77,9 +85,16 @@ public interface IsRegattaLike extends Serializable { * its {@link #getRegattaLog() regatta log}, accommodating for the fact that in between regattas competitors may get * a new, different rating, resulting in different handicaps for different regattas. * - * @see #getTimeOnTimeFactor(Competitor) + * @param changeCallback + * an optional callback listener that will be {@link Runnable#run() invoked} when the + * {@code competitor}'s time-on-distance allowance changes for any reason. Only a weak reference will be + * established to the {@link Runnable} so that if the callback or the objects it references become + * eligible for garbage collection then any registration that is made internally in order to satisfy the + * callback will automatically be cleared. + * + * @see #getTimeOnTimeFactor(Competitor, Optional) */ - Duration getTimeOnDistanceAllowancePerNauticalMile(Competitor competitor); + Duration getTimeOnDistanceAllowancePerNauticalMile(Competitor competitor, Optional changeCallback); void setFleetsCanRunInParallelToTrue(); } \ No newline at end of file diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java index 903edfe5587..bd42a6bd811 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/TrackedLegOfCompetitor.java @@ -262,17 +262,26 @@ public interface TrackedLegOfCompetitor extends Serializable { /** * Computes the distance along the wind track to the wind-projected position of the race's overall leader. If leader * and competitor are in the same leg, this is simply the windward distance. If the leader is already one or more - * legs ahead, it's the competitor's winward distance to go plus the windward distance between the marks of all legs - * that the leader completed after this competitor's leg plus the windard distance between the leader and the + * legs ahead, it's the competitor's windward distance to go plus the windward distance between the marks of all + * legs that the leader completed after this competitor's leg plus the windward distance between the leader and the * leader's leg's start. *

* * If the leg is neither an {@link LegType#UPWIND upwind} nor a {@link LegType#DOWNWIND downwind} leg, the geometric * distance between this leg's competitor and the leader is returned. Note that this can lead to a situation where - * the distance to leader is unrelated to the {@link #getWindwardDistanceToGo(TimePoint, WindPositionMode) distance to go} which is - * used for ranking. + * the distance to leader is unrelated to the {@link #getWindwardDistanceToGo(TimePoint, WindPositionMode) distance + * to go} which is used for ranking. + *

* - * @param rankingInfo materialized ranking information that is pre-calculated to avoid expensive redundant work + * If at {@code timePoint} the {@link #getCompetitor() competitor} is not yet sailing in the {@link #getLeg() leg}, + * {@code null} will result. If at {@code timePoint} the {@link #getCompetitor() competitor} has already finished the + * {@link #getLeg() leg}, the time point at which the competitor finished the leg is used as basis for the calculation + * instead of {@code timePoint}. In particular, the leader is then determined for that finishing time point, and the + * leader's position is determined for that finishing time point, too. This way, the result will---apart from any + * out of order fix deliveries or course changes---remain constant for any later time point. + * + * @param rankingInfo + * materialized ranking information that is pre-calculated to avoid expensive redundant work */ Distance getWindwardDistanceToCompetitorFarthestAhead(TimePoint timePoint, WindPositionMode windPositionMode, RankingInfo rankingInfo); diff --git a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegOfCompetitorImpl.java b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegOfCompetitorImpl.java index d58586bc9ee..f68e77fbc56 100755 --- a/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegOfCompetitorImpl.java +++ b/java/com.sap.sailing.domain/src/com/sap/sailing/domain/tracking/impl/TrackedLegOfCompetitorImpl.java @@ -17,7 +17,6 @@ import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.SpeedWithBearing; import com.sap.sailing.domain.common.Wind; import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; -import com.sap.sailing.domain.common.impl.MeterDistance; import com.sap.sailing.domain.common.tracking.BravoFix; import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuseCache; @@ -460,55 +459,71 @@ public class TrackedLegOfCompetitorImpl implements TrackedLegOfCompetitor { @Override public Distance getWindwardDistanceToCompetitorFarthestAhead(TimePoint timePoint, WindPositionMode windPositionMode, final RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { - // FIXME bug 607 it seems the following fetches the leader of this leg, not the overall leader; validate!!! Use getTrackedRace().getRanks() instead - Competitor competitorFarthestAhead = rankingInfo.getCompetitorFarthestAhead(); - TrackedLegOfCompetitor leaderLeg = getTrackedRace().getCurrentLeg(competitorFarthestAhead, timePoint); + assert rankingInfo.getTimePoint().equals(timePoint); // the ranking info must be for timePoint Distance result = null; - Position leaderPosition = getTrackedRace().getTrack(competitorFarthestAhead).getEstimatedPosition(timePoint, /* extrapolate */ false); - Position currentPosition = getTrackedRace().getTrack(getCompetitor()).getEstimatedPosition(timePoint, /* extrapolate */ false); - if (leaderPosition != null && currentPosition != null) { - result = Distance.NULL; - boolean foundCompetitorsLeg = false; - getTrackedRace().getRace().getCourse().lockForRead(); - try { - for (Leg leg : getTrackedRace().getRace().getCourse().getLegs()) { - if (leg == getLeg()) { - foundCompetitorsLeg = true; - } - if (foundCompetitorsLeg) { - // if the leaderLeg is null, the leader has already arrived - if (leaderLeg == null || leg != leaderLeg.getLeg()) { - // add distance to next mark - Position nextMarkPosition = getTrackedRace().getApproximatePosition(leg.getTo(), timePoint); - if (nextMarkPosition == null) { - result = null; - break; - } else { - Distance distanceToNextMark = getTrackedRace().getTrackedLeg(leg) - .getAbsoluteWindwardDistance(currentPosition, nextMarkPosition, timePoint, windPositionMode, cache); - if (distanceToNextMark != null) { - result = new MeterDistance(result.getMeters() + distanceToNextMark.getMeters()); - } else { + final TimePoint competitorLegStartTime = getStartTime(); + if (competitorLegStartTime != null && !timePoint.before(competitorLegStartTime)) { + // only deliver a result if the competitor has started the leg at or before timePoint + final TimePoint competitorLegFinishTime = getFinishTime(); + final TimePoint effectiveTimePoint; + final RankingInfo effectiveRankingInfo; + if (competitorLegFinishTime != null && timePoint.after(competitorLegFinishTime)) { + // the competitor finished the leg before timePoint; use the finishing time point for all calculations, + // including determining who is farthest ahead at that point in time: + effectiveTimePoint = competitorLegFinishTime; + effectiveRankingInfo = getTrackedRace().getRankingMetric().getRankingInfo(effectiveTimePoint); + } else { + effectiveTimePoint = timePoint; + effectiveRankingInfo = rankingInfo; + } + final Competitor competitorFarthestAhead = effectiveRankingInfo.getCompetitorFarthestAhead(); + final TrackedLegOfCompetitor leaderLeg = getTrackedRace().getCurrentLeg(competitorFarthestAhead, effectiveTimePoint); + Position leaderPosition = getTrackedRace().getTrack(competitorFarthestAhead).getEstimatedPosition(effectiveTimePoint, /* extrapolate */ false); + Position currentPosition = getTrackedRace().getTrack(getCompetitor()).getEstimatedPosition(effectiveTimePoint, /* extrapolate */ false); + if (leaderPosition != null && currentPosition != null) { + result = Distance.NULL; + boolean foundCompetitorsLeg = false; + getTrackedRace().getRace().getCourse().lockForRead(); + try { + for (Leg leg : getTrackedRace().getRace().getCourse().getLegs()) { + if (leg == getLeg()) { + foundCompetitorsLeg = true; + } + if (foundCompetitorsLeg) { + // if the leaderLeg is null, the leader has already arrived + if (leaderLeg == null || leg != leaderLeg.getLeg()) { + // add distance to next mark + Position nextMarkPosition = getTrackedRace().getApproximatePosition(leg.getTo(), effectiveTimePoint); + if (nextMarkPosition == null) { result = null; break; + } else { + Distance distanceToNextMark = getTrackedRace().getTrackedLeg(leg) + .getAbsoluteWindwardDistance(currentPosition, nextMarkPosition, effectiveTimePoint, windPositionMode, cache); + if (distanceToNextMark != null) { + result = result.add(distanceToNextMark); + } else { + result = null; + break; + } } - } - currentPosition = nextMarkPosition; - } else { - // we're now in the same leg with leader; compute windward distance to leader - final Distance absoluteWindwardDistance = getTrackedRace().getTrackedLeg(leg) - .getAbsoluteWindwardDistance(currentPosition, leaderPosition, timePoint, windPositionMode, cache); - if (absoluteWindwardDistance != null) { - result = new MeterDistance(result.getMeters() + absoluteWindwardDistance.getMeters()); + currentPosition = nextMarkPosition; } else { - result = null; + // we're now in the same leg with leader; compute windward distance to leader + final Distance absoluteWindwardDistance = getTrackedRace().getTrackedLeg(leg) + .getAbsoluteWindwardDistance(currentPosition, leaderPosition, effectiveTimePoint, windPositionMode, cache); + if (absoluteWindwardDistance != null) { + result = result.add(absoluteWindwardDistance); + } else { + result = null; + } + break; } - break; } } + } finally { + getTrackedRace().getRace().getCourse().unlockAfterRead(); } - } finally { - getTrackedRace().getRace().getCourse().unlockAfterRead(); } } return result; diff --git a/java/com.sap.sailing.expeditionconnector.common/META-INF/MANIFEST.MF b/java/com.sap.sailing.expeditionconnector.common/META-INF/MANIFEST.MF index d5046d17411..cd9737a7655 100755 --- a/java/com.sap.sailing.expeditionconnector.common/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.expeditionconnector.common/META-INF/MANIFEST.MF @@ -12,4 +12,5 @@ Require-Bundle: com.sap.sse.gwt, Automatic-Module-Name: com.sap.sailing.expeditionconnector.common Import-Package: com.sap.sse, com.sap.sse.security.shared, + com.sap.sse.security.shared.dto, com.sap.sse.security.shared.impl diff --git a/java/com.sap.sailing.expeditionconnector.common/src/com/sap/sailing/expeditionconnector/ExpeditionDeviceConfiguration.java b/java/com.sap.sailing.expeditionconnector.common/src/com/sap/sailing/expeditionconnector/ExpeditionDeviceConfiguration.java index c00c7b23a3b..7b7e040e9ac 100755 --- a/java/com.sap.sailing.expeditionconnector.common/src/com/sap/sailing/expeditionconnector/ExpeditionDeviceConfiguration.java +++ b/java/com.sap.sailing.expeditionconnector.common/src/com/sap/sailing/expeditionconnector/ExpeditionDeviceConfiguration.java @@ -1,16 +1,21 @@ package com.sap.sailing.expeditionconnector; -import java.io.Serializable; import java.util.UUID; import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sse.common.impl.NamedImpl; import com.sap.sse.security.shared.HasPermissions; +import com.sap.sse.security.shared.QualifiedObjectIdentifier; import com.sap.sse.security.shared.TypeRelativeObjectIdentifier; +import com.sap.sse.security.shared.dto.AccessControlListDTO; +import com.sap.sse.security.shared.dto.OwnershipDTO; +import com.sap.sse.security.shared.dto.SecuredDTO; +import com.sap.sse.security.shared.dto.SecurityInformationDTO; -public class ExpeditionDeviceConfiguration extends NamedImpl implements Serializable { +public class ExpeditionDeviceConfiguration extends NamedImpl implements SecuredDTO { private static final long serialVersionUID = -7819154195403387909L; + private SecurityInformationDTO securityInformation = new SecurityInformationDTO(); private final UUID deviceUuid; /** @@ -76,19 +81,41 @@ public class ExpeditionDeviceConfiguration extends NamedImpl implements Serializ + ", getName()=" + getName() + "]"; } - /** - * Get TypeRelativeObjectIdentifer. Needs a parameter for the servername passed as a String parameter. - * - */ - public TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier(String serverName) { - return getTypeRelativeObjectIdentifier(serverName, getName()); - } - - public static TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier(String serverName, String name) { - return new TypeRelativeObjectIdentifier(serverName, name); - } - public HasPermissions getType() { return SecuredDomainType.EXPEDITION_DEVICE_CONFIGURATION; } + + @Override + public QualifiedObjectIdentifier getIdentifier() { + return getPermissionType().getQualifiedObjectIdentifier(getTypeRelativeObjectIdentifier()); + } + + @Override + public HasPermissions getPermissionType() { + return SecuredDomainType.EXPEDITION_DEVICE_CONFIGURATION; + } + + public TypeRelativeObjectIdentifier getTypeRelativeObjectIdentifier() { + return new TypeRelativeObjectIdentifier(getDeviceUuid().toString()); + } + + @Override + public final AccessControlListDTO getAccessControlList() { + return securityInformation.getAccessControlList(); + } + + @Override + public final OwnershipDTO getOwnership() { + return securityInformation.getOwnership(); + } + + @Override + public final void setAccessControlList(final AccessControlListDTO accessControlList) { + this.securityInformation.setAccessControlList(accessControlList); + } + + @Override + public final void setOwnership(final OwnershipDTO ownership) { + this.securityInformation.setOwnership(ownership); + } } diff --git a/java/com.sap.sailing.expeditionconnector.persistence/src/com/sap/sailing/expeditionconnector/persistence/MongoObjectFactory.java b/java/com.sap.sailing.expeditionconnector.persistence/src/com/sap/sailing/expeditionconnector/persistence/MongoObjectFactory.java index e4cfecac400..70949885784 100755 --- a/java/com.sap.sailing.expeditionconnector.persistence/src/com/sap/sailing/expeditionconnector/persistence/MongoObjectFactory.java +++ b/java/com.sap.sailing.expeditionconnector.persistence/src/com/sap/sailing/expeditionconnector/persistence/MongoObjectFactory.java @@ -1,9 +1,11 @@ package com.sap.sailing.expeditionconnector.persistence; +import java.util.UUID; + import com.sap.sailing.expeditionconnector.ExpeditionDeviceConfiguration; public interface MongoObjectFactory { void storeExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration expeditionDeviceConfiguration); - void removeExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration expeditionDeviceConfiguration); + void removeExpeditionDeviceConfiguration(UUID expeditionDeviceConfigurationId); } diff --git a/java/com.sap.sailing.expeditionconnector.persistence/src/com/sap/sailing/expeditionconnector/persistence/impl/MongoObjectFactoryImpl.java b/java/com.sap.sailing.expeditionconnector.persistence/src/com/sap/sailing/expeditionconnector/persistence/impl/MongoObjectFactoryImpl.java index 2ba176a5701..60884cde612 100755 --- a/java/com.sap.sailing.expeditionconnector.persistence/src/com/sap/sailing/expeditionconnector/persistence/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sailing.expeditionconnector.persistence/src/com/sap/sailing/expeditionconnector/persistence/impl/MongoObjectFactoryImpl.java @@ -1,5 +1,6 @@ package com.sap.sailing.expeditionconnector.persistence.impl; +import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; @@ -25,14 +26,14 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { expeditionDeviceConfigurationsCollection.createIndex(index, new IndexOptions().name("uuidindex").unique(true).background(false)); } - private Document getExpeditionDeviceConfigurationDBKey(ExpeditionDeviceConfiguration expeditionDeviceConfiguration) { - final Document basicDBObject = new Document(FieldNames.EXPEDITION_DEVICE_CONFIGURATION_UUID.name(), expeditionDeviceConfiguration.getDeviceUuid()); + private Document getExpeditionDeviceConfigurationDBKey(UUID expeditionDeviceConfigurationId) { + final Document basicDBObject = new Document(FieldNames.EXPEDITION_DEVICE_CONFIGURATION_UUID.name(), expeditionDeviceConfigurationId); return basicDBObject; } @Override public void storeExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration expeditionDeviceConfiguration) { - final Document key = getExpeditionDeviceConfigurationDBKey(expeditionDeviceConfiguration); + final Document key = getExpeditionDeviceConfigurationDBKey(expeditionDeviceConfiguration.getDeviceUuid()); final Document expeditionDeviceConfigurationDBObject = new Document(); expeditionDeviceConfigurationDBObject.put(FieldNames.EXPEDITION_DEVICE_CONFIGURATION_UUID.name(), expeditionDeviceConfiguration.getDeviceUuid()); expeditionDeviceConfigurationDBObject.put(FieldNames.EXPEDITION_DEVICE_CONFIGURATION_NAME.name(), expeditionDeviceConfiguration.getName()); @@ -56,7 +57,7 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { } @Override - public void removeExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration expeditionDeviceConfiguration) { - expeditionDeviceConfigurationsCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).deleteOne(getExpeditionDeviceConfigurationDBKey(expeditionDeviceConfiguration)); + public void removeExpeditionDeviceConfiguration(UUID expeditionDeviceConfigurationId) { + expeditionDeviceConfigurationsCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).deleteOne(getExpeditionDeviceConfigurationDBKey(expeditionDeviceConfigurationId)); } } diff --git a/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/ExpeditionTrackerFactory.java b/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/ExpeditionTrackerFactory.java index 4a2d801b019..683506256e6 100755 --- a/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/ExpeditionTrackerFactory.java +++ b/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/ExpeditionTrackerFactory.java @@ -211,7 +211,7 @@ public class ExpeditionTrackerFactory implements WindTrackerFactory, DeviceRegis private void addOrReplaceDeviceConfigurationNoPersistence(ExpeditionDeviceConfiguration deviceConfiguration) { if (deviceConfiguration.getExpeditionBoatId() != null && devicesPerBoatId.containsKey(deviceConfiguration.getExpeditionBoatId()) && - !devicesPerBoatId.get(deviceConfiguration.getExpeditionBoatId()).equals(deviceConfiguration)) { + !devicesPerBoatId.get(deviceConfiguration.getExpeditionBoatId()).getDeviceUuid().equals(deviceConfiguration.getDeviceUuid())) { throw new IllegalStateException("Trying to create an ambiguous Expedition Boat ID mapping: established is "+ devicesPerBoatId.get(deviceConfiguration.getExpeditionBoatId()) + " and boat ID #"+deviceConfiguration.getExpeditionBoatId()+" therefore cannot be mapped to "+deviceConfiguration+ @@ -226,12 +226,12 @@ public class ExpeditionTrackerFactory implements WindTrackerFactory, DeviceRegis } } - public void removeDeviceConfiguration(ExpeditionDeviceConfiguration deviceConfiguration) { - deviceConfigurations.remove(deviceConfiguration.getDeviceUuid()); - if (deviceConfiguration.getExpeditionBoatId() != null) { + public void removeDeviceConfiguration(UUID deviceConfigurationId) { + final ExpeditionDeviceConfiguration deviceConfiguration = deviceConfigurations.remove(deviceConfigurationId); + if (deviceConfiguration != null && deviceConfiguration.getExpeditionBoatId() != null) { devicesPerBoatId.remove(deviceConfiguration.getExpeditionBoatId()); } - mongoObjectFactory.removeExpeditionDeviceConfiguration(deviceConfiguration); + mongoObjectFactory.removeExpeditionDeviceConfiguration(deviceConfigurationId); } @Override diff --git a/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/impl/Activator.java b/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/impl/Activator.java index 2e15435808b..b1e18a7b580 100755 --- a/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/impl/Activator.java +++ b/java/com.sap.sailing.expeditionconnector/src/com/sap/sailing/expeditionconnector/impl/Activator.java @@ -25,12 +25,9 @@ import com.sap.sailing.expeditionconnector.persistence.ExpeditionGpsDeviceIdenti import com.sap.sailing.expeditionconnector.persistence.MongoObjectFactory; import com.sap.sailing.expeditionconnector.persistence.PersistenceFactory; import com.sap.sailing.server.gateway.serialization.racelog.tracking.DeviceIdentifierJsonHandler; -import com.sap.sse.ServerInfo; import com.sap.sse.common.TypeBasedServiceFinder; import com.sap.sse.replication.FullyInitializedReplicableTracker; import com.sap.sse.security.SecurityService; -import com.sap.sse.security.shared.QualifiedObjectIdentifier; -import com.sap.sse.security.shared.impl.WildcardPermissionEncoder; import com.sap.sse.util.impl.ThreadFactoryWithPriority; public class Activator implements BundleActivator { @@ -83,22 +80,16 @@ public class Activator implements BundleActivator { /* sensorFixStore will be discovered by tracker factory through OSGi */ null, domainObjectFactory, mongoObjectFactory); registrations.add(context.registerService(ExpeditionTrackerFactory.class, expeditionTrackerFactory, /* properties */null)); registrations.add(context.registerService(WindTrackerFactory.class, expeditionTrackerFactory, /* properties */null)); - registrations.add(context.registerService(DeviceIdentifierJsonHandler.class, new ExpeditionGpsDeviceIdentifierJsonHandler(), getDict(ExpeditionGpsDeviceIdentifier.TYPE))); registrations.add(context.registerService(DeviceIdentifierStringSerializationHandler.class, new ExpeditionGpsStringSerializationHandler(), getDict(ExpeditionGpsDeviceIdentifier.TYPE))); registrations.add(context.registerService(DeviceIdentifierJsonHandler.class, new ExpeditionSensorDeviceIdentifierJsonHandler(), getDict(ExpeditionSensorDeviceIdentifier.TYPE))); registrations.add(context.registerService(DeviceIdentifierStringSerializationHandler.class, new ExpeditionSensorStringSerializationHandler(), getDict(ExpeditionSensorDeviceIdentifier.TYPE))); - new Thread(() -> { final FullyInitializedReplicableTracker securityServiceServiceTracker = FullyInitializedReplicableTracker.createAndOpen(context, SecurityService.class); try { final SecurityService securityService = securityServiceServiceTracker.getInitializedService(0); - final WildcardPermissionEncoder permissionEncoder = new WildcardPermissionEncoder(); - for (ExpeditionDeviceConfiguration deviceConfiguration : expeditionTrackerFactory - .getDeviceConfigurations()) { - QualifiedObjectIdentifier identifier = deviceConfiguration.getType().getQualifiedObjectIdentifier(deviceConfiguration.getTypeRelativeObjectIdentifier(ServerInfo.getName())); - securityService.migrateOwnership(identifier, permissionEncoder.decodePermissionPart( - deviceConfiguration.getTypeRelativeObjectIdentifier(ServerInfo.getName()).toString())); + for (final ExpeditionDeviceConfiguration deviceConfiguration : expeditionTrackerFactory.getDeviceConfigurations()) { + securityService.migrateOwnership(deviceConfiguration); } securityService .assumeOwnershipMigrated(SecuredDomainType.EXPEDITION_DEVICE_CONFIGURATION.getName()); diff --git a/java/com.sap.sailing.gwt.ui.test/.classpath b/java/com.sap.sailing.gwt.ui.test/.classpath deleted file mode 100644 index 2ce79594a4d..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/.classpath +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/java/com.sap.sailing.gwt.ui.test/.gitignore b/java/com.sap.sailing.gwt.ui.test/.gitignore deleted file mode 100755 index cca910ac7ad..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -bin -war -gwt-unitCache -www-test diff --git a/java/com.sap.sailing.gwt.ui.test/.project b/java/com.sap.sailing.gwt.ui.test/.project deleted file mode 100755 index 1b5fe668904..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/.project +++ /dev/null @@ -1,39 +0,0 @@ - - - com.sap.sailing.gwt.ui.test - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.pde.ManifestBuilder - - - - - org.eclipse.pde.SchemaBuilder - - - - - com.gwtplugins.gdt.eclipse.core.webAppProjectValidator - - - - - com.gwtplugins.gwt.eclipse.core.gwtProjectValidator - - - - - - org.eclipse.pde.PluginNature - org.eclipse.jdt.core.javanature - com.gwtplugins.gwt.eclipse.core.gwtNature - - diff --git a/java/com.sap.sailing.gwt.ui.test/.settings/com.gwtplugins.gdt.eclipse.core.prefs b/java/com.sap.sailing.gwt.ui.test/.settings/com.gwtplugins.gdt.eclipse.core.prefs deleted file mode 100644 index 8f0b83a4967..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/.settings/com.gwtplugins.gdt.eclipse.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -eclipse.preferences.version=1 -jarsExcludedFromWebInfLib= -warSrcDir= -warSrcDirIsOutput=true diff --git a/java/com.sap.sailing.gwt.ui.test/.settings/com.gwtplugins.gwt.eclipse.core.prefs b/java/com.sap.sailing.gwt.ui.test/.settings/com.gwtplugins.gwt.eclipse.core.prefs deleted file mode 100644 index fb32c70cc69..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/.settings/com.gwtplugins.gwt.eclipse.core.prefs +++ /dev/null @@ -1,3 +0,0 @@ -eclipse.preferences.version=1 -entryPointModules= -filesCopiedToWebInfLib= diff --git a/java/com.sap.sailing.gwt.ui.test/.settings/org.eclipse.jdt.core.prefs b/java/com.sap.sailing.gwt.ui.test/.settings/org.eclipse.jdt.core.prefs deleted file mode 100755 index 0c68a61dca8..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,7 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/java/com.sap.sailing.gwt.ui.test/.settings/org.eclipse.pde.core.prefs b/java/com.sap.sailing.gwt.ui.test/.settings/org.eclipse.pde.core.prefs deleted file mode 100755 index 87782a3a8b4..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/.settings/org.eclipse.pde.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -#Wed Nov 02 13:57:42 CET 2011 -eclipse.preferences.version=1 -pluginProject.extensions=false -resolve.requirebundle=false diff --git a/java/com.sap.sailing.gwt.ui.test/GwtTestCases (no proxy).launch b/java/com.sap.sailing.gwt.ui.test/GwtTestCases (no proxy).launch deleted file mode 100644 index 0b40ba801c7..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/GwtTestCases (no proxy).launch +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/java/com.sap.sailing.gwt.ui.test/GwtTestCases (proxy).launch b/java/com.sap.sailing.gwt.ui.test/GwtTestCases (proxy).launch deleted file mode 100644 index 89f049af085..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/GwtTestCases (proxy).launch +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/java/com.sap.sailing.gwt.ui.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.gwt.ui.test/META-INF/MANIFEST.MF deleted file mode 100644 index 20f49f0b52c..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/META-INF/MANIFEST.MF +++ /dev/null @@ -1,31 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Test -Bundle-SymbolicName: com.sap.sailing.gwt.ui.test -Bundle-Version: 1.0.0.qualifier -Bundle-Vendor: SAP -Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Fragment-Host: com.sap.sailing.gwt.ui -Require-Bundle: com.sap.sailing.server, - com.sap.sailing.expeditionconnector, - org.mockito.mockito-core;bundle-version="1.9.5", - org.objenesis;bundle-version="1.3.0", - org.hamcrest;bundle-version="1.1.0", - com.sap.sailing.domain.igtimiadapter.persistence, - com.sap.sailing.domain.racelogtrackingadapter.testsupport, - com.rabbitmq.client;bundle-version="2.8.4", - com.sap.sse.filestorage, - com.google.gwt.user;bundle-version="2.8.2";resolution:=optional, - org.moxieapps.gwt.highcharts;bundle-version="1.5.0", - com.sap.sse.replication;bundle-version="1.0.0" -Bundle-ClassPath: . -Import-Package: com.sap.sailing.domain.racelogtracking.impl, - javax.servlet;version="3.1.0", - javax.servlet.http;version="3.1.0", - junit.framework;version="4.8.1", - org.json.simple, - org.json.simple.parser, - org.junit;version="4.8.1", - org.osgi.framework, - org.osgi.util.tracker;version="1.5.0" -Automatic-Module-Name: com.sap.sailing.gwt.ui.test diff --git a/java/com.sap.sailing.gwt.ui.test/build.properties b/java/com.sap.sailing.gwt.ui.test/build.properties deleted file mode 100755 index 2a76b9a34ac..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/build.properties +++ /dev/null @@ -1,8 +0,0 @@ -source.. = src/,\ - resources/ -output.. = bin -bin.includes = META-INF/,\ - . -jars.compile.order = . -source.. = src/,\ - resources/ diff --git a/java/com.sap.sailing.gwt.ui.test/pom.xml b/java/com.sap.sailing.gwt.ui.test/pom.xml deleted file mode 100644 index d83cacf301b..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/pom.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - 4.0.0 - - root - com.sap.sailing - 1.0.0-SNAPSHOT - - com.sap.sailing.gwt.ui.test - eclipse-plugin - - - - - org.codehaus.mojo - gwt-maven-plugin - 2.4.0 - - **/GwtTestCaseColumnToggling.java - - - - - test - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - **/GwtTestCaseColumnToggling.java - - - - - - diff --git a/java/com.sap.sailing.gwt.ui.test/resources/com/sap/sailing/gwt/ui/test/TestConsole.gwt.xml b/java/com.sap.sailing.gwt.ui.test/resources/com/sap/sailing/gwt/ui/test/TestConsole.gwt.xml deleted file mode 100644 index da425453964..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/resources/com/sap/sailing/gwt/ui/test/TestConsole.gwt.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/client/GwtUrlHelperTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/client/GwtUrlHelperTest.java deleted file mode 100644 index fbc1ec96195..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/client/GwtUrlHelperTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.sap.sailing.gwt.ui.client; - -import org.junit.Test; - -import com.google.gwt.junit.client.GWTTestCase; -import com.sap.sse.common.util.UrlHelper; - -public class GwtUrlHelperTest extends GWTTestCase { - - private final UrlHelper urlHelper = GwtUrlHelper.INSTANCE; - - @Test - public void testEncodeQueryStringSimple() { - testCase("TestTest", "TestTest"); - } - - @Test - public void testEncodeQueryStringWithWhitespace() { - testCase("Test+Test", "Test Test"); - } - - @Test - public void testEncodeQueryStringWithSlash() { - testCase("Test%2FTest", "Test/Test"); - } - - @Test - public void testEncodeQueryStringWithPlusSign() { - testCase("Test%2BTest", "Test+Test"); - } - - @Test - public void testEncodeQueryStringWithAmpersand() { - testCase("Test%26Test", "Test&Test"); - } - - @Test - public void testEncodeQueryStringComplex() { - testCase("Test+%2B+Test+%2F+Test+%26+Test", "Test + Test / Test & Test"); - } - - private void testCase(String expectedEncodedString, String decodedString) { - assertEquals(expectedEncodedString, urlHelper.encodeQueryString(decodedString)); - } - - @Override - public String getModuleName() { - return "com.sap.sailing.gwt.ui.test.TestConsole"; - } - -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/common/client/CountdownTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/common/client/CountdownTest.java deleted file mode 100644 index b96f7024c87..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/common/client/CountdownTest.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.sap.sailing.gwt.ui.common.client; - -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; - -import org.junit.Test; - -import com.sap.sailing.gwt.home.shared.utils.Countdown; -import com.sap.sailing.gwt.home.shared.utils.Countdown.CountdownListener; -import com.sap.sailing.gwt.home.shared.utils.Countdown.RemainingTime; -import com.sap.sailing.gwt.home.shared.utils.Countdown.Unit; -import com.sap.sse.common.Duration; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.impl.MillisecondsTimePoint; - -public class CountdownTest { - - @Test - public void testDaysAndHours() throws Exception { - final long days = 2; - final long hours = 13; - final long minutes = 28; - final long seconds = 2; - TimePoint zeroDate = MillisecondsTimePoint.now().plus(Duration.ONE_DAY.times(days)).plus(Duration.ONE_HOUR.times(hours)).plus(Duration.ONE_MINUTE.times(minutes)).plus(Duration.ONE_SECOND.times(seconds)); - CountdownListener countdownListener = createCountDownAssertionListener(days, Unit.DAYS, hours, Unit.HOURS); - new Countdown(zeroDate, countdownListener, true); - } - - private CountdownListener createCountDownAssertionListener(final long majorValue, final Unit majorUnit, final long minorValue, final Unit minorUnit) { - return new CountdownListener() { - - @Override - public void changed(RemainingTime major, RemainingTime minor) { - assertThat(major, is(notNullValue())); - assertThat(major.value, is(majorValue)); - assertThat(major.unit, is(majorUnit)); - - if (minorUnit != null) { - assertThat(minor, is(notNullValue())); - assertThat(minor.value, is(minorValue)); - assertThat(minor.unit, is(minorUnit)); - } else { - assertThat(minor, is(nullValue())); - } - - - } - }; - } - - @Test - public void testDaysNoHours() throws Exception { - final long days = 2; - final long hours = 0; - final long minutes = 28; - final long seconds = 2; - TimePoint zeroDate = MillisecondsTimePoint.now().plus(Duration.ONE_DAY.times(days)).plus(Duration.ONE_HOUR.times(hours)).plus(Duration.ONE_MINUTE.times(minutes)).plus(Duration.ONE_SECOND.times(seconds)); - CountdownListener countdownListener = createCountDownAssertionListener(days, Unit.DAYS, hours, Unit.HOURS); - new Countdown(zeroDate, countdownListener, true); - } - - @Test - public void testOnlyDays() throws Exception { - final long days = 3; - final long hours = 0; - final long minutes = 28; - final long seconds = 2; - TimePoint zeroDate = MillisecondsTimePoint.now().plus(Duration.ONE_DAY.times(days)).plus(Duration.ONE_HOUR.times(hours)).plus(Duration.ONE_MINUTE.times(minutes)).plus(Duration.ONE_SECOND.times(seconds)); - CountdownListener countdownListener = createCountDownAssertionListener(days, Unit.DAYS, 0, null); - new Countdown(zeroDate, countdownListener, true); - } - - @Test - public void testHoursAndMinutes() throws Exception { - final long days = 0; - final long hours = 13; - final long minutes = 28; - final long seconds = 2; - TimePoint zeroDate = MillisecondsTimePoint.now().plus(Duration.ONE_DAY.times(days)).plus(Duration.ONE_HOUR.times(hours)).plus(Duration.ONE_MINUTE.times(minutes)).plus(Duration.ONE_SECOND.times(seconds)); - CountdownListener countdownListener = createCountDownAssertionListener(hours, Unit.HOURS, minutes, Unit.MINUTES); - new Countdown(zeroDate, countdownListener, true); - } - - @Test - public void testMinutesAndSeconds() throws Exception { - final long days = 0; - final long hours = 0; - final long minutes = 28; - final long seconds = 2; - TimePoint zeroDate = MillisecondsTimePoint.now().plus(Duration.ONE_DAY.times(days)).plus(Duration.ONE_HOUR.times(hours)).plus(Duration.ONE_MINUTE.times(minutes)).plus(Duration.ONE_SECOND.times(seconds)); - CountdownListener countdownListener = createCountDownAssertionListener(minutes, Unit.MINUTES, seconds, Unit.SECONDS); - new Countdown(zeroDate, countdownListener, true); - } - - @Test - public void testSecondOnly() throws Exception { - final long days = 0; - final long hours = 0; - final long minutes = 0; - final long seconds = 2; - TimePoint zeroDate = MillisecondsTimePoint.now().plus(Duration.ONE_DAY.times(days)).plus(Duration.ONE_HOUR.times(hours)).plus(Duration.ONE_MINUTE.times(minutes)).plus(Duration.ONE_SECOND.times(seconds)); - CountdownListener countdownListener = createCountDownAssertionListener(seconds, Unit.SECONDS, 0, null); - new Countdown(zeroDate, countdownListener, true); - } - -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/AbstractListFilterTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/AbstractListFilterTest.java deleted file mode 100755 index 8fe2bc16f10..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/AbstractListFilterTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; - -import org.junit.Before; -import org.junit.Test; - -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sse.common.Util; -import com.sap.sse.common.filter.AbstractListFilter; - -public class AbstractListFilterTest { - - AbstractListFilter als = new AbstractListFilter() { - @Override - public Iterable getStrings(BoatImpl t) { - return Arrays.asList(t.getName(), t.getSailID()); - } - }; - ArrayList all = new ArrayList(); - - @Before - public void setUp() { - all.add(new BoatImpl("1", "Race 1", null, "Kiel")); - all.add(new BoatImpl("2", "Race 2", null, "Kiel")); - all.add(new BoatImpl("3", "Race 3", null, "Kiel")); - all.add(new BoatImpl("4", "Race 1", null, "Wannsee")); - all.add(new BoatImpl("5", "Race 2", null, "Wannsee")); - all.add(new BoatImpl("6", "Final", null, "Wannsee")); - } - - @Test - public void test() { - assertEquals(2, Util.size(als.applyFilter(Arrays.asList(new String[] { "Race", "2" }), all))); - assertEquals(1, Util.size(als.applyFilter(Collections.singleton("3"), all))); - assertEquals("Race 3", als.applyFilter(Collections.singleton("3"), all).iterator().next().getName()); - assertEquals(1, Util.size(als.applyFilter(Arrays.asList(new String[] { "1", "Wannsee" }), all))); - assertEquals("Race 1", als.applyFilter(Arrays.asList(new String[] { "1", "Wannsee" }), all).iterator().next().getName()); - assertEquals(0, Util.size(als.applyFilter(Arrays.asList(new String[] { "Wannsee", "3" }), all))); - assertEquals(5, Util.size(als.applyFilter(Arrays.asList(new String[] { "Race", "Race" }), all))); - assertEquals(5, Util.size(als.applyFilter(Collections.singleton("R"), all))); - assertEquals(4, Util.size(als.applyFilter(Collections.singleton("i"), all))); - } -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/GwtTestCaseColumnToggling.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/GwtTestCaseColumnToggling.java deleted file mode 100644 index 202492537ef..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/GwtTestCaseColumnToggling.java +++ /dev/null @@ -1,249 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import java.util.ArrayList; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.junit.Test; - -import com.google.gwt.core.client.GWT; -import com.google.gwt.junit.client.GWTTestCase; -import com.google.gwt.user.cellview.client.Column; -import com.google.gwt.user.client.rpc.AsyncCallback; -import com.sap.sailing.domain.common.RegattaNameAndRaceName; -import com.sap.sailing.domain.common.ScoringSchemeType; -import com.sap.sailing.domain.common.dto.IncrementalOrFullLeaderboardDTO; -import com.sap.sailing.domain.common.dto.LeaderboardDTO; -import com.sap.sailing.domain.common.dto.LeaderboardRowDTO; -import com.sap.sailing.domain.common.dto.RaceColumnDTO; -import com.sap.sailing.domain.tractracadapter.TracTracConnectionConstants; -import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.leaderboard.ExpandableSortableColumn; -import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTOWithSecurity; -import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDTO; -import com.sap.sse.common.Util; - -public class GwtTestCaseColumnToggling extends GWTTestCase { - - //These objects should be created by calling GWT.create(Class c); - private LeaderboardPanelMock leaderboardPanel; - private MyTestSailingServiceAsync service; - private StringMessages stringMessages; - - //Test data. - private final String LEADERBOARD_NAME = "test"; - private static final String DEFAULT_FLEET_NAME = "Default"; - private final String COLUMN1_NAME = "r1"; - private final String EVENT_NAME = "Sailing Team Germany (STG)"; - protected static final boolean tractracTunnel = Boolean.valueOf(System.getProperty("tractrac.tunnel", "false")); - protected static final String tractracTunnelHost = System.getProperty("tractrac.tunnel.host", "localhost"); - private final String JSON_URL= "http://" + TracTracConnectionConstants.HOST_NAME + "/events/event_20110505_SailingTea/jsonservice.php"; - private final String TRACKED_RACE = "schwerttest"; - private final String COURSE_DESIGN_UPDATE_URI = "http://tracms.traclive.dk/update_course"; - private final String TRACTRAC_USERNAME = "tracTest"; //only used for course update authentification - private final String TRACTRAC_PASSWORD = "tracTest"; //only used for course update authentification - - private LeaderboardDTO leaderboard; - private TracTracRaceRecordDTO rrDao; - private ExpandableSortableColumn rc; - - - - @Override - protected void gwtSetUp() throws Exception { - super.gwtSetUp(); - service = GWT.create(MyTestSailingService.class); - stringMessages = GWT.create(StringMessages.class); - } - - @Test - public void testColumnDeleting() { - delayTestFinish(1000000); - listRacesInEvent(); - } - - private void listRacesInEvent(){ - service.listTracTracRacesInEvent(JSON_URL, /* hidden */ true, new AsyncCallback>>() { - - @Override - public void onFailure(Throwable caught) { - fail("Failed to list races." + caught.getLocalizedMessage()); - } - - @Override - public void onSuccess(Util.Pair> result) { - System.out.println("Listed races."); - for (TracTracRaceRecordDTO rr : result.getB()){ - if (rr.getName().equals(TRACKED_RACE)){ - rrDao = rr; - } - } - assertNotNull(rrDao); - trackRace(); - } - }); - } - - private void trackRace(){ - final Set rrDAOs = new HashSet(); - rrDAOs.add(rrDao); - service.trackWithTracTrac(/* regattaToAddTo */null, rrDAOs, tractracTunnel ? "tcp://" + tractracTunnelHost + ":" - + TracTracConnectionConstants.PORT_TUNNEL_LIVE : "tcp://" + TracTracConnectionConstants.HOST_NAME + ":" - + TracTracConnectionConstants.PORT_LIVE, tractracTunnel ? "tcp://" + tractracTunnelHost + ":" - + TracTracConnectionConstants.PORT_TUNNEL_STORED : "tcp://" + TracTracConnectionConstants.HOST_NAME - + ":" + TracTracConnectionConstants.PORT_STORED, - COURSE_DESIGN_UPDATE_URI, - false, false, /* offsetToStartTimeOfSimulatedRace */ null, /* ignoreTracTracMarkPassings */ false, - /* useOfficialEventsToUpdateRaceLog */ false, TRACTRAC_USERNAME, TRACTRAC_PASSWORD, new AsyncCallback() { - - @Override - public void onFailure(Throwable caught) { - fail("Failed to track race: " + caught.getLocalizedMessage()); - } - - @Override - public void onSuccess(Void result) { - System.out.println("Tracked race."); - createLeaderboard(); - } - }); - } - - private void createLeaderboard(){ - service.removeLeaderboard(LEADERBOARD_NAME, new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - fail("Failed to remove Leaderboard "+LEADERBOARD_NAME+": " + caught.getLocalizedMessage()); - finishTest(); - } - - @Override - public void onSuccess(Void result) { - service.createFlexibleLeaderboard(LEADERBOARD_NAME, null, new int[] { 1, 2 }, - ScoringSchemeType.LOW_POINT, null, - new AsyncCallback() { - @Override - public void onSuccess(StrippedLeaderboardDTOWithSecurity result) { - System.out.println("Created Leaderboard "+result.getName()); - addColumnToLeaderboard(); - } - - @Override - public void onFailure(Throwable caught) { - fail("Failed to create Leaderboard." + caught.getLocalizedMessage()); - } - }); - } - }); - } - - private void addColumnToLeaderboard() { - leaderboardPanel = new LeaderboardPanelMock(service, LEADERBOARD_NAME, null, stringMessages); - service.addColumnToLeaderboard(COLUMN1_NAME, LEADERBOARD_NAME, false, - new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - fail("Failed to add column to leaderboard."); - } - - @Override - public void onSuccess(Void result) { - System.out.println("Added column to leaderboard."); - RaceColumnDTO race = new RaceColumnDTO(); - race.setName(COLUMN1_NAME); - race.setMedalRace(false); - leaderboardPanel.addColumn(leaderboardPanel.createRaceColumn(race)); - linkTrackedRace(); - } - }); - } - - private void linkTrackedRace() { - service.connectTrackedRaceToLeaderboardColumn(LEADERBOARD_NAME, COLUMN1_NAME, DEFAULT_FLEET_NAME, - new RegattaNameAndRaceName(EVENT_NAME, TRACKED_RACE), - new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - fail("Failed to link race."); - } - - @Override - public void onSuccess(Boolean result) { - System.out.println("Success of linking race to column: "+result); - getLeaderboardByNameAndDeleteColumn(); - } - }); - } - - private void getLeaderboardByNameAndDeleteColumn(){ - ArrayList al = new ArrayList(); - al.add(COLUMN1_NAME); - service.getLeaderboardByName(LEADERBOARD_NAME, new Date(), al, /* addOverallDetails */ false, /* previousLeaderboardId */ null, - /* fillUncorrectedTotalPoints */ false, new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - fail("Failed to get leaderboard."); - finishTest(); - } - - @Override - public void onSuccess(IncrementalOrFullLeaderboardDTO result) { - System.out.println("Got leaderboard."); - leaderboard = result.getLeaderboardDTO(/* previousVersion */ null); - leaderboardPanel.updateLeaderboard(leaderboard); - for (int i = 0; i < leaderboardPanel.getLeaderboardTable() - .getColumnCount(); i++) { - Column c = leaderboardPanel.getLeaderboardTable().getColumn(i); - if (c instanceof ExpandableSortableColumn) { - @SuppressWarnings("unchecked") - ExpandableSortableColumn myRc = (ExpandableSortableColumn) c; - rc = myRc; - rc.setEnableExpansion(true); - } - } - removeColumnAndAssert(); - } - }); - } - - private void removeColumnAndAssert() { - service.removeLeaderboardColumn(LEADERBOARD_NAME, COLUMN1_NAME, - new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - fail("Failed to remoce column."); - finishTest(); - } - - @Override - public void onSuccess(Void result) { - leaderboardPanel.updateLeaderboard(leaderboard); - assertNotNull(rc); - try { - rc.changeExpansionState(/* expand */ !rc.isExpanded()); - leaderboardPanel.updateLeaderboard(leaderboard); - } catch (Exception e) { - fail("Toggle column failed." + e.getLocalizedMessage()); - } - finishTest(); - } - }); - } - - - - @Override - protected void gwtTearDown() throws Exception { - // TODO Auto-generated method stub - super.gwtTearDown(); - } - - @Override - public String getModuleName() { - // TODO Auto-generated method stub - return "com.sap.sailing.gwt.ui.test.TestConsole"; - } - -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/LeaderboardPanelMock.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/LeaderboardPanelMock.java deleted file mode 100644 index bc4fe0a452f..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/LeaderboardPanelMock.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import java.util.Arrays; - -import com.sap.sailing.domain.common.DetailType; -import com.sap.sailing.domain.common.dto.LeaderboardDTO; -import com.sap.sailing.domain.common.dto.LeaderboardRowDTO; -import com.sap.sailing.domain.common.dto.RaceColumnDTO; -import com.sap.sailing.gwt.settings.client.leaderboard.MultiRaceLeaderboardSettings; -import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel; -import com.sap.sailing.gwt.ui.client.FlagImageResolverImpl; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; -import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sailing.gwt.ui.leaderboard.ClassicLeaderboardStyle; -import com.sap.sailing.gwt.ui.leaderboard.MultiRaceLeaderboardPanel; -import com.sap.sse.gwt.client.ErrorReporter; -import com.sap.sse.gwt.client.async.AsyncActionsExecutor; -import com.sap.sse.gwt.client.celltable.AbstractSortableColumnWithMinMax; -import com.sap.sse.gwt.client.celltable.SortedCellTable; - -public class LeaderboardPanelMock extends MultiRaceLeaderboardPanel { - - public LeaderboardPanelMock(SailingServiceAsync sailingService, - String leaderboardName, ErrorReporter errorReporter, - StringMessages stringMessages) { - super(null, null, sailingService, new AsyncActionsExecutor(), new MultiRaceLeaderboardSettings(), - new CompetitorSelectionModel( - /* hasMultiSelection */true), - leaderboardName, errorReporter, stringMessages, /* showRaceDetails */ true, new ClassicLeaderboardStyle(), - FlagImageResolverImpl.get(), Arrays.asList(DetailType.values())); - } - - @Override - protected void addColumn(AbstractSortableColumnWithMinMax column) { - super.addColumn(column); - } - - @Override - public RaceColumn createRaceColumn(RaceColumnDTO race) { - return super.createRaceColumn(race); - } - - @Override - public void removeColumn(int columnIndex) { - super.removeColumn(columnIndex); - } - - @Override - public void updateLeaderboard(LeaderboardDTO leaderboard) { - super.updateLeaderboard(leaderboard); - } - - @Override - public SortedCellTable getLeaderboardTable() { - return super.getLeaderboardTable(); - } - -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/LineSegmentTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/LineSegmentTest.java deleted file mode 100644 index 8ae2a248e10..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/LineSegmentTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -import com.sap.sailing.gwt.ui.simulator.util.LineSegment; -import com.sap.sailing.gwt.ui.simulator.util.LineSegment.Point; - -public class LineSegmentTest { - - @Test - public void test1() { - LineSegment s1 = new LineSegment(0,0,10,10); - LineSegment s2 = new LineSegment(10,0,0,10); - - Point intersectionPoint = s1.intersect(s2); - if (intersectionPoint != null) { - System.out.println("The lines interect at " + intersectionPoint); - } - assertEquals("Lines do intersect", 5.0, intersectionPoint.getX(),1e-6); - assertEquals("Lines do intersect", 5.0, intersectionPoint.getY(),1e-6); - } - - @Test - public void test2() { - LineSegment s1 = new LineSegment(0,0,0,10); - LineSegment s2 = new LineSegment(10,0,10,10); - - Point intersectionPoint = s1.intersect(s2); - - assertEquals("Lines do not intersect", null, intersectionPoint); - } - - @Test - public void test3() { - - LineSegment s1 = new LineSegment(53.987292187570304, 10.944955638570837,53.991202136256135, 10.951666848382969); - - LineSegment b1 = new LineSegment(53.977189863832564, 10.886260271572164,53.96560719314814, 10.925463437534281); - LineSegment b2 = new LineSegment(53.96560719314814, 10.925463437534281,53.991220287799436, 10.947350263095805); - LineSegment b3 = new LineSegment(53.991220287799436, 10.947350263095805,54.00280295848386, 10.90814709713369); - LineSegment b4 = new LineSegment(54.00280295848386, 10.90814709713369,53.977189863832564, 10.886260271572164); - - s1.intersect(b1); - s1.intersect(b2); - s1.intersect(b3); - s1.intersect(b4); - Point intersectionPoint = s1.intersect(b1); - assertEquals("Lines s1 and b1 do not intersect", null, intersectionPoint); - intersectionPoint = s1.intersect(b2); - assertEquals("Lines s and b2 do not intersect", null, intersectionPoint); - intersectionPoint = s1.intersect(b3); - assertEquals("Lines s3 and b3 do not intersect", null, intersectionPoint); - intersectionPoint = s1.intersect(b4); - assertEquals("Lines s4 and b4 do not intersect", null, intersectionPoint); - - } - -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java deleted file mode 100755 index 8af8413755e..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MockedTrackedRace.java +++ /dev/null @@ -1,969 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.io.Serializable; -import java.util.Collections; -import java.util.List; -import java.util.NavigableSet; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.Future; - -import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; -import com.sap.sailing.domain.base.Boat; -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CourseBase; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.base.Leg; -import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.base.RaceDefinition; -import com.sap.sailing.domain.base.Regatta; -import com.sap.sailing.domain.base.Sideline; -import com.sap.sailing.domain.base.SpeedWithConfidence; -import com.sap.sailing.domain.base.Waypoint; -import com.sap.sailing.domain.common.NoWindException; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.SpeedWithBearing; -import com.sap.sailing.domain.common.Tack; -import com.sap.sailing.domain.common.TargetTimeInfo; -import com.sap.sailing.domain.common.Wind; -import com.sap.sailing.domain.common.WindSource; -import com.sap.sailing.domain.common.WindSourceType; -import com.sap.sailing.domain.common.racelog.Flags; -import com.sap.sailing.domain.common.tracking.GPSFix; -import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.common.tracking.SensorFix; -import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException; -import com.sap.sailing.domain.polars.PolarDataService; -import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver; -import com.sap.sailing.domain.ranking.RankingMetric; -import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo; -import com.sap.sailing.domain.tracking.CourseDesignChangedListener; -import com.sap.sailing.domain.tracking.DynamicGPSFixTrack; -import com.sap.sailing.domain.tracking.DynamicRaceDefinitionSet; -import com.sap.sailing.domain.tracking.DynamicSensorFixTrack; -import com.sap.sailing.domain.tracking.DynamicTrackedRace; -import com.sap.sailing.domain.tracking.DynamicTrackedRegatta; -import com.sap.sailing.domain.tracking.GPSFixTrack; -import com.sap.sailing.domain.tracking.LineDetails; -import com.sap.sailing.domain.tracking.Maneuver; -import com.sap.sailing.domain.tracking.MarkPassing; -import com.sap.sailing.domain.tracking.MarkPositionAtTimePointCache; -import com.sap.sailing.domain.tracking.RaceAbortedListener; -import com.sap.sailing.domain.tracking.RaceChangeListener; -import com.sap.sailing.domain.tracking.RaceExecutionOrderProvider; -import com.sap.sailing.domain.tracking.RaceListener; -import com.sap.sailing.domain.tracking.SensorFixTrack; -import com.sap.sailing.domain.tracking.StartTimeChangedListener; -import com.sap.sailing.domain.tracking.TrackFactory; -import com.sap.sailing.domain.tracking.TrackedLeg; -import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; -import com.sap.sailing.domain.tracking.TrackedRace; -import com.sap.sailing.domain.tracking.TrackedRaceStatus; -import com.sap.sailing.domain.tracking.TrackingConnectorInfo; -import com.sap.sailing.domain.tracking.TrackingDataLoader; -import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; -import com.sap.sailing.domain.tracking.WindPositionMode; -import com.sap.sailing.domain.tracking.WindStore; -import com.sap.sailing.domain.tracking.WindSummary; -import com.sap.sailing.domain.tracking.WindTrack; -import com.sap.sailing.domain.tracking.WindWithConfidence; -import com.sap.sailing.domain.tracking.impl.WindTrackImpl; -import com.sap.sailing.domain.windestimation.IncrementalWindEstimation; -import com.sap.sse.common.Bearing; -import com.sap.sse.common.Distance; -import com.sap.sse.common.Duration; -import com.sap.sse.common.IsManagedByCache; -import com.sap.sse.common.Speed; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util; -import com.sap.sse.util.ThreadLocalTransporter; - -public class MockedTrackedRace implements DynamicTrackedRace { - private static final long serialVersionUID = 5827912985564121181L; - private final WindTrack windTrack = new WindTrackImpl(/* millisecondsOverWhichToAverage */ 30000, /* useSpeed */ true, "TestWindTrack"); - - public WindTrack getWindTrack() { - return windTrack; - } - - @Override - public RaceDefinition getRace() { - return null; - } - - @Override - public TimePoint getStartOfRace() { - return null; - } - - @Override - public TimePoint getStartOfRace(boolean inferred) { - return null; - } - - @Override - public TimePoint getFinishingTime() { - return null; - } - - @Override - public TimePoint getFinishedTime() { - return null; - } - - @Override - public Iterable getTrackedLegs() { - return null; - } - - @Override - public TrackedLeg getTrackedLeg(Leg leg) { - return null; - } - - @Override - public TrackedLegOfCompetitor getCurrentLeg(Competitor competitor, TimePoint timePoint) { - return null; - } - - @Override - public TrackedLeg getCurrentLeg(TimePoint timePoint) { - return null; - } - - @Override - public TrackedLeg getTrackedLegFinishingAt(Waypoint endOfLeg) { - return null; - } - - @Override - public TrackedLeg getTrackedLegStartingAt(Waypoint startOfLeg) { - return null; - } - - @Override - public TrackedLegOfCompetitor getTrackedLeg(Competitor competitor, TimePoint at) { - return null; - } - - @Override - public TrackedLegOfCompetitor getTrackedLeg(Competitor competitor, Leg leg) { - return null; - } - - @Override - public long getUpdateCount() { - return 0; - } - - @Override - public int getRankDifference(Competitor competitor, Leg leg, TimePoint timePoint) { - return 0; - } - - @Override - public int getRank(Competitor competitor) throws NoWindException { - return 0; - } - - @Override - public int getRank(Competitor competitor, TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { - return 0; - } - - @Override - public Iterable getMarkPassingsInOrder(Waypoint waypoint) { - return null; - } - - @Override - public MarkPassing getMarkPassing(Competitor competitor, Waypoint waypoint) { - return null; - } - - @Override - public DynamicGPSFixTrack getOrCreateTrack(Mark mark) { - return null; - } - - @Override - public WindTrack getOrCreateWindTrack(WindSource windSource, long delayForWindEstimationCacheInvalidation) { - return null; - } - - @Override - public void waitForNextUpdate(int sinceUpdate) throws InterruptedException { - } - - @Override - public TimePoint getStartOfTracking() { - return null; - } - - @Override - public TimePoint getTimePointOfNewestEvent() { - return null; - } - - @Override - public NavigableSet getMarkPassings(Competitor competitor) { - return null; - } - - @Override - public boolean recordFix(Competitor competitor, GPSFixMoving fix, boolean onlyWhenInTrackingTimeInterval) { - return false; - } - - @Override - public boolean recordWind(Wind wind, WindSource windSource, boolean applyFilter) { - if (windSource.getType() == WindSourceType.EXPEDITION) { - windTrack.add(wind); - return true; - } else { - return false; - } - } - - @Override - public void addListener(RaceChangeListener listener) { - } - - @Override - public void addListener(RaceChangeListener listener, boolean notifyAboutWindFixesAlreadyLoaded, - boolean notifyAboutGPSFixesAlreadyLoaded) { - } - - @Override - public void updateMarkPassings(Competitor competitor, Iterable markPassings) { - } - - @Override - public void setStartTimeReceived(TimePoint start) { - } - - @Override - public DynamicGPSFixTrack getTrack(Competitor competitor) { - return null; - } - - @Override - public void removeWind(Wind wind, WindSource windSource) { - } - - @Override - public TimePoint getTimePointOfLastEvent() { - return null; - } - - @Override - public void setMillisecondsOverWhichToAverageSpeed(long millisecondsOverWhichToAverageSpeed) { - } - - @Override - public void setMillisecondsOverWhichToAverageWind(long millisecondsOverWhichToAverageWind) { - } - - @Override - public long getMillisecondsOverWhichToAverageSpeed() { - return 0; - } - - @Override - public long getMillisecondsOverWhichToAverageWind() { - return 0; - } - - @Override - public Wind getEstimatedWindDirection(TimePoint timePoint) { - return null; - } - - @Override - public boolean hasStarted(TimePoint at) { - return false; - } - - @Override - public DynamicTrackedRegatta getTrackedRegatta() { - return new DynamicTrackedRegatta() { - private static final long serialVersionUID = 2651590861333064588L; - - @Override - public Regatta getRegatta() { - final Regatta result = mock(Regatta.class); - when(result.getName()).thenReturn("A Mocked Test Regatta"); - return result; - } - - @Override - public Iterable getTrackedRaces() { - return null; - } - - @Override - public void addTrackedRace(TrackedRace trackedRace, Optional threadLocalTransporter) { - } - - @Override - public void removeTrackedRace(TrackedRace trackedRace, Optional threadLocalTransporter) { - } - - @Override - public void addRaceListener(RaceListener listener, Optional threadLocalTransporter, boolean synchronous) { - } - - @Override - public int getTotalPoints(Competitor competitor, TimePoint timePoint) throws NoWindException { - return 0; - } - - @Override - public DynamicTrackedRace getTrackedRace(RaceDefinition race) { - return null; - } - - @Override - public DynamicTrackedRace getExistingTrackedRace(RaceDefinition race) { - return null; - } - - @Override - public DynamicTrackedRace createTrackedRace(RaceDefinition raceDefinition, Iterable sidelines, WindStore windStore, - long delayToLiveInMillis, long millisecondsOverWhichToAverageWind, - long millisecondsOverWhichToAverageSpeed, DynamicRaceDefinitionSet raceDefinitionSetToUpdate, - boolean useMarkPassingCalculator, RaceLogAndTrackedRaceResolver raceLogResolver, Optional threadLocalTransporter, TrackingConnectorInfo trackingConnectorInfo) { - return null; - } - - @Override - public void lockTrackedRacesForRead() { - } - - @Override - public void unlockTrackedRacesAfterRead() { - } - - @Override - public void lockTrackedRacesForWrite() { - } - - @Override - public void unlockTrackedRacesAfterWrite() { - } - - @Override - public Future removeRaceListener(RaceListener listener) { - return null; - } - }; - } - - @Override - public Position getApproximatePosition(Waypoint waypoint, TimePoint timePoint, MarkPositionAtTimePointCache markPositionCache) { - return null; - } - - @Override - public Tack getTack(Competitor competitor, TimePoint timePoint) { - return null; - } - - @Override - public Tack getTack(SpeedWithBearing speedWithBearing, Wind wind, TimePoint timePoint) { - return null; - } - - @Override - public Wind getDirectionFromStartToNextMark(TimePoint at) { - return null; - } - - @Override - public List approximate(Competitor competitor, Distance maxDistance, TimePoint from, TimePoint to) { - return null; - } - - @Override - public Iterable getManeuvers(Competitor competitor, TimePoint from, TimePoint to, boolean waitForLatest) { - return null; - } - - @Override - public Iterable getManeuvers(Competitor competitor, boolean waitForLatest) { - return null; - } - - @Override - public boolean raceIsKnownToStartUpwind() { - return false; - } - - @Override - public void setRaceIsKnownToStartUpwind(boolean raceIsKnownToStartUpwind) { - } - - @Override - public RegattaAndRaceIdentifier getRaceIdentifier() { - return null; - } - - @Override - public TimePoint getEndOfRace() { - return null; - } - - @Override - public Distance getDistanceTraveled(Competitor competitor, TimePoint timePoint) { - return null; - } - - @Override - public Distance getDistanceFoiled(Competitor competitor, TimePoint timePoint) { - return null; - } - - @Override - public Duration getDurationFoiled(Competitor competitor, TimePoint timePoint) { - return null; - } - - @Override - public Distance getWindwardDistanceToCompetitorFarthestAhead(Competitor competitor, TimePoint timePoint, WindPositionMode windPositionMode) { - return null; - } - - @Override - public Wind getWind(Position p, TimePoint at) { - return null; - } - - @Override - public Wind getWind(Position p, TimePoint at, Set windSourcesToExclude) { - return null; - } - - @Override - public Set getWindSources(WindSourceType type) { - return null; - } - - @Override - public Set getWindSources() { - return null; - } - - @Override - public WindWithConfidence> getWindWithConfidence(Position p, TimePoint at, - Set windSourcesToExclude) { - return null; - } - - @Override - public WindWithConfidence getEstimatedWindDirectionWithConfidence(TimePoint timePoint) { - return null; - } - - @Override - public WindWithConfidence> getWindWithConfidence(Position p, TimePoint at) { - return null; - } - - @Override - public Set getWindSourcesToExclude() { - return null; - } - - @Override - public TimePoint getEndOfTracking() { - return null; - } - - @Override - public TimePoint getTimePointOfOldestEvent() { - return null; - } - - @Override - public void setStartOfTrackingReceived(TimePoint startOfTrackingReceived) { - } - - @Override - public void setEndOfTrackingReceived(TimePoint endOfTrackingReceived) { - } - - @Override - public Iterable>> getMarkPassingsTimes() { - return null; - } - - @Override - public Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint timePoint, boolean waitForLatestAnalysis) throws NoWindException { - return null; - } - - @Override - public Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint timePoint, - boolean waitForLatestAnalyses, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { - return null; - } - - @Override - public WindTrack getOrCreateWindTrack(WindSource windSource) { - return null; - } - - @Override - public void recordFix(Mark mark, GPSFix fix, boolean onlyWhenInTrackingTimeInterval) { - } - - @Override - public void removeListener(RaceChangeListener listener) { - } - - @Override - public WindStore getWindStore() { - return null; - } - - @Override - public void setWindSourcesToExclude(Iterable windSourcesToExclude) { - } - - @Override - public Competitor getOverallLeader(TimePoint timePoint) { - return null; - } - - @Override - public long getDelayToLiveInMillis() { - return 0; - } - - @Override - public void setDelayToLiveInMillis(long delayToLiveInMillis) { - } - - @Override - public void setAndFixDelayToLiveInMillis(long delayToLiveInMillis) { - } - - @Override - public List getCompetitorsFromBestToWorst(TimePoint timePoint) { - return null; - } - - @Override - public Distance getAverageAbsoluteCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, boolean upwindOnly, boolean waitForLatestAnalyses) - throws NoWindException { - return null; - } - - @Override - public void waitUntilLoadingFromWindStoreComplete() throws InterruptedException { - } - - @Override - public Iterable getMarks() { - return null; - } - - @Override - public boolean hasWindData() { - return false; - } - - @Override - public boolean hasGPSData() { - return false; - } - - @Override - public void lockForRead(Iterable markPassings) { - } - - @Override - public void unlockAfterRead(Iterable markPassings) { - } - - @Override - public TrackedRaceStatus getStatus() { - return null; - } - - @Override - public void setStatus(TrackedRaceStatus newStatus) { - } - - @Override - public void onStatusChanged(TrackingDataLoader loader, TrackedRaceStatus status) { - } - - @Override - public void waitUntilNotLoading() { - } - - @Override - public RaceLog detachRaceLog(Serializable identifier) { - return null; - } - - @Override - public void attachRaceLog(RaceLog raceLog) { - } - - @Override - public RaceLog getRaceLog(Serializable identifier) { - return null; - } - - @Override - public void onCourseDesignChangedByRaceCommittee(CourseBase courseDesign) { - } - - @Override - public void addCourseDesignChangedListener(CourseDesignChangedListener listener) { - } - - @Override - public Distance getDistanceToStartLine(Competitor competitor, TimePoint timePoint) { - return null; - } - - @Override - public Distance getDistanceFromStarboardSideOfStartLineWhenPassingStart(Competitor competitor) { - return null; - } - - @Override - public void invalidateStartTime() { - } - - @Override - public void invalidateEndTime() { - } - - @Override - public boolean isLive(TimePoint at) { - return false; - } - - @Override - public Iterable getCourseSidelines() { - return null; - } - - @Override - public Distance getDistanceToStartLine(Competitor competitor, long millisecondsBeforeRaceStart) { - return null; - } - - @Override - public Speed getSpeed(Competitor competitor, long millisecondsBeforeRaceStart) { - return null; - } - - public void onStartTimeChangedByRaceCommittee(TimePoint newStartTime) { - } - - @Override - public void addStartTimeChangedListener(StartTimeChangedListener listener) { - } - - @Override - public void removeStartTimeChangedListener(StartTimeChangedListener listener) { - } - - @Override - public TimePoint getStartTimeReceived() { - return null; - } - - @Override - public LineDetails getStartLine(TimePoint at) { - return null; - } - - @Override - public LineDetails getFinishLine(TimePoint at) { - return null; - } - - @Override - public SpeedWithConfidence getAverageWindSpeedWithConfidence(long resolutionInMillis) { - return null; - } - - @Override - public SpeedWithConfidence getAverageWindSpeedWithConfidenceWithNumberOfSamples(int numberOfSamples) { - return null; - } - - @Override - public SpeedWithConfidence getAverageWindSpeedWithConfidence(TimePoint formTimePoint, - TimePoint toTimePoint, int numberOfSamples) { - return null; - } - - @Override - public Distance getCourseLength() { - return null; - } - - @Override - public Speed getSpeedWhenCrossingStartLine(Competitor competitor) { - return null; - } - - @Override - public Distance getDistanceFromStarboardSideOfStartLine(Competitor competitor, TimePoint timePoint) { - return null; - } - - @Override - public Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint timePoint, - boolean waitForLatestAnalysis) throws NoWindException { - return null; - } - - @Override - public Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint timePoint, - boolean waitForLatestAnalyses, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { - return null; - } - - @Override - public Distance getAverageSignedCrossTrackError(Competitor competitor, TimePoint from, TimePoint to, - boolean upwindOnly, boolean waitForLatestAnalysis) throws NoWindException { - return null; - } - - @Override - public void addRaceAbortedListener(RaceAbortedListener listener) { - } - - @Override - public void onAbortedByRaceCommittee(Flags flag) { - } - - @Override - public Position getCenterOfCourse(TimePoint at) { - return null; - } - - @Override - public boolean isUsingMarkPassingCalculator() { - return false; - } - - @Override - public void attachRegattaLog(RegattaLog regattaLog) { - } - - - @Override - public void waitForLoadingToFinish() throws InterruptedException { - } - - @Override - public Boolean isGateStart() { - return null; - } - - @Override - public Distance getDistanceTraveledIncludingGateStart(Competitor competitor, TimePoint timePoint) { - return null; - } - - @Override - public Distance getAdditionalGateStartDistance(Competitor competitor, TimePoint timePoint) { - return null; - } - - @Override - public GPSFixTrack getTrack(Mark mark) { - return null; - } - - @Override - public long getGateStartGolfDownTime() { - return 0; - } - - @Override - public int getLastLegStarted(TimePoint timePoint) { - return 0; - } - - @Override - public void setPolarDataService(PolarDataService polarDataService) { - } - - @Override - public TargetTimeInfo getEstimatedTimeToComplete(TimePoint timepoint) throws NotEnoughDataHasBeenAddedException, - NoWindException { - return null; - } - - @Override - public Distance getWindwardDistanceToCompetitorFarthestAhead(Competitor competitor, TimePoint timePoint, - WindPositionMode windPositionMode, RankingInfo rankingInfo, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { - return null; - } - - @Override - public Competitor getOverallLeader(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { - return null; - } - - @Override - public List getCompetitorsFromBestToWorst(TimePoint timePoint, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { - return null; - } - - @Override - public RankingMetric getRankingMetric() { - return null; - } - - @Override - public void detachRaceExecutionOrderProvider(RaceExecutionOrderProvider raceExecutionOrderProvider) { - } - - @Override - public void attachRaceExecutionProvider(RaceExecutionOrderProvider raceExecutionOrderProvider) { - } - - @Override - public IsManagedByCache resolve(DomainFactory domainFactory) { - return this; - } - - @Override - public void updateMarkPassingsAfterRaceLogChanges() { - } - - @Override - public void updateStartAndEndOfTracking(boolean waitForGPSFixesToLoad) { - } - - @Override - public void setFinishingTime(TimePoint newFinishingTime) { - } - - @Override - public void setFinishedTime(TimePoint newFinishedTime) { - } - - @Override - public > TrackT getSensorTrack( - Competitor competitor, String trackName) { - return null; - } - - @Override - public > TrackT getDynamicSensorTrack( - Competitor competitor, String trackName) { - return null; - } - - @Override - public > TrackT getOrCreateSensorTrack( - Competitor competitor, String trackName, TrackFactory newTrackFactory) { - return null; - } - - @Override - public boolean isWithinStartAndEndOfTracking(TimePoint timePoint) { - return true; - } - - @Override - public Iterable getAttachedRegattaLogs() { - return Collections.emptySet(); - } - - @Override - public void recordSensorFix(Competitor competitor, String trackName, SensorFix fix, - boolean onlyWhenInTrackingTimeInterval) { - } - - @Override - public void addSensorTrack(Competitor trackedItem, String trackName, DynamicSensorFixTrack track) { - } - - @Override - public Iterable getAttachedRaceLogs() { - return Collections.emptySet(); - } - - @Override - public NavigableSet getMarkPassings(Competitor competitor, boolean waitForLatestUpdates) { - return null; - } - - @Override - public Distance getAverageRideHeight(Competitor competitor, TimePoint timePoint) { - return null; - } - - @Override - public Boat getBoatOfCompetitor(Competitor competitor) { - return null; - } - - @Override - public Competitor getCompetitorOfBoat(Boat boat) { - return null; - } - - public Distance getEstimatedDistanceToComplete(TimePoint now) { - return null; - } - - @Override - public > Iterable getSensorTracks( - String trackName) { - return Collections.emptySet(); - } - - @Override - public Speed getAverageSpeedOverGround(Competitor competitor, TimePoint timePoint) { - return null; - } - - @Override - public Tack getTack(Position where, TimePoint timePoint, Bearing boatBearing) throws NoWindException { - return null; - } - - @Override - public SpeedWithBearing getVelocityMadeGood(Competitor competitor, TimePoint timePoint, - WindPositionMode windPositionMode, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { - return null; - } - - @Override - public WindSummary getWindSummary() { - return null; - } - - @Override - public PolarDataService getPolarDataService() { - return null; - } - - @Override - public void setWindEstimation(IncrementalWindEstimation windEstimation) { - } - - @Override - public TrackingConnectorInfo getTrackingConnectorInfo() { - return null; - } -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MyTestSailingService.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MyTestSailingService.java deleted file mode 100644 index c0e857afae9..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MyTestSailingService.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; -import com.sap.sailing.gwt.ui.client.SailingService; - -@RemoteServiceRelativePath("testsailing") -public interface MyTestSailingService extends SailingService { - -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MyTestSailingServiceAsync.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MyTestSailingServiceAsync.java deleted file mode 100644 index 84ac961c89d..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MyTestSailingServiceAsync.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; - -public interface MyTestSailingServiceAsync extends SailingServiceAsync { -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MyTestSailingServiceImpl.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MyTestSailingServiceImpl.java deleted file mode 100644 index c98b558f81f..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/MyTestSailingServiceImpl.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - - -public class MyTestSailingServiceImpl extends SailingServiceImplMock implements MyTestSailingService { - private static final long serialVersionUID = 3647254510616623048L; - - public MyTestSailingServiceImpl(){ - super(); - } -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PingMarkViaRegattaLogTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PingMarkViaRegattaLogTest.java deleted file mode 100644 index 8cf7b6a5a99..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/PingMarkViaRegattaLogTest.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import java.util.Collections; -import java.util.UUID; - -import org.junit.Before; -import org.junit.Test; - -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.Regatta; -import com.sap.sailing.domain.base.Series; -import com.sap.sailing.domain.base.impl.FleetImpl; -import com.sap.sailing.domain.base.impl.RegattaImpl; -import com.sap.sailing.domain.base.impl.SeriesImpl; -import com.sap.sailing.domain.common.CompetitorRegistrationType; -import com.sap.sailing.domain.common.NotFoundException; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.RankingMetrics; -import com.sap.sailing.domain.common.impl.DegreePosition; -import com.sap.sailing.domain.common.racelog.tracking.DoesNotHaveRegattaLogException; -import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; -import com.sap.sailing.domain.leaderboard.impl.HighPoint; -import com.sap.sailing.domain.ranking.RankingMetricsFactory; -import com.sap.sailing.gwt.ui.shared.MarkDTO; -import com.sap.sailing.server.interfaces.RacingEventService; - -public class PingMarkViaRegattaLogTest { - private SailingServiceImplMock sailingService; - private RacingEventService service; - private final String columnName = "column"; - private final Fleet fleet = new FleetImpl("fleet"); - - @Before - public void prepare() { - sailingService = new SailingServiceImplMock(); - service = sailingService.getRacingEventService(); - } - - @Test - public void testPinging() throws DoesNotHaveRegattaLogException, NotFoundException { - service.getMongoObjectFactory().getDatabase().drop(); - Series series = new SeriesImpl("series", false, /* isFleetsCanRunInParallel */ true, Collections.singletonList(fleet), - Collections.singletonList(columnName), service); - Regatta regatta = service.createRegatta(RegattaImpl.getDefaultName("regatta", "Laser"), "Laser", - /* canBoatsOfCompetitorsChangePerRace */ true, CompetitorRegistrationType.CLOSED, /* registrationLinkSecret */ null, /*startDate*/ null, /*endDate*/ null, - UUID.randomUUID(), Collections.singletonList(series), - false, new HighPoint(), UUID.randomUUID(), /*buoyZoneRadiusInHullLengths*/2.0, /* useStartTimeInference */ true, - /* controlTrackingFromStartAndFinishTimes */ false, /* autoRestartTrackingUponCompetitorSetChange */ false, RankingMetricsFactory.getRankingMetricConstructor(RankingMetrics.ONE_DESIGN)); - RegattaLeaderboard leaderboard = service.addRegattaLeaderboard(regatta.getRegattaIdentifier(), "RegattaLeaderboard", new int[] {}); - - MarkDTO mark = new MarkDTO("mark", "mark", "m"); - Position position = new DegreePosition(30, 40); - - sailingService.pingMark(leaderboard.getName(), mark, /* time point for fix */ null, position); - } -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/QualifiedObjectIdentifierCustomFieldSerializerTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/QualifiedObjectIdentifierCustomFieldSerializerTest.java deleted file mode 100755 index 9d6fe49ee54..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/QualifiedObjectIdentifierCustomFieldSerializerTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import static org.junit.Assert.assertEquals; - -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.google.gwt.user.client.rpc.SerializationException; -import com.google.gwt.user.client.rpc.SerializationStreamReader; -import com.google.gwt.user.client.rpc.SerializationStreamWriter; -import com.google.gwt.user.client.rpc.core.com.sap.sse.security.shared.impl.QualifiedObjectIdentifierImpl_CustomFieldSerializer; -import com.sap.sailing.domain.common.security.SecuredDomainType; -import com.sap.sse.security.shared.TypeRelativeObjectIdentifier; -import com.sap.sse.security.shared.impl.QualifiedObjectIdentifierImpl; - -/** - * See bug 4927 (https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=4927) - * - * @author Axel Uhl (d043530) - * - */ -public class QualifiedObjectIdentifierCustomFieldSerializerTest { - private QualifiedObjectIdentifierImpl_CustomFieldSerializer s; - private SerializationStreamReader reader; - private SerializationStreamWriter writer; - private PipedInputStream pis; - private PipedOutputStream pos; - private DataOutputStream dos; - - @Before - public void setUp() throws SerializationException, IOException { - s = new QualifiedObjectIdentifierImpl_CustomFieldSerializer(); - pos = new PipedOutputStream(); - pis = new PipedInputStream(pos); - reader = Mockito.mock(SerializationStreamReader.class); - writer = Mockito.mock(SerializationStreamWriter.class); - final DataInputStream dis = new DataInputStream(pis); - dos = new DataOutputStream(pos); - Mockito.when(reader.readString()).thenAnswer(invocation->dis.readUTF()); - Mockito.doAnswer(invocation->{ - dos.writeUTF(invocation.getArgumentAt(0, String.class)); - return null; - }).when(writer).writeString(Mockito.anyString()); - } - - @Test - public void testSerializationDeserialization() throws SerializationException, IOException { - final QualifiedObjectIdentifierImpl original = new QualifiedObjectIdentifierImpl(SecuredDomainType.TRACKED_RACE.getName(), - new TypeRelativeObjectIdentifier("2017Dec15_2019-02-27T10:01:08.886", "R2")); - s.serializeInstance(writer, original); - dos.flush(); - final QualifiedObjectIdentifierImpl read = s.instantiateInstance(reader); - assertEquals(original, read); - } -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/RegexpTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/RegexpTest.java deleted file mode 100755 index a73af768d6b..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/RegexpTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -import com.google.gwt.regexp.shared.MatchResult; -import com.google.gwt.regexp.shared.RegExp; - -public class RegexpTest { - RegExp regexp = RegExp.compile("^([A-Z][A-Z][A-Z])[^0-9]*([0-9]*)$"); - - @Test - public void testSailIDParsing() { - String sailID = "GER 61"; - String result = null; - MatchResult m = regexp.exec(sailID); - if (regexp.test(sailID)) { - String iocCode = m.getGroup(1); - if (iocCode != null && iocCode.trim().length() > 0) { - String number = m.getGroup(2); - result = iocCode + number; - } - } - assertEquals("GER61", result); - } -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/SafeHtmlHeaderWithTooltipTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/SafeHtmlHeaderWithTooltipTest.java deleted file mode 100644 index ed36926f0d7..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/SafeHtmlHeaderWithTooltipTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -import com.google.gwt.safehtml.shared.SafeHtmlBuilder; -import com.sap.sailing.gwt.ui.leaderboard.SafeHtmlHeaderWithTooltip; - -public class SafeHtmlHeaderWithTooltipTest { - - @Test - public void textCreation() { - SafeHtmlBuilder titleBuilder = new SafeHtmlBuilder().appendEscaped("Title Text"); - SafeHtmlHeaderWithTooltip header = new SafeHtmlHeaderWithTooltip(titleBuilder.toSafeHtml(), "Tooltip"); - assertEquals("Title Text", header.getValue().asString()); - - titleBuilder = new SafeHtmlBuilder().appendEscapedLines("Title\nText"); - header = new SafeHtmlHeaderWithTooltip(titleBuilder.toSafeHtml(), "Tooltip"); - assertEquals("Title
Text", header.getValue().asString()); - - titleBuilder = new SafeHtmlBuilder().appendEscaped("Title Text"); - header = new SafeHtmlHeaderWithTooltip(titleBuilder.toSafeHtml(), "Tooltip with\nline break."); - assertEquals("Title Text", header.getValue().asString()); - } - -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/SailingServiceImplMock.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/SailingServiceImplMock.java deleted file mode 100755 index 22296f411da..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/SailingServiceImplMock.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import java.io.IOException; -import java.net.UnknownHostException; -import java.text.ParseException; -import java.util.Collections; -import java.util.List; - -import javax.xml.bind.JAXBException; - -import com.sap.sailing.domain.base.BoatClass; -import com.sap.sailing.domain.base.DomainFactory; -import com.sap.sailing.domain.common.RegattaIdentifier; -import com.sap.sailing.domain.common.ScoreCorrectionProvider; -import com.sap.sailing.domain.racelog.RaceLogStore; -import com.sap.sailing.domain.racelog.tracking.test.mock.MockSmartphoneImeiServiceFinderFactory; -import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapterFactory; -import com.sap.sailing.domain.regattalog.RegattaLogStore; -import com.sap.sailing.domain.swisstimingadapter.StartList; -import com.sap.sailing.domain.swisstimingadapter.SwissTimingAdapter; -import com.sap.sailing.domain.swisstimingadapter.SwissTimingAdapterFactory; -import com.sap.sailing.domain.swisstimingadapter.SwissTimingFactory; -import com.sap.sailing.domain.swisstimingreplayadapter.SwissTimingReplayService; -import com.sap.sailing.domain.tracking.RaceHandle; -import com.sap.sailing.domain.tracking.TrackerManager; -import com.sap.sailing.domain.tractracadapter.TracTracAdapterFactory; -import com.sap.sailing.gwt.ui.server.SailingServiceImpl; -import com.sap.sailing.server.impl.RacingEventServiceImpl; -import com.sap.sailing.server.interfaces.RacingEventService; -import com.sap.sailing.xrr.schema.RegattaResults; -import com.sap.sse.replication.Replicable; -import com.sap.sse.replication.ReplicationService; -import com.sap.sse.replication.impl.AbstractReplicablesProvider; -import com.sap.sse.replication.impl.ReplicationInstancesManager; -import com.sap.sse.replication.impl.ReplicationServiceImpl; - -public class SailingServiceImplMock extends SailingServiceImpl { - private static final long serialVersionUID = 8564037671550730455L; - - private final RacingEventService service; - private ReplicationService replicationService; - private final ScoreCorrectionProvider scoreCorrectionProvider = null; - private final TracTracAdapterFactory tracTracAdapterFactory = TracTracAdapterFactory.INSTANCE; - private final SwissTimingAdapterFactory swissTimingAdapterFactory; - private final SwissTimingReplayService swissTimingReplayService = null; - private final RaceLogTrackingAdapterFactory raceLogTrackingAdapterFactory = RaceLogTrackingAdapterFactory.INSTANCE; - - public SailingServiceImplMock() { - super(); - service = new RacingEventServiceImpl(/* clearPersistentCompetitorStore */ true, new MockSmartphoneImeiServiceFinderFactory(), /* restoreTrackedRaces */ false); - try { - replicationService = new ReplicationServiceImpl("test exchange", "localhost", 0, - new ReplicationInstancesManager(), new AbstractReplicablesProvider() { - @Override - public Iterable> getReplicables() { - return Collections.> singleton(service); - } - }); - } catch (IOException e) { - e.printStackTrace(); - } - swissTimingAdapterFactory = new SwissTimingAdapterFactory() { - @Override - public SwissTimingAdapter getOrCreateSwissTimingAdapter(DomainFactory baseDomainFactory) { - return new SwissTimingAdapter() { - @Override - public List getSwissTimingRaceRecords( - String hostname, int port) throws InterruptedException, UnknownHostException, IOException, - ParseException { - // TODO Auto-generated method stub - return null; - } - - @Override - public RaceHandle addSwissTimingRace(TrackerManager trackerManager, - RegattaIdentifier regattaToAddTo, String raceID, String raceName, String raceDescription, - BoatClass boatClass, String hostname, int port, StartList startList, RaceLogStore logStore, - RegattaLogStore regattaLogStore, long timeoutInMilliseconds, boolean useInternalMarkPassingAlgorithm, boolean trackWind, boolean correctWindDirectionByMagneticDeclination, String updateURL, String updateUsername, String updatePassword, String eventName, String manage2SailEventUrl) throws InterruptedException, - UnknownHostException, IOException, ParseException, Exception { - // TODO Auto-generated method stub - return null; - } - - @Override - public SwissTimingFactory getSwissTimingFactory() { - // TODO Auto-generated method stub - return null; - } - - @Override - public com.sap.sailing.domain.swisstimingadapter.DomainFactory getSwissTimingDomainFactory() { - return com.sap.sailing.domain.swisstimingadapter.DomainFactory.INSTANCE; - } - - @Override - public StartList readStartListForRace(String raceId, RegattaResults regattaResults) { - // TODO Auto-generated method stub - return null; - } - - @Override - public RegattaResults readRegattaEntryListFromXrrUrl(String xrrEntryListUrl) throws IOException, - JAXBException { - // TODO Auto-generated method stub - return null; - } - }; - } - }; - } - - public ScoreCorrectionProvider getScoreCorrectionProvider() { - return scoreCorrectionProvider; - } - - @Override - protected TracTracAdapterFactory getTracTracAdapterFactory() { - return tracTracAdapterFactory; - } - - @Override - protected SwissTimingAdapterFactory getSwissTimingAdapterFactory() { - return swissTimingAdapterFactory; - } - - @Override - protected SwissTimingReplayService getSwissTimingReplayService() { - return swissTimingReplayService; - } - - @Override - protected RaceLogTrackingAdapterFactory getRaceLogTrackingAdapterFactory() { - return raceLogTrackingAdapterFactory; - } - - @Override - protected ReplicationService getReplicationService() { - return replicationService; - } - - @Override - protected RacingEventService getService() { - return service; - } - - public RacingEventService getRacingEventService() { - return getService(); - } -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/SlicingTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/SlicingTest.java deleted file mode 100644 index 3414f6e3909..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/SlicingTest.java +++ /dev/null @@ -1,140 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.UUID; - -import org.apache.shiro.subject.Subject; -import org.apache.shiro.subject.support.SubjectThreadState; -import org.apache.shiro.util.ThreadState; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.mockito.Mockito; - -import com.sap.sailing.domain.common.BoatClassMasterdata; -import com.sap.sailing.domain.common.CompetitorDescriptor; -import com.sap.sailing.domain.common.CompetitorRegistrationType; -import com.sap.sailing.domain.common.LeaderboardNameConstants; -import com.sap.sailing.domain.common.RankingMetrics; -import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.domain.common.RegattaName; -import com.sap.sailing.domain.common.ScoringSchemeType; -import com.sap.sailing.domain.common.abstractlog.TimePointSpecificationFoundInLogImpl; -import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTO; -import com.sap.sailing.domain.common.dto.FleetDTO; -import com.sap.sailing.domain.common.dto.RaceColumnDTO; -import com.sap.sailing.domain.common.dto.RaceDTO; -import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO; -import com.sap.sailing.domain.common.dto.SeriesCreationParametersDTO; -import com.sap.sailing.domain.common.dto.TrackedRaceDTO; -import com.sap.sailing.gwt.ui.adminconsole.RaceLogSetTrackingTimesDTO; -import com.sap.sailing.gwt.ui.shared.DeviceIdentifierDTO; -import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO; -import com.sap.sailing.gwt.ui.shared.RegattaDTO; -import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; -import com.sap.sse.common.TimePoint; -import com.sap.sse.common.Util.Pair; -import com.sap.sse.common.Util.Triple; -import com.sap.sse.common.impl.CountryCodeFactoryImpl; -import com.sap.sse.common.impl.MillisecondsTimePoint; -import com.sap.sse.util.ClearStateTestSupport; - -import org.junit.Assert; - -public class SlicingTest { - private final String regattaName = "test"; - private final String boatClassName = BoatClassMasterdata.TP52.name(); - private final TimePoint startOriginalRace = new MillisecondsTimePoint(0); - private final TimePoint endOriginalRace = new MillisecondsTimePoint(300); - private final TimePoint startSlicedRace = new MillisecondsTimePoint(100); - private final TimePoint endSlicedRace = new MillisecondsTimePoint(200); - private final String seriesName = LeaderboardNameConstants.DEFAULT_SERIES_NAME; - private final String fleetName = "default"; - private final String columnNameOriginalRace = "original"; - private final String columnNameSlicedRace = "sliced"; - - private final CompetitorDescriptor competitor = new CompetitorDescriptor(null, regattaName, columnNameOriginalRace, fleetName, null, - "test1", "test", "test", null, CountryCodeFactoryImpl.INSTANCE.getFromTwoLetterISOName("de"), - 1.0, null, null, "B1", boatClassName, "GER 123"); - - private SailingServiceImplMock sailingService; - - private ThreadState threadState; - protected Subject subject; - - @Before - public void setUp() throws Exception { - sailingService = new SailingServiceImplMock(); - ((ClearStateTestSupport)(sailingService.getRacingEventService())).clearState(); - - subject = Mockito.mock(Subject.class); - threadState = new SubjectThreadState(subject); - threadState.bind(); - } - - @After - public void tearDown() throws Exception { - threadState.clear(); - ((ClearStateTestSupport)(sailingService.getRacingEventService())).clearState(); - } - - @Test - @Ignore - /** - * Currently non functional test case for race slicing. Should be finished when SailingServiceImplMock is fixed to - * work properly for test cases. See bug 4418 for details. - */ - public void testSliceRace() throws Exception { - final LinkedHashMap seriesCreationParameters = new LinkedHashMap<>(); - final List fleets = new ArrayList<>(); - fleets.add(new FleetDTO(fleetName, 0, null)); - seriesCreationParameters.put(seriesName, - new SeriesCreationParametersDTO(fleets, false, false, true, false, new int[0], false, 0)); - final RegattaCreationParametersDTO regattaCreationParameters = new RegattaCreationParametersDTO( - seriesCreationParameters); - final RegattaDTO regatta = sailingService.createRegatta(regattaName, boatClassName, false, - CompetitorRegistrationType.CLOSED, null, null, null, regattaCreationParameters, false, - ScoringSchemeType.HIGH_POINT, null, 3.0, false, false, /* autoRestartTrackingUponCompetitorSetChange */ false, RankingMetrics.ONE_DESIGN); - final List> columnNames = new ArrayList<>(); - columnNames.add(new Pair<>(columnNameOriginalRace, 0)); - sailingService.addRaceColumnsToSeries(regatta.getRegattaIdentifier(), seriesName, columnNames); - sailingService.createRegattaLeaderboard(new RegattaName(regatta.getName()), regattaName, new int[0]); - final List competitors = sailingService.addCompetitors(Arrays.asList(competitor), null); - final CompetitorWithBoatDTO competitorDTO = competitors.iterator().next(); - sailingService.setCompetitorRegistrationsInRegattaLog(regattaName, new HashSet<>(competitors)); - DeviceIdentifierDTO deviceId = new DeviceIdentifierDTO("FILE", UUID.randomUUID().toString()); - final DeviceMappingDTO deviceMapping = new DeviceMappingDTO(deviceId, startOriginalRace.asDate(), endOriginalRace.asDate(), competitorDTO, null); - sailingService.addDeviceMappingToRegattaLog(regattaName, deviceMapping); - final List> leaderboardRaceColumnFleetNames = new ArrayList<>(); - leaderboardRaceColumnFleetNames.add(new Triple<>(regattaName, columnNameOriginalRace, fleetName)); - RaceLogSetTrackingTimesDTO raceLogSetTrackingTimes = new RaceLogSetTrackingTimesDTO(); - raceLogSetTrackingTimes.leaderboardName = regattaName; - raceLogSetTrackingTimes.authorName = "Test"; - raceLogSetTrackingTimes.raceColumnName = columnNameOriginalRace; - raceLogSetTrackingTimes.fleetName = fleetName; - raceLogSetTrackingTimes.newStartOfTracking = new TimePointSpecificationFoundInLogImpl(startOriginalRace); - raceLogSetTrackingTimes.newEndOfTracking = new TimePointSpecificationFoundInLogImpl(endOriginalRace); - sailingService.setTrackingTimes(raceLogSetTrackingTimes); - sailingService.startRaceLogTracking(leaderboardRaceColumnFleetNames , true, false); - // TODO add wind fixes - - final StrippedLeaderboardDTO leaderboard = sailingService.getLeaderboard(regattaName); - final RaceColumnDTO columnOfOriginalRace = leaderboard.getRaceList().iterator().next(); - final RaceDTO originalRace = columnOfOriginalRace.getRace(columnOfOriginalRace.getFleets().iterator().next()); - final RegattaAndRaceIdentifier raceIdentifierOfOriginalRace = originalRace.getRaceIdentifier(); - final RegattaAndRaceIdentifier sliceRaceIdentifier = sailingService.sliceRace(raceIdentifierOfOriginalRace, columnNameSlicedRace, startSlicedRace, endSlicedRace); - final StrippedLeaderboardDTO leaderboard2 = sailingService.getLeaderboard(regattaName); - final RaceColumnDTO columnOfSlicedRace = leaderboard2.getRaceColumnByName(columnNameSlicedRace); - final RaceDTO slicedRace = columnOfSlicedRace.getRace(columnOfOriginalRace.getFleets().iterator().next()); - Assert.assertEquals(slicedRace.getRaceIdentifier(), sliceRaceIdentifier); - final TrackedRaceDTO trackedRace = slicedRace.trackedRace; - Assert.assertEquals(startSlicedRace.asDate(), trackedRace.startOfTracking); - Assert.assertEquals(endSlicedRace.asDate(), trackedRace.endOfTracking); - } - -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/TestColumnSwapping.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/TestColumnSwapping.java deleted file mode 100755 index fbc3075e6cd..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/TestColumnSwapping.java +++ /dev/null @@ -1,165 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.UUID; - -import org.junit.Before; -import org.junit.Test; - -import com.sap.sailing.domain.common.BoatClassMasterdata; -import com.sap.sailing.domain.common.ScoringSchemeType; -import com.sap.sailing.domain.common.dto.BoatClassDTO; -import com.sap.sailing.domain.common.dto.FleetDTO; -import com.sap.sailing.domain.common.dto.LeaderboardDTO; -import com.sap.sailing.domain.common.dto.RaceColumnDTO; -import com.sap.sailing.gwt.ui.server.SailingServiceImpl; - -public class TestColumnSwapping { - - private LeaderboardDTO lb = null; - private static final String LEADERBOARDNAME = "test"; - private static final String DEFAULT_FLEET_NAME = "Default"; - private static final FleetDTO DEFAULT_FLEET = new FleetDTO(DEFAULT_FLEET_NAME, /* ordering */ 0, /* color */ null); - private SailingServiceImpl service; - private LeaderboardDTO leaderboardOriginalDTO; - private LeaderboardDTO leaderboardDTO; - private Collection leglist; - private Date leaderboardCreationDate; - private SailingServiceImpl sailingService = null; - - // Test-Data - private final String TEST_LEADERBOARD_NAME = "test_board"; - private final String[] races = { "1", "2", "3" }; - private final boolean[] isMedalRace = { false, false, true }; - - @Before - public void prepareColumnSwapping() { - service = new SailingServiceImplMock(); - int[] disc = { 5, 8, 9, 0, 7, 5, 43 }; - service.removeLeaderboard(LEADERBOARDNAME); - service.createFlexibleLeaderboard(LEADERBOARDNAME, null, disc, ScoringSchemeType.LOW_POINT, null); - service.addColumnToLeaderboard("Race1", LEADERBOARDNAME, true); - service.addColumnToLeaderboard("Race2", LEADERBOARDNAME, true); - service.addColumnToLeaderboard("Race3", LEADERBOARDNAME, true); - leglist = new ArrayList(); - leglist.add("Race1"); - leglist.add("Race2"); - leglist.add("Race3"); - leaderboardCreationDate = new Date(); - try { - // get Leaderboard with name and current date - leaderboardOriginalDTO = new LeaderboardDTO(new Date(), null, null, ScoringSchemeType.LOW_POINT, /* higherScoreIsBetter */ false, new LeaderboardDTO.UUIDGenerator() { - @Override - public String generateRandomUUID() { - return UUID.randomUUID().toString(); - } - }, /* hasOverallDetails */ false, new BoatClassDTO(BoatClassMasterdata._49ER.getDisplayName(), BoatClassMasterdata._49ER.getHullLength(), BoatClassMasterdata._49ER.getHullBeam())); - leaderboardOriginalDTO.addRace("Race1", /* explicitFactor */ null, 2., /* regattaName */ null, /* seriesName */ null, DEFAULT_FLEET, true, null, null, false); - leaderboardOriginalDTO.addRace("Race3", /* explicitFactor */ null, 2., /* regattaName */ null, /* seriesName */ null, DEFAULT_FLEET, true, null, null, false); - leaderboardOriginalDTO.addRace("Race2", /* explicitFactor */ null, 2., /* regattaName */ null, /* seriesName */ null, DEFAULT_FLEET, true, null, null, false); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void testColumnSwapping() { - testColumnSwappingFabian(); - testLeaderBoardDTOMethods(); - testSailingService(); - } - - @Test - public void testSailingService() { - sailingService = new SailingServiceImplMock(); - assertNotNull("Sailingservice != NULL", sailingService); - int td[] = { 5, 8 }; - sailingService.removeLeaderboard(TEST_LEADERBOARD_NAME); - sailingService.createFlexibleLeaderboard(TEST_LEADERBOARD_NAME, null, td, - ScoringSchemeType.LOW_POINT, null); - for (int i = 0; i < races.length; i++) - sailingService.addColumnToLeaderboard(races[i], TEST_LEADERBOARD_NAME, isMedalRace[i]); - sailingService.moveLeaderboardColumnDown(TEST_LEADERBOARD_NAME, races[0]); - sailingService.moveLeaderboardColumnDown(TEST_LEADERBOARD_NAME, races[0]); - sailingService.moveLeaderboardColumnUp(TEST_LEADERBOARD_NAME, races[2]); - sailingService.updateIsMedalRace(TEST_LEADERBOARD_NAME, races[0], true); - sailingService.updateIsMedalRace(TEST_LEADERBOARD_NAME, races[2], false); - try { - for (int i = 0; i < races.length; i++) - sailingService.addColumnToLeaderboard(races[i], TEST_LEADERBOARD_NAME, isMedalRace[i]); - sailingService.moveLeaderboardColumnDown(TEST_LEADERBOARD_NAME, races[0]); - sailingService.moveLeaderboardColumnDown(TEST_LEADERBOARD_NAME, races[0]); - sailingService.moveLeaderboardColumnUp(TEST_LEADERBOARD_NAME, races[2]); - sailingService.updateIsMedalRace(TEST_LEADERBOARD_NAME, races[0], true); - sailingService.updateIsMedalRace(TEST_LEADERBOARD_NAME, races[2], false); - lb = sailingService.getLeaderboardByName(TEST_LEADERBOARD_NAME, new Date(), /* races to load */ null, /* addOverallDetails */ true, /* previous leaderboard ID */ null, - /* fillTotalPointsUncorrected */ false).getLeaderboardDTO(/* previousVersion */ null); - } catch (Exception e) { - // e.printStackTrace(); - fail(e.getLocalizedMessage()); - } - assertNotNull("LeaderboardDTO != NULL", lb); - - // asserted data - String[] raceNames = new String[] { "3", "2", "1" }; - boolean[] medalRace = { true, false, false }; - - for (int i = 0; i < lb.getRaceList().size(); i++) { - assertEquals("Race[" + i + "] == " + raceNames[i], raceNames[i], lb.getRaceList().get(i).getName()); - assertTrue("Race[" + i + "] is " + (medalRace[i] ? "" : "no ") + "medalrace.", - lb.raceIsMedalRace(races[i]) == medalRace[i]); - } - } - - @Test - public void testLeaderBoardDTOMethods() { - lb = new LeaderboardDTO(new Date(), null, null, ScoringSchemeType.LOW_POINT, /* higherScoreIsBetter */ false, new LeaderboardDTO.UUIDGenerator() { - @Override - public String generateRandomUUID() { - return UUID.randomUUID().toString(); - } - }, /* hasOverallDetails */ false, new BoatClassDTO(BoatClassMasterdata._49ER.getDisplayName(), BoatClassMasterdata._49ER.getHullLength(), BoatClassMasterdata._49ER.getHullBeam())); - assertNotNull("Leaderboard != NULL", lb); - lb.addRace("1", /* explicitFactor */ null, 1., /* regattaName */ null, /* seriesName */ null, DEFAULT_FLEET, false, null, null, false); - lb.addRace("2", /* explicitFactor */ null, 1., /* regattaName */ null, /* seriesName */ null, DEFAULT_FLEET, false, null, null, false); - lb.addRace("3", /* explicitFactor */ null, 1., /* regattaName */ null, /* seriesName */ null, DEFAULT_FLEET, true, null, null, false); - lb.moveRaceDown("1"); - String[] s = new String[] { "2", "1", "3" }; - for (int i = 0; i < lb.getRaceList().size(); i++) { - assertEquals("Race[" + i + "] = " + s[i], s[i], lb.getRaceList().get(i).getName()); - } - } - - @Test - public void testColumnSwappingFabian() { - service.moveLeaderboardColumnUp(LEADERBOARDNAME, "Race3"); - try { - leaderboardDTO = service.getLeaderboardByName(LEADERBOARDNAME, leaderboardCreationDate, leglist, /* addOverallDetails */ - true, /* previous leaderboard ID */null, /* fillTotalPointsUncorrected */false).getLeaderboardDTO(/* previousVersion */null); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - // check if leaderboardDTO an dleaderboardOriginalDTO same - List leaderboardList = leaderboardDTO.getRaceList(); - List leaderboardOriginalList = leaderboardOriginalDTO.getRaceList(); - - // ??????? assert races in list - assertArrayEquals(leaderboardList.toArray(), leaderboardOriginalList.toArray()); - - for (RaceColumnDTO raceDTO : leaderboardOriginalList) { - assert leaderboardDTO.raceIsMedalRace(raceDTO.getRaceColumnName()) == leaderboardOriginalDTO.raceIsMedalRace(raceDTO.getRaceColumnName()); - assert leaderboardDTO.raceIsTracked(raceDTO.getRaceColumnName()) == leaderboardOriginalDTO.raceIsTracked(raceDTO.getRaceColumnName()); - } - } -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/TestWindChartPointRecalculation.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/TestWindChartPointRecalculation.java deleted file mode 100644 index 59d0010822b..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/TestWindChartPointRecalculation.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import static org.hamcrest.Matchers.closeTo; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertThat; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.junit.Test; -import org.moxieapps.gwt.highcharts.client.Point; - -import com.sap.sailing.gwt.ui.client.shared.charts.ChartPointRecalculator; - -public class TestWindChartPointRecalculation { - - private static final double POINT_Y_EQUALITY_EPSILON = 0.005; - - private static final List MULTIPLE_WRAP_AROUNDS = Arrays.asList(356.74, 10.54, 30.192, 20.625, 5.647, 350.526); - private static final List EXPECTED_RECALCULATED_VALUES_FOR_MULTIPLE_WRAP_AROUNDS = Arrays.asList(356.74, 10.54 + 360, 30.192 + 360, 20.625 + 360, 5.647 + 360, 350.526); - - private static final List CONTINOUS_WRAP_AROUNDS = Arrays.asList(5.34, 358.97, 10.42, 50.0, 110.65, 140.54, - 210.85, 280.38, 330.5, 358.97, 7.24, 48.0, 112.65, 135.54, 215.85, 278.38, 333.5, 356.97, 8.24, 48.245, - 112.57, 133.54, 215.637, 278.38, 333.5, 356.97); - private static final List EXPECTED_RECALCULATED_VALUES_FOR_CONTINOUS_WRAP_AROUNDS_OVERALL_DELTA_MINIMUM = Arrays.asList( - 5.34, 358.97 - 360, 10.42, 50.0, 110.65, 140.54, 210.85 - 360, 280.38 - 360, 330.5 - 360, - 358.97 - 360, 7.24, 48.0, 112.65, 135.54, 215.85 - 360, 278.38 - 360, 333.5 - 360, 356.97 - 360, - 8.24, 48.245, 112.57, 133.54, 215.637 - 360, 278.38 - 360, 333.5 - 360, 356.97 - 360); - private static final List EXPECTED_RECALCULATED_VALUES_FOR_CONTINOUS_WRAP_AROUNDS_CLOSEST_TO_PREVIOUS_POINT = Arrays.asList( - 5.34, 358.97 - 360, 10.42, 50.0, 110.65, 140.54, 210.85, 280.38, 330.5, 358.97, 367.24, 408.0, 472.65, - 135.54 + 360, 575.85, 638.38, 693.5, 716.97, 728.24, 768.245, 112.57 + 720, 853.54, 935.637, 998.38, 1053.5, - 1076.97); - - private static void pointYEquals(Point actual, double expectedY) { - assertThat(actual.getY().doubleValue(), closeTo(expectedY, POINT_Y_EQUALITY_EPSILON)); - } - - @Test - public void testClosestToPreviousPointRecalculation() { - Point previousPoint = new Point(9, 20); - - Point notToBeRecalculated = new Point(10, 100); - pointYEquals(ChartPointRecalculator.stayClosestToPreviousPoint(previousPoint, notToBeRecalculated), notToBeRecalculated.getY().doubleValue()); - - notToBeRecalculated = new Point(10, 5); - pointYEquals(ChartPointRecalculator.stayClosestToPreviousPoint(previousPoint, notToBeRecalculated), notToBeRecalculated.getY().doubleValue()); - - Point toBeMovedDown = new Point(10, 358); - pointYEquals(ChartPointRecalculator.stayClosestToPreviousPoint(previousPoint, toBeMovedDown), -2); - - previousPoint = new Point(9, 350); - Point toBeMovedUp = new Point(10, 2); - pointYEquals(ChartPointRecalculator.stayClosestToPreviousPoint(previousPoint, toBeMovedUp), 362); - } - - @Test - public void testOverallDeltaMinimalRecalculaion() { - Point notToBeRecalculated = new Point(10, 100); - assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(90.0, 110.0, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY())); - assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(null, 110.0, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY())); - assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(90.0, null, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY())); - assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(100.27458, 110.0, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY())); - assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(90.0, 100.75639, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY())); - - //Test for special case, which caused a wrong recalculation, because of the wrong use of Math.abs() - notToBeRecalculated = new Point(10, 179.8537); - assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(180.12356, 190.0, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY())); - assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(170.0, 179.5372, notToBeRecalculated).getY(), equalTo(notToBeRecalculated.getY())); - - Point toBeMovedDown = new Point(10, 356); - assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(4.0, 23.0, toBeMovedDown).getY(), equalTo(new Point(10, 356.0 - 360.0).getY())); - - Point toBeMovedUp = new Point(10, 5); - assertThat(ChartPointRecalculator.keepOverallDeltaMinimal(356.0, 359.83364, toBeMovedUp).getY(), equalTo(new Point(10, 5.0 + 360.0).getY())); - } - - @Test - public void testClosestToPreviousPointWithMultipleAndContiniusWrapArounds() { - //Test multiple wrap around between 350 and 30 - assertThat(recalculatePointsClosestToPreviousPoint(MULTIPLE_WRAP_AROUNDS), equalTo(EXPECTED_RECALCULATED_VALUES_FOR_MULTIPLE_WRAP_AROUNDS)); - - //Test multiple round trips from 0 to 360 - assertThat(recalculatePointsClosestToPreviousPoint(CONTINOUS_WRAP_AROUNDS), equalTo(EXPECTED_RECALCULATED_VALUES_FOR_CONTINOUS_WRAP_AROUNDS_CLOSEST_TO_PREVIOUS_POINT)); - } - - private List recalculatePointsClosestToPreviousPoint(List points) { - List racalculatedPoints = new ArrayList(); - Point previousPoint = null; - for (Double yValue : points) { - Point newPoint = new Point(10, yValue); - if (previousPoint != null) { - newPoint = ChartPointRecalculator.stayClosestToPreviousPoint(previousPoint, newPoint); - } - racalculatedPoints.add(newPoint.getY().doubleValue()); - previousPoint = newPoint; - } - return racalculatedPoints; - } - - @Test - public void testOverallDeltaMinimalWithMultipleAndContinuousWrapArounds() { - //Test multiple wrap around between 350 and 30 - assertThat(recalculatePointsWithOverallDeltaMinimal(MULTIPLE_WRAP_AROUNDS), equalTo(EXPECTED_RECALCULATED_VALUES_FOR_MULTIPLE_WRAP_AROUNDS)); - - //Test multiple round trips from 0 to 360 - assertThat(recalculatePointsWithOverallDeltaMinimal(CONTINOUS_WRAP_AROUNDS), equalTo(EXPECTED_RECALCULATED_VALUES_FOR_CONTINOUS_WRAP_AROUNDS_OVERALL_DELTA_MINIMUM)); - } - - private List recalculatePointsWithOverallDeltaMinimal(List pointYValues) { - List recalculatedPointYValues = new ArrayList(); - Double min = null; - Double max = null; - for (Double yValue : pointYValues) { - Point p = new Point(10, yValue); - p = ChartPointRecalculator.keepOverallDeltaMinimal(min, max, p); - Double newYValue = p.getY().doubleValue(); - recalculatedPointYValues.add(newYValue); - - if (min == null || newYValue < min) { - min = newYValue; - } - if (max == null || newYValue > max) { - max = newYValue; - } - } - return recalculatedPointYValues; - } - -} diff --git a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/WindGridColorPaletteTest.java b/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/WindGridColorPaletteTest.java deleted file mode 100644 index 47afd6a2753..00000000000 --- a/java/com.sap.sailing.gwt.ui.test/src/com/sap/sailing/gwt/ui/test/WindGridColorPaletteTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.sap.sailing.gwt.ui.test; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -import com.sap.sailing.gwt.ui.simulator.util.WindGridColorPalette; - -public class WindGridColorPaletteTest { - - @Test - public void test() { - int min = 10; - int max = 100; - WindGridColorPalette cp = new WindGridColorPalette(min,max); - - //assertEquals("Lightest color", "#FFFFFF", cp.getColor(min)); - //assertEquals("Darkest color", "#0000FF", cp.getColor(max)); - - //assertEquals("In between color", "#7F7FFF", cp.getColor((max+min)/2)); - - assertEquals("Lightest color", "#FFFFFF", cp.getColor(min)); - assertEquals("Darkest color", "#4B7FBB", cp.getColor(max)); - - assertEquals("In between color", "#A5BFDD", cp.getColor((max+min)/2)); - } - -} diff --git a/java/com.sap.sailing.gwt.ui/.settings/com.gwtplugins.gwt.eclipse.core.prefs b/java/com.sap.sailing.gwt.ui/.settings/com.gwtplugins.gwt.eclipse.core.prefs index fb32c70cc69..1f6ee646737 100644 --- a/java/com.sap.sailing.gwt.ui/.settings/com.gwtplugins.gwt.eclipse.core.prefs +++ b/java/com.sap.sailing.gwt.ui/.settings/com.gwtplugins.gwt.eclipse.core.prefs @@ -1,3 +1,4 @@ eclipse.preferences.version=1 entryPointModules= filesCopiedToWebInfLib= +gwtCompileSettings=PGd3dC1jb21waWxlLXNldHRpbmdzPjxsb2ctbGV2ZWw+SU5GTzwvbG9nLWxldmVsPjxvdXRwdXQtc3R5bGU+T0JGVVNDQVRFRDwvb3V0cHV0LXN0eWxlPjxleHRyYS1hcmdzPjwhW0NEQVRBWy1sb2NhbFdvcmtlcnMgMTAgIC13YXIgLi9dXT48L2V4dHJhLWFyZ3M+PHZtLWFyZ3M+PCFbQ0RBVEFbLVhteDJnXV0+PC92bS1hcmdzPjxlbnRyeS1wb2ludC1tb2R1bGU+Y29tLnNhcC5zYWlsaW5nLmd3dC51aS5TaW11bGF0b3I8L2VudHJ5LXBvaW50LW1vZHVsZT48ZW50cnktcG9pbnQtbW9kdWxlPmNvbS5zYXAuc2FpbGluZy5nd3QudWkuTGVhZGVyYm9hcmQ8L2VudHJ5LXBvaW50LW1vZHVsZT48ZW50cnktcG9pbnQtbW9kdWxlPmNvbS5zYXAuc2FpbGluZy5nd3QuaG9tZS5Ib21lPC9lbnRyeS1wb2ludC1tb2R1bGU+PGVudHJ5LXBvaW50LW1vZHVsZT5jb20uc2FwLnNhaWxpbmcuZ3d0LnVpLlNwZWN0YXRvcjwvZW50cnktcG9pbnQtbW9kdWxlPjxlbnRyeS1wb2ludC1tb2R1bGU+Y29tLnNhcC5zYWlsaW5nLmd3dC51aS5BZG1pbkNvbnNvbGU8L2VudHJ5LXBvaW50LW1vZHVsZT48ZW50cnktcG9pbnQtbW9kdWxlPmNvbS5zYXAuc2FpbGluZy5nd3QudWkuWW91dHViZVBvcHVwPC9lbnRyeS1wb2ludC1tb2R1bGU+PGVudHJ5LXBvaW50LW1vZHVsZT5jb20uc2FwLnNhaWxpbmcuZ3d0LnVpLkRhdGFNaW5pbmc8L2VudHJ5LXBvaW50LW1vZHVsZT48ZW50cnktcG9pbnQtbW9kdWxlPmNvbS5zYXAuc2FpbGluZy5nd3QucmVnYXR0YW92ZXJ2aWV3LlJlZ2F0dGFPdmVydmlldzwvZW50cnktcG9pbnQtbW9kdWxlPjxlbnRyeS1wb2ludC1tb2R1bGU+Y29tLnNhcC5zYWlsaW5nLmd3dC51aS5WaWRlb1BvcHVwPC9lbnRyeS1wb2ludC1tb2R1bGU+PGVudHJ5LXBvaW50LW1vZHVsZT5jb20uc2FwLnNhaWxpbmcuZ3d0LnVpLkVtYmVkZGVkTWFwQW5kV2luZENoYXJ0PC9lbnRyeS1wb2ludC1tb2R1bGU+PGVudHJ5LXBvaW50LW1vZHVsZT5jb20uc2FwLnNhaWxpbmcuZ3d0LnVpLlBhaXJpbmdMaXN0PC9lbnRyeS1wb2ludC1tb2R1bGU+PGVudHJ5LXBvaW50LW1vZHVsZT5jb20uc2FwLnNhaWxpbmcuZ3d0LnVpLkxlYWRlcmJvYXJkRWRpdGluZzwvZW50cnktcG9pbnQtbW9kdWxlPjxlbnRyeS1wb2ludC1tb2R1bGU+Y29tLnNhcC5zYWlsaW5nLmd3dC5hdXRvcGxheS5BdXRvUGxheTwvZW50cnktcG9pbnQtbW9kdWxlPjxlbnRyeS1wb2ludC1tb2R1bGU+Y29tLnNhcC5zYWlsaW5nLmd3dC51aS5SYWNlQm9hcmQ8L2VudHJ5LXBvaW50LW1vZHVsZT48L2d3dC1jb21waWxlLXNldHRpbmdzPg\=\= diff --git a/java/com.sap.sailing.gwt.ui/AdminConsole.css b/java/com.sap.sailing.gwt.ui/AdminConsole.css index 9e65fc5bcdc..6c7c200357a 100644 --- a/java/com.sap.sailing.gwt.ui/AdminConsole.css +++ b/java/com.sap.sailing.gwt.ui/AdminConsole.css @@ -76,6 +76,16 @@ fieldset legend { clear: both; } +.systemInformationPanel { + float: left; + display: inline-flex; + padding: 0px 0px 0px 50px; +} + +.releaseNotesAnchor { + float: right; +} + .errorLabel { color: #FF0000; } diff --git a/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF b/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF index a7efa0be243..158ce5f3afe 100644 --- a/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.gwt.ui/META-INF/MANIFEST.MF @@ -25,8 +25,8 @@ Require-Bundle: com.sap.sailing.domain, com.sap.sailing.freg.resultimport, com.sap.sailing.domain.swisstimingreplayadapter, com.sap.sailing.simulator, - com.google.gwt.user;bundle-version="2.8.2";resolution:=optional, - com.google.gwt.servlet;bundle-version="2.8.2", + com.google.gwt.user;bundle-version="2.9.0";resolution:=optional, + com.google.gwt.servlet;bundle-version="2.9.0", com.sap.sailing.domain.igtimiadapter, com.sap.sailing.xrr.resultimport, com.sap.sailing.datamining.shared, diff --git a/java/com.sap.sailing.gwt.ui/WEB-INF/web.xml b/java/com.sap.sailing.gwt.ui/WEB-INF/web.xml index 969909c2fe7..834dd55789a 100755 --- a/java/com.sap.sailing.gwt.ui/WEB-INF/web.xml +++ b/java/com.sap.sailing.gwt.ui/WEB-INF/web.xml @@ -91,6 +91,17 @@ /service/sailing/* + + Sailing ServiceWrite + SailingServiceWrite + com.sap.sailing.gwt.ui.server.SailingServiceWriteImpl + + + SailingServiceWrite + /service/sailingmaster + /service/sailingmaster/* + + Server Configuration Service ServerConfigurationService diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/expeditionconnector/ExpeditionDeviceConfiguration_CustomFieldSerializer.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/expeditionconnector/ExpeditionDeviceConfiguration_CustomFieldSerializer.java index 9a17f3263e8..9e35dc81fde 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/expeditionconnector/ExpeditionDeviceConfiguration_CustomFieldSerializer.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sailing/expeditionconnector/ExpeditionDeviceConfiguration_CustomFieldSerializer.java @@ -7,6 +7,8 @@ import com.google.gwt.user.client.rpc.SerializationException; import com.google.gwt.user.client.rpc.SerializationStreamReader; import com.google.gwt.user.client.rpc.SerializationStreamWriter; import com.sap.sailing.expeditionconnector.ExpeditionDeviceConfiguration; +import com.sap.sse.security.shared.dto.AccessControlListDTO; +import com.sap.sse.security.shared.dto.OwnershipDTO; public class ExpeditionDeviceConfiguration_CustomFieldSerializer extends CustomFieldSerializer { @@ -21,6 +23,8 @@ public class ExpeditionDeviceConfiguration_CustomFieldSerializer extends CustomF streamWriter.writeString(instance.getName()); streamWriter.writeObject(instance.getDeviceUuid()); streamWriter.writeObject(instance.getExpeditionBoatId()); + streamWriter.writeObject(instance.getAccessControlList()); + streamWriter.writeObject(instance.getOwnership()); } @Override @@ -36,7 +40,12 @@ public class ExpeditionDeviceConfiguration_CustomFieldSerializer extends CustomF public static ExpeditionDeviceConfiguration instantiate(SerializationStreamReader streamReader) throws SerializationException { - return new ExpeditionDeviceConfiguration(streamReader.readString(), (UUID) streamReader.readObject(), (Integer) streamReader.readObject()); + final ExpeditionDeviceConfiguration result = new ExpeditionDeviceConfiguration(streamReader.readString(), (UUID) streamReader.readObject(), (Integer) streamReader.readObject()); + final AccessControlListDTO acl = (AccessControlListDTO) streamReader.readObject(); + final OwnershipDTO ownership = (OwnershipDTO) streamReader.readObject(); + result.setAccessControlList(acl); + result.setOwnership(ownership); + return result; } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sse/security/shared/UnauthorizedException_CustomFieldSerializer.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sse/security/shared/UnauthorizedException_CustomFieldSerializer.java new file mode 100755 index 00000000000..c0be84c90f6 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sse/security/shared/UnauthorizedException_CustomFieldSerializer.java @@ -0,0 +1,46 @@ +package com.google.gwt.user.client.rpc.core.com.sap.sse.security.shared; + +import com.google.gwt.user.client.rpc.CustomFieldSerializer; +import com.google.gwt.user.client.rpc.SerializationException; +import com.google.gwt.user.client.rpc.SerializationStreamReader; +import com.google.gwt.user.client.rpc.SerializationStreamWriter; +import com.sap.sse.security.shared.UnauthorizedException; + +public class UnauthorizedException_CustomFieldSerializer extends CustomFieldSerializer { + @Override + public boolean hasCustomInstantiateInstance() { + return true; + } + + @Override + public UnauthorizedException instantiateInstance(SerializationStreamReader streamReader) throws SerializationException { + return instantiate(streamReader); + } + + public static UnauthorizedException instantiate(SerializationStreamReader streamReader) throws SerializationException { + return new UnauthorizedException(streamReader.readString()); + } + + public static void deserialize(SerializationStreamReader streamReader, UnauthorizedException instance) + throws SerializationException { + // handled by instantiateInstance + } + + @Override + public void deserializeInstance(SerializationStreamReader streamReader, UnauthorizedException instance) + throws SerializationException { + deserialize(streamReader, instance); + } + + @Override + public void serializeInstance(SerializationStreamWriter streamWriter, UnauthorizedException instance) + throws SerializationException { + serialize(streamWriter, instance); + } + + public static void serialize(SerializationStreamWriter streamWriter, UnauthorizedException instance) + throws SerializationException { + streamWriter.writeString(instance.getMessage()); + } + +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sse/security/shared/UserGroupManagementException_CustomFieldSerializer.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sse/security/shared/UserGroupManagementException_CustomFieldSerializer.java new file mode 100755 index 00000000000..6cf0cf68932 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sse/security/shared/UserGroupManagementException_CustomFieldSerializer.java @@ -0,0 +1,46 @@ +package com.google.gwt.user.client.rpc.core.com.sap.sse.security.shared; + +import com.google.gwt.user.client.rpc.CustomFieldSerializer; +import com.google.gwt.user.client.rpc.SerializationException; +import com.google.gwt.user.client.rpc.SerializationStreamReader; +import com.google.gwt.user.client.rpc.SerializationStreamWriter; +import com.sap.sse.security.shared.UserGroupManagementException; + +public class UserGroupManagementException_CustomFieldSerializer extends CustomFieldSerializer { + @Override + public boolean hasCustomInstantiateInstance() { + return true; + } + + @Override + public UserGroupManagementException instantiateInstance(SerializationStreamReader streamReader) throws SerializationException { + return instantiate(streamReader); + } + + public static UserGroupManagementException instantiate(SerializationStreamReader streamReader) throws SerializationException { + return new UserGroupManagementException(streamReader.readString()); + } + + public static void deserialize(SerializationStreamReader streamReader, UserGroupManagementException instance) + throws SerializationException { + // handled by instantiateInstance + } + + @Override + public void deserializeInstance(SerializationStreamReader streamReader, UserGroupManagementException instance) + throws SerializationException { + deserialize(streamReader, instance); + } + + @Override + public void serializeInstance(SerializationStreamWriter streamWriter, UserGroupManagementException instance) + throws SerializationException { + serialize(streamWriter, instance); + } + + public static void serialize(SerializationStreamWriter streamWriter, UserGroupManagementException instance) + throws SerializationException { + streamWriter.writeString(instance.getMessage()); + } + +} \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sse/security/shared/UserManagementException_CustomFieldSerializer.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sse/security/shared/UserManagementException_CustomFieldSerializer.java new file mode 100755 index 00000000000..44a552f0831 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/google/gwt/user/client/rpc/core/com/sap/sse/security/shared/UserManagementException_CustomFieldSerializer.java @@ -0,0 +1,46 @@ +package com.google.gwt.user.client.rpc.core.com.sap.sse.security.shared; + +import com.google.gwt.user.client.rpc.CustomFieldSerializer; +import com.google.gwt.user.client.rpc.SerializationException; +import com.google.gwt.user.client.rpc.SerializationStreamReader; +import com.google.gwt.user.client.rpc.SerializationStreamWriter; +import com.sap.sse.security.shared.UserManagementException; + +public class UserManagementException_CustomFieldSerializer extends CustomFieldSerializer { + @Override + public boolean hasCustomInstantiateInstance() { + return true; + } + + @Override + public UserManagementException instantiateInstance(SerializationStreamReader streamReader) throws SerializationException { + return instantiate(streamReader); + } + + public static UserManagementException instantiate(SerializationStreamReader streamReader) throws SerializationException { + return new UserManagementException(streamReader.readString()); + } + + public static void deserialize(SerializationStreamReader streamReader, UserManagementException instance) + throws SerializationException { + // handled by instantiateInstance + } + + @Override + public void deserializeInstance(SerializationStreamReader streamReader, UserManagementException instance) + throws SerializationException { + deserialize(streamReader, instance); + } + + @Override + public void serializeInstance(SerializationStreamWriter streamWriter, UserManagementException instance) + throws SerializationException { + serialize(streamWriter, instance); + } + + public static void serialize(SerializationStreamWriter streamWriter, UserManagementException instance) + throws SerializationException { + streamWriter.writeString(instance.getMessage()); + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/AutoPlayClientFactory.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/AutoPlayClientFactory.java index 08c663eb388..c6a6dcff60c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/AutoPlayClientFactory.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/AutoPlayClientFactory.java @@ -1,9 +1,10 @@ package com.sap.sailing.gwt.autoplay.client.app; import com.sap.sailing.gwt.home.communication.SailingDispatchSystem; +import com.sap.sailing.gwt.home.desktop.places.user.profile.WithSailingServiceWrite; import com.sap.sailing.gwt.ui.client.SailingClientFactory; -public interface AutoPlayClientFactory extends SailingClientFactory { +public interface AutoPlayClientFactory extends SailingClientFactory, WithSailingServiceWrite { AutoPlayPlaceNavigator getPlaceNavigator(); void setAutoPlayContext(AutoPlayContext configurationSixtyInch); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/AutoPlayClientFactoryBase.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/AutoPlayClientFactoryBase.java index 78a6e381f05..881da7e1346 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/AutoPlayClientFactoryBase.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/app/AutoPlayClientFactoryBase.java @@ -16,12 +16,14 @@ import com.sap.sailing.gwt.ui.client.MediaServiceAsync; import com.sap.sailing.gwt.ui.client.RemoteServiceMappingConstants; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.SailingServiceHelper; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sse.gwt.client.EntryPointHelper; import com.sap.sse.security.ui.client.SecureClientFactoryImpl; public abstract class AutoPlayClientFactoryBase extends SecureClientFactoryImpl implements AutoPlayClientFactory { private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final MediaServiceAsync mediaService; private final AutoPlayPlaceNavigator navigator; @@ -32,6 +34,7 @@ public abstract class AutoPlayClientFactoryBase super(root, eventBus, placeController); this.navigator = navigator; sailingService = SailingServiceHelper.createSailingServiceInstance(); + sailingServiceWrite = SailingServiceHelper.createSailingServiceWriteInstance(); mediaService = GWT.create(MediaService.class); EntryPointHelper.registerASyncService((ServiceDefTarget) sailingService, RemoteServiceMappingConstants.sailingServiceRemotePath); @@ -66,6 +69,11 @@ public abstract class AutoPlayClientFactoryBase return sailingServiceAsync; } } + + @Override + public SailingServiceWriteAsync getSailingServiceWrite() { + return sailingServiceWrite; + } @Override public MediaServiceAsync getMediaService() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/nodes/LiveRaceBoardNode.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/nodes/LiveRaceBoardNode.java index 547a162f726..a81c58dd85e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/nodes/LiveRaceBoardNode.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/nodes/LiveRaceBoardNode.java @@ -77,7 +77,7 @@ public class LiveRaceBoardNode extends FiresPlaceNode implements RaceTimesInfoPr /** leaderboardGroupName */ null, /** eventId */ null, cf.getErrorReporter(), StringMessages.INSTANCE, null, raceTimesInfoProvider, true, false, - Arrays.asList(DetailType.values()), result.getLeaderboard(), result.getRace(), result.getTrackingConnectorInfo()); + Arrays.asList(DetailType.values()), result.getLeaderboard(), result.getRace(), result.getTrackingConnectorInfo(), cf.getSailingServiceWrite()); setPlaceToGo(new LiveRaceWithRaceboardPlace(raceboardPerspective)); firePlaceChangeAndStartTimer(); getBus().fireEvent(new AutoPlayHeaderEvent(cf.getAutoPlayCtxSignalError().getLifeOrPreLiveRace().getRegattaName(), diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/shared/header/SAPHeaderComponentSettings.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/shared/header/SAPHeaderComponentSettings.java index 8ef186982f9..22e97504136 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/shared/header/SAPHeaderComponentSettings.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/shared/header/SAPHeaderComponentSettings.java @@ -10,7 +10,6 @@ public class SAPHeaderComponentSettings extends AbstractGenericSerializableSetti @Override protected void addChildSettings() { - super.addChildSettings(); title = new StringSetting("title", this,""); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/user/profile/WithSailingServiceWrite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/user/profile/WithSailingServiceWrite.java new file mode 100644 index 00000000000..bf686e665aa --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/user/profile/WithSailingServiceWrite.java @@ -0,0 +1,8 @@ +package com.sap.sailing.gwt.home.desktop.places.user.profile; + +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; + +public interface WithSailingServiceWrite { + + SailingServiceWriteAsync getSailingServiceWrite(); +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/InSightAppNotes.html b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/InSightAppNotes.html index d83307a398b..f94fbb8b769 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/InSightAppNotes.html +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/InSightAppNotes.html @@ -2,8 +2,86 @@

-

What's New - SAP Sail InSight (Android)

+

What's New - SAP Sail InSight

+
08.04.2020 - Version 2.3.8
+
    +
  • Added MTCP communications module.
  • +
  • Fixed the bug that allowed you to get the waypoint name editing form field on start/finish waypoints.
  • +
  • Fixed issue with first character being capitalized on password input on Android devices.
  • +
  • Swap the order of first two steps in Event Overview page.
  • +
  • Changed mark tracking screen to make binding marks visually more comprehensible.
  • +
  • Added splash screen on Android.
  • +
  • Fixed navigation issue when quickly pressing sub-sections one by one on Account page.
  • +
  • Fixed issue with events become unresponsive after starting tracking for an invited event.
  • +
  • Fixed issue with anonymous users loses joined events after restarting the app.
  • +
+ +
18.03.2020 - Version 2.2.0
+
    +
  • Regatta details and races are now refreshed when selecting an event.
  • +
  • Fixed an issue with updating competitor ACL on the settings specified server instead of event server when joining an event.
  • +
  • Fixed an issue that prevented anonymous users from joining events due to an unnecessary call to update competitor ACL.
  • +
  • Course creator is now updated showing the new device binding when coming out of the ‘Scan QR Code’ screen for mark.
  • +
  • Display time gaps in the format 'DD:HH:mm:ss' in the leaderboard. Layout fixes to leaderboard screen.
  • +
  • Fixed a layout issue in course creator to extend the mark background to the lower edge of the screen.
  • +
  • Complete refactor of app navigation code, fixing various navigation issues.
  • +
  • Fixed an issue that showed an empty boat class field for owners in handicap based events.
  • +
  • Registration form is now cleared after a successful register.
  • +
  • Fixed an issue that hides the 'New team' button in teams screen when scrolling.
  • +
+ +
06.03.2020 - Version 2.1.1
+
    +
  • Fixed an issue that stopped tracking when tapping on tracking tab while being in leaderboard view.
  • +
  • Fixed an issue that made the Android back button not working properly in screens other than tracking.
  • +
  • Fixed an issue where the app didn't navigate properly after registering a new user.
  • +
+ +
03.03.2020 - Version 2.0.2
+
    +
  • React Navigation dependency upgraded to the latest version.
  • +
  • Visual fixes in leaderboard screen.
  • +
  • Added localized text for undefined course or missing start times in race details.
  • +
+ +
02.03.2020 - Version 2.0.0
+
    +
  • Fixed leaderboard layout issues on certain devices.
  • +
  • Competitors and boats are assigned ‘READ_ALL’ permissions when joining an event.
  • +
  • Removed deletion of locally stored gps fixes when tracking is started. This fixes scenarios related to tracking being interrupted and restarted.
  • +
  • Fixed an issue that prevented start tracking while offline.
  • +
  • Color code other competitors in the leaderboard based on whether they're ahead or behind my competitor.
  • +
  • Reduce the length of the mantissa to 1 when converting between handicap value types.
  • +
  • Fixed issue with Scan QR Code button overlapping the last item in Tracking screen.
  • +
  • Fixed issue with first save of a new course with mark position change of existing marks from inventory.
  • +
  • Fixed issue that sometimes prevented start time being set on races while tracking was active.
  • +
+ +
20.02.2020 - Version 1.0.64
+
    +
  • Fixed visuals for boat handicap style selector in Team details.
  • +
  • Default generated event names are now only placeholders in Event Creation screen, applied only if the input is left empty.
  • +
  • Default generated event names are now only placeholders in Event Creation screen, applied only if the input is left empty.
  • +
  • Fixed issue with fixed gps position overriding a tracker binding when saving a course right after binding was successfully made.
  • +
  • Fixed issue with ‘Join As Competitor’ button not being removed after an organizer joins an event he created.
  • +
  • Fixed issue where ‘Scan QR Code’ button overlapped the last event card in events list, making it hard to tap on the event.
  • +
  • Fixed issue where app was crashing when clicking on leaderboard dropdown.
  • +
  • Fixed issue with competitors not being able to see each other in the leaderboard due to permissions.
  • +
  • Fixed issue with missing multidex support on Android, making certain devices crash on app start.
  • +
  • Replaced hard to read font in event organizer view.
  • +
+ +
19.02.2020 - Version 1.0.63
+
    +
  • Fixed issue with tracking screen being closed when tapping multiple times on the tracking tab.
  • +
  • Added loading indicator on the button when creating a new event.
  • +
  • Added link to SAP race board for current tracked race from tracking screen.
  • +
  • Main tab bar hidden while device keyboard is shown.
  • +
  • Improved back button handling in Android devices.
  • +
  • Removed the modal popup presented to the user that blocked joining an event which is already added to the user's device.
  • +
+
March 2018
  • Made app robust against events that have no start/end dates set
  • @@ -24,6 +102,15 @@ and the automatic overriding of user preferences has been removed.
  • In some rare situations the app crashed, if you want to scan a QR-Code.
+ +
October 2016 - SAP Sail InSight (iOS)
+
    +
  • This release introduces an entirely new design.
  • +
  • The landscape mode is optimized for small devices.
  • +
  • Unsent GPS-fixes will be sent automatically after a sudden reboot of the device.
  • +
  • Fixed an issue where a login could be done twice.
  • +
  • Fixed an issue where an invalid login is handled as a successful one.
  • +
August 2016
@@ -43,17 +130,7 @@ start tracking for one buoy. It will track all buoys.
-

What's New - SAP Sail InSight (iOS)

-
-
October 2016
-
    -
  • This release introduces an entirely new design.
  • -
  • The landscape mode is optimized for small devices.
  • -
  • Unsent GPS-fixes will be sent automatically after a sudden reboot of the device.
  • -
  • Fixed an issue where a login could be done twice.
  • -
  • Fixed an issue where an invalid login is handled as a successful one.
  • -
-
+
\ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html index 8fcef584a3c..ae53f7af437 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/home/desktop/places/whatsnew/resources/SailingAnalyticsNotes.html @@ -4,6 +4,11 @@

What's New - SAP Sailing Analytics

+
June 2020
+
    +
  • The "Gap Change" for the first leg will now show the current gap in the first leg rather than + "NaN" (not a number).
  • +
March 2020
  • The security infrastructure of the previously separate environments of diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaOverviewEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaOverviewEntryPoint.java index 091642b1f28..bef51ac8286 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaOverviewEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/regattaoverview/client/RegattaOverviewEntryPoint.java @@ -18,13 +18,13 @@ import com.sap.sailing.gwt.common.client.SharedResources; import com.sap.sailing.gwt.regattaoverview.client.RegattaRaceStatesComponent.EntryHandler; import com.sap.sailing.gwt.settings.client.regattaoverview.RegattaOverviewContextDefinition; import com.sap.sailing.gwt.settings.client.regattaoverview.RegattaRaceStatesSettings; -import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint; +import com.sap.sailing.gwt.ui.client.AbstractSailingReadEntryPoint; import com.sap.sailing.gwt.ui.shared.RegattaOverviewEntryDTO; import com.sap.sse.gwt.client.Notification; import com.sap.sse.gwt.client.Notification.NotificationType; import com.sap.sse.gwt.settings.SettingsToUrlSerializer; -public class RegattaOverviewEntryPoint extends AbstractSailingEntryPoint { +public class RegattaOverviewEntryPoint extends AbstractSailingReadEntryPoint { private static final SettingsToUrlSerializer serializer = new SettingsToUrlSerializer(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractBoatCertificatesPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractBoatCertificatesPanel.java index a45b486f871..bf2f2d48415 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractBoatCertificatesPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractBoatCertificatesPanel.java @@ -42,6 +42,7 @@ import com.sap.sailing.domain.common.dto.RaceColumnDTO; import com.sap.sailing.domain.common.orc.ORCCertificate; import com.sap.sailing.domain.common.orc.ORCCertificateUploadConstants; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sse.common.Util.Triple; @@ -79,7 +80,7 @@ public abstract class AbstractBoatCertificatesPanel extends SimplePanel { private final Map boatsByIdAsString; private final CertificatesTableWrapper> certificateTable; private final BusyIndicator busyIndicator; - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final ErrorReporter errorReporter; private final StringListEditorComposite urls; @@ -125,10 +126,10 @@ public abstract class AbstractBoatCertificatesPanel extends SimplePanel { /** * After invoking this superclass constructor, and after doing any other initialization work, subclasses must call {@link #refresh}. */ - public AbstractBoatCertificatesPanel(final SailingServiceAsync sailingService, final UserService userService, + public AbstractBoatCertificatesPanel(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final SecuredDTO objectToCheckUpdatePermissionFor, final StringMessages stringMessages, final ErrorReporter errorReporter, Supplier contextUpdatePermissionCheck, String errorContext) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.errorReporter = errorReporter; this.stringMessages = stringMessages; this.certificateTableSelectionHandler = createCertificateTableSelectionHandler(); @@ -141,10 +142,10 @@ public abstract class AbstractBoatCertificatesPanel extends SimplePanel { this.urls = new StringListEditorComposite(Collections.emptySet(), stringMessages, stringMessages.courseAreas(), IconResources.INSTANCE.removeIcon(), /* suggested values */ Collections.emptySet(), stringMessages.enterURLsForCertificateDownload()); this.hiddenCertificateUrlsFields = new ArrayList<>(); - this.boatTable = new BoatWithCertificateTableWrapper<>(sailingService, userService, stringMessages, + this.boatTable = new BoatWithCertificateTableWrapper<>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ true, /* enablePager */ true, TableWrapper.DEFAULT_PAGING_SIZE, /* allow actions */ true, boat->unlink(boat), objectToCheckUpdatePermissionFor, boat->certificateAssignments.containsKey(boat)); - this.certificateTable = new CertificatesTableWrapper<>(sailingService, userService, stringMessages, + this.certificateTable = new CertificatesTableWrapper<>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true, TableWrapper.DEFAULT_PAGING_SIZE); busyIndicator = new SimpleBusyIndicator(false, 0.8f); this.form = new FormPanel(); @@ -224,7 +225,7 @@ public abstract class AbstractBoatCertificatesPanel extends SimplePanel { searchGrid.setWidget(1, 6, boatClassNameTextBox); searchButton.addClickHandler(e->{ busyIndicator.setBusy(true); - sailingService.searchORCBoatCertificates(DialogUtils.getSelectedCountry(issuingCountryListBox), + sailingServiceWrite.searchORCBoatCertificates(DialogUtils.getSelectedCountry(issuingCountryListBox), yearOfIssuanceBox.getValue(), referenceNumberTextBox.getValue().trim().isEmpty() ? null : referenceNumberTextBox.getValue(), yachtNameTextBox.getValue() == null ? null : yachtNameTextBox.getValue(), @@ -251,7 +252,7 @@ public abstract class AbstractBoatCertificatesPanel extends SimplePanel { try { final JSONObject json = (JSONObject) JSONParser.parseStrict(e.getResults()); if (json.get(ORCCertificateUploadConstants.CERTIFICATES) != null) { - sailingService.getORCCertificates(e.getResults(), new AsyncCallback>() { + sailingServiceWrite.getORCCertificates(e.getResults(), new AsyncCallback>() { @Override public void onFailure(Throwable caught) { busyIndicator.setBusy(false); @@ -401,7 +402,7 @@ public abstract class AbstractBoatCertificatesPanel extends SimplePanel { final Set selectedBoats = boatTable.getSelectionModel().getSelectedSet(); if (selectedBoats != null && !selectedBoats.isEmpty()) { busyIndicator.setBusy(true); - sailingService.getSuggestedORCBoatCertificates(new ArrayList<>(selectedBoats), + sailingServiceWrite.getSuggestedORCBoatCertificates(new ArrayList<>(selectedBoats), new AsyncCallback>>() { @Override public void onFailure(Throwable caught) { @@ -446,10 +447,10 @@ public abstract class AbstractBoatCertificatesPanel extends SimplePanel { result.getB(), result.getC()), Notification.NotificationType.INFO); } }; - assignCertificates(sailingService, certificatesByBoatIdAsString, callback); + assignCertificates(sailingServiceWrite, certificatesByBoatIdAsString, callback); } - protected abstract void assignCertificates(SailingServiceAsync sailingService, + protected abstract void assignCertificates(SailingServiceWriteAsync sailingServiceWrite, Map certificatesByBoatIdAsString, AsyncCallback> callback); @@ -495,10 +496,10 @@ public abstract class AbstractBoatCertificatesPanel extends SimplePanel { boatTable.setBoats(boatResults); } }; - getORCCertificateAssignemtnsByBoatIdAsString(sailingService, callbackForGetCertificates); + getORCCertificateAssignemtnsByBoatIdAsString(sailingServiceWrite, callbackForGetCertificates); } }; - getBoats(sailingService, callbackForGetBoats); + getBoats(sailingServiceWrite, callbackForGetBoats); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractCompetitorRegistrationDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractCompetitorRegistrationDialog.java index 7d8ddab8bda..3c9768b4376 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractCompetitorRegistrationDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractCompetitorRegistrationDialog.java @@ -8,6 +8,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.dialog.DataEntryDialog; @@ -21,7 +22,7 @@ public abstract class AbstractCompetitorRegistrationDialog extends DataEntryDial protected final boolean canBoatsOfCompetitorsChangePerRace; protected final CompetitorRegistrationsPanel competitorRegistrationsPanel; - public AbstractCompetitorRegistrationDialog(SailingServiceAsync sailingService, final UserService userService, StringMessages stringMessages, + public AbstractCompetitorRegistrationDialog(SailingServiceWriteAsync sailingServiceWrite, final UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, boolean editable, com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback> callback, String leaderboardName, boolean canBoatsOfCompetitorsChangePerRace, String boatClass, String okButtonMessage, @@ -30,10 +31,10 @@ public abstract class AbstractCompetitorRegistrationDialog extends DataEntryDial validator, callback); this.errorReporter = errorReporter; this.stringMessages = stringMessages; - this.sailingService = sailingService; + this.sailingService = sailingServiceWrite; this.leaderboardName = leaderboardName; this.canBoatsOfCompetitorsChangePerRace = canBoatsOfCompetitorsChangePerRace; - this.competitorRegistrationsPanel = new CompetitorRegistrationsPanel(sailingService, userService, stringMessages, errorReporter, editable, leaderboardName, canBoatsOfCompetitorsChangePerRace, boatClass, + this.competitorRegistrationsPanel = new CompetitorRegistrationsPanel(sailingServiceWrite, userService, stringMessages, errorReporter, editable, leaderboardName, canBoatsOfCompetitorsChangePerRace, boatClass, ()->validateAndUpdate(), getRegisteredCompetitorsRetriever(), /* restrictPoolToLeaderboard */ false, getAdditionalWidgetsToInsertAboveCompetitorTables(stringMessages)); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractCompetitorWithBoatDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractCompetitorWithBoatDialog.java index 3e1ea39f232..8e3fd954ec4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractCompetitorWithBoatDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractCompetitorWithBoatDialog.java @@ -3,12 +3,15 @@ package com.sap.sailing.gwt.ui.adminconsole; import com.google.gwt.user.client.ui.FocusWidget; import com.google.gwt.user.client.ui.SuggestBox; import com.google.gwt.user.client.ui.TextBox; +import com.sap.sailing.domain.common.dto.BoatClassDTO; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTO; import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTOImpl; import com.sap.sailing.gwt.common.client.suggestion.BoatClassMasterdataSuggestOracle; import com.sap.sailing.gwt.ui.client.StringMessages; +import com.sap.sse.common.Color; +import com.sap.sse.common.Distance; import com.sap.sse.gwt.client.ColorTextBox; /** @@ -76,45 +79,64 @@ public abstract class AbstractCompetitorWithBoatDialog extends CompetitorEditDia } } - /** * The class creates the UI-dialog to type in the Data about a competitor. * - * @param competitorToEdit - * The 'competitorToEdit' parameter contains the competitor which should be changed or initialized. + * @param competitorWithBoat + * The 'competitorWithBoat' parameter contains the competitor which should be changed or initialized. * @param boatClass * The boat class is the default shown boat class for new boats. Set null if your boat is * already initialized or you don't want a default boat class. + * @param The + * {@link Validator} for competitor with boat */ - public AbstractCompetitorWithBoatDialog(String dialogTitle, StringMessages stringMessages, CompetitorWithBoatDTO competitorToEdit, - DialogCallback callback, String boatClass) { - super(dialogTitle, stringMessages, competitorToEdit, - new AbstractCompetitorWithBoatDialog.CompetitorWithBoatValidator(stringMessages, - competitorToEdit.getBoat()), - callback); - - final BoatDTO boatToEdit = competitorToEdit.getBoat(); + public AbstractCompetitorWithBoatDialog(String dialogTitle, StringMessages stringMessages, + CompetitorWithBoatDTO competitorWithBoat, DialogCallback callback, String boatClass, + CompetitorWithoutBoatValidator validator) { + super(dialogTitle, stringMessages, competitorWithBoat, validator, callback); + final BoatDTO boat = competitorWithBoat.getBoat(); this.boatClassNameTextBox = createSuggestBox(new BoatClassMasterdataSuggestOracle()); boatClassNameTextBox.ensureDebugId("BoatClassNameSuggestBox"); - if (boatToEdit.getBoatClass() != null) { - boatClassNameTextBox.setValue(boatToEdit.getBoatClass().getName()); - boatClassNameTextBox.setEnabled(false); + if (boat.getBoatClass() != null) { + boatClassNameTextBox.setValue(boat.getBoatClass().getName()); + setBoatClassNameEnabled(boatClassNameTextBox, false); } else { boatClassNameTextBox.setValue(boatClass); // widgets have to accept null values here } - this.boatNameTextBox = createTextBox(boatToEdit.getName()); + this.boatNameTextBox = createTextBox(boat.getName()); boatNameTextBox.ensureDebugId("BoatNameTextBox"); - this.boatDisplayColorTextBox = createColorTextBox(boatToEdit.getColor()); - this.sailIdTextBox = createTextBox(boatToEdit.getSailId()); + this.boatDisplayColorTextBox = createColorTextBox(boat.getColor()); + this.sailIdTextBox = createTextBox(boat.getSailId()); sailIdTextBox.ensureDebugId("SailIdTextBox"); } + public AbstractCompetitorWithBoatDialog(String dialogTitle, StringMessages stringMessages, + CompetitorWithBoatDTO competitorWithBoat, DialogCallback callback, + String boatClass) { + this(dialogTitle, stringMessages, competitorWithBoat, callback, boatClass, + new AbstractCompetitorWithBoatDialog.CompetitorWithBoatValidator(stringMessages, + competitorWithBoat.getBoat())); + } + @Override protected FocusWidget getInitialFocusWidget() { return super.getInitialFocusWidget(); } - protected abstract BoatDTO getBoat(); + protected BoatDTO getBoat() { + BoatDTO result = null; + Color boatColor; + if (boatDisplayColorTextBox.isValid()) { + boatColor = boatDisplayColorTextBox.getColor(); + } else { + boatColor = new InvalidColor(new IllegalArgumentException(boatDisplayColorTextBox.getValue()), + getStringMessages()); + } + BoatClassDTO boatClass = new BoatClassDTO(boatClassNameTextBox.getValue(), Distance.NULL, Distance.NULL); + result = new BoatDTO(getCompetitorToEdit().getBoat().getIdAsString(), boatNameTextBox.getValue(), boatClass, + sailIdTextBox.getValue(), boatColor); + return result; + } @Override protected CompetitorWithBoatDTO getResult() { @@ -129,4 +151,8 @@ public abstract class AbstractCompetitorWithBoatDialog extends CompetitorEditDia return result; } + protected void setBoatClassNameEnabled(SuggestBox boatClassNameTextBox, boolean enabled) { + boatClassNameTextBox.setEnabled(enabled); + } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractEventManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractEventManagementPanel.java index a7062aa18f9..ca191ee4971 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractEventManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractEventManagementPanel.java @@ -16,7 +16,7 @@ import com.google.gwt.user.client.ui.ListBox; import com.sap.sailing.domain.common.BoatClassMasterdata; import com.sap.sailing.gwt.ui.client.AbstractRegattaPanel; import com.sap.sailing.gwt.ui.client.RegattaRefresher; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RaceRecordDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; @@ -29,17 +29,17 @@ public abstract class AbstractEventManagementPanel extends AbstractRegattaPanel private final List availableRegattas; private final ListBox availableRegattasListBox; - public AbstractEventManagementPanel(SailingServiceAsync sailingService, UserService userService, + public AbstractEventManagementPanel(SailingServiceWriteAsync sailingServiceWrite, UserService userService, RegattaRefresher regattaRefresher, ErrorReporter errorReporter, boolean actionButtonsEnabled, StringMessages stringMessages) { - super(sailingService, regattaRefresher, errorReporter, stringMessages); + super(sailingServiceWrite, regattaRefresher, errorReporter, stringMessages); this.availableRegattas = new ArrayList(); this.availableRegattasListBox = new ListBox(); this.availableRegattasListBox.ensureDebugId("AvailableRegattasListBox"); // TrackedEventsComposite should exist in every *ManagementPanel. - trackedRacesListComposite = new TrackedRacesListComposite(null, null, sailingService, userService, + trackedRacesListComposite = new TrackedRacesListComposite(null, null, sailingServiceWrite, userService, errorReporter, regattaRefresher, stringMessages, /* multiselection */ true, actionButtonsEnabled); trackedRacesListComposite.ensureDebugId("TrackedRacesListComposite"); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardConfigPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardConfigPanel.java index af440f0d7f8..3f5983ea1fb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardConfigPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardConfigPanel.java @@ -42,7 +42,7 @@ import com.sap.sailing.gwt.ui.client.LeaderboardsDisplayer; import com.sap.sailing.gwt.ui.client.LeaderboardsRefresher; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.RegattasDisplayer; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RaceLogDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; @@ -78,7 +78,7 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel protected final StringMessages stringMessages; - protected final SailingServiceAsync sailingService; + protected final SailingServiceWriteAsync sailingServiceWrite; protected final ListDataProvider filteredLeaderboardList; @@ -156,12 +156,12 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel } } - public AbstractLeaderboardConfigPanel(final SailingServiceAsync sailingService, final UserService userService, + public AbstractLeaderboardConfigPanel(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, RegattaRefresher regattaRefresher, LeaderboardsRefresher leaderboardsRefresher, final ErrorReporter errorReporter, StringMessages theStringConstants, boolean multiSelection) { this.stringMessages = theStringConstants; - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.userService = userService; filteredLeaderboardList = new ListDataProvider(); allRegattas = new ArrayList(); @@ -252,7 +252,7 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel trackedRacesCaptionPanel.setContentWidget(trackedRacesPanel); trackedRacesCaptionPanel.setStyleName("bold"); - trackedRacesListComposite = new TrackedRacesListComposite(null, null, sailingService, userService, + trackedRacesListComposite = new TrackedRacesListComposite(null, null, sailingServiceWrite, userService, errorReporter, regattaRefresher, stringMessages, /* multiselection */false, isActionButtonsEnabled()); refreshableTrackedRaceSelectionModel = trackedRacesListComposite.getSelectionModel(); @@ -331,7 +331,7 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel Label lblRaceNamesIn = new Label(stringMessages.races()); vPanel.add(lblRaceNamesIn); raceColumnTable = new RaceTableWrapper>( - sailingService, stringMessages, errorReporter, multiSelection); + sailingServiceWrite, stringMessages, errorReporter, multiSelection); raceColumnTable.asWidget().ensureDebugId("RaceColumnTable"); raceColumnTable.getTable().setWidth("100%"); addColumnsToRacesTable(raceColumnTable.getTable()); @@ -421,7 +421,7 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel + t.getMessage()); } }); - sailingService.getLeaderboardWithSecurity(leaderboardName, callback); + sailingServiceWrite.getLeaderboardWithSecurity(leaderboardName, callback); } private void replaceLeaderboardInList(List leaderboardList, @@ -440,7 +440,7 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel protected void unlinkRaceColumnFromTrackedRace(final String raceColumnName, final FleetDTO fleet) { final String selectedLeaderboardName = getSelectedLeaderboardName(); - sailingService.disconnectLeaderboardColumnFromTrackedRace(selectedLeaderboardName, raceColumnName, + sailingServiceWrite.disconnectLeaderboardColumnFromTrackedRace(selectedLeaderboardName, raceColumnName, fleet.getName(), new AsyncCallback() { @Override public void onFailure(Throwable t) { @@ -459,7 +459,7 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel protected void refreshRaceLog(final RaceColumnDTO raceColumnDTO, final FleetDTO fleet, final boolean showAlerts) { final String selectedLeaderboardName = getSelectedLeaderboardName(); - sailingService.reloadRaceLog(selectedLeaderboardName, raceColumnDTO, fleet, + sailingServiceWrite.reloadRaceLog(selectedLeaderboardName, raceColumnDTO, fleet, new MarkedAsyncCallback(new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -496,7 +496,7 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel final String selectedRaceColumnName = selectedRaceColumnAndFleetNameInLeaderboard.getA() .getRaceColumnName(); final String selectedFleetName = selectedRaceColumnAndFleetNameInLeaderboard.getB().getName(); - sailingService.getRegattaAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(selectedLeaderboardName, + sailingServiceWrite.getRegattaAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(selectedLeaderboardName, selectedRaceColumnName, new MarkedAsyncCallback>( new AsyncCallback>() { @Override @@ -593,7 +593,7 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel private void linkTrackedRaceToSelectedRaceColumn(final RaceColumnDTO selectedRaceInLeaderboard, final FleetDTO fleet, final RegattaAndRaceIdentifier selectedRace) { - sailingService.connectTrackedRaceToLeaderboardColumn(getSelectedLeaderboardName(), + sailingServiceWrite.connectTrackedRaceToLeaderboardColumn(getSelectedLeaderboardName(), selectedRaceInLeaderboard.getRaceColumnName(), fleet.getName(), selectedRace, new MarkedAsyncCallback(new AsyncCallback() { @Override @@ -676,15 +676,15 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel } }; if (rename) { - sailingService.renameLeaderboardColumn(selectedLeaderboardName, oldRaceColumnName, + sailingServiceWrite.renameLeaderboardColumn(selectedLeaderboardName, oldRaceColumnName, result.getName(), renameLeaderboardColumnCallback); } if (updateIsMedalRace) { - sailingService.updateIsMedalRace(selectedLeaderboardName, result.getName(), + sailingServiceWrite.updateIsMedalRace(selectedLeaderboardName, result.getName(), result.isMedalRace(), updateIsMedalRaceCallback); } if (updateFactor) { - sailingService.updateLeaderboardColumnFactor(selectedLeaderboardName, result.getName(), + sailingServiceWrite.updateLeaderboardColumnFactor(selectedLeaderboardName, result.getName(), result.getExplicitFactor(), updateLeaderboardColumnFactorCallback); } } @@ -694,7 +694,7 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel protected void showRaceLog(final RaceColumnDTO raceColumnDTO, final FleetDTO fleetDTO) { final String selectedLeaderboardName = getSelectedLeaderboardName(); - sailingService.getRaceLog(selectedLeaderboardName, raceColumnDTO, fleetDTO, + sailingServiceWrite.getRaceLog(selectedLeaderboardName, raceColumnDTO, fleetDTO, new MarkedAsyncCallback(new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -723,7 +723,7 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel protected void showRegattaLog() { final String selectedLeaderboardName = getSelectedLeaderboardName(); - sailingService.getRegattaLog(selectedLeaderboardName, + sailingServiceWrite.getRegattaLog(selectedLeaderboardName, new MarkedAsyncCallback(new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -801,13 +801,13 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel } protected void assignCertificates(RaceColumnDTOAndFleetDTOWithNameBasedEquality object) { - BoatCertificateAssignmentDialog dialog = new BoatCertificateAssignmentDialog(sailingService, userService, - stringMessages, errorReporter, new RaceBoatCertificatesPanel(sailingService, userService, object.getC(), object.getA(), object.getB(), stringMessages, errorReporter)); + BoatCertificateAssignmentDialog dialog = new BoatCertificateAssignmentDialog(sailingServiceWrite, userService, + stringMessages, errorReporter, new RaceBoatCertificatesPanel(sailingServiceWrite, userService, object.getC(), object.getA(), object.getB(), stringMessages, errorReporter)); dialog.show(); } protected void selectScratchBoat(RaceColumnDTOAndFleetDTOWithNameBasedEquality object) { - sailingService.getORCPerformanceCurveScratchBoat(object.getC().getName(), object.getA().getName(), object.getB().getName(), new AsyncCallback() { + sailingServiceWrite.getORCPerformanceCurveScratchBoat(object.getC().getName(), object.getA().getName(), object.getB().getName(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(stringMessages.errorObtainingScratchBoat(caught.getMessage()), /* silent */ true); @@ -815,12 +815,12 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel @Override public void onSuccess(CompetitorDTO scratchBoatSoFar) { - new CompetitorSelectionDialog(sailingService, userService, errorReporter, + new CompetitorSelectionDialog(sailingServiceWrite, userService, errorReporter, stringMessages.selectScratchBoat(), stringMessages.selectScratchBoat(), getRaceCompetitorProvider(object), stringMessages, scratchBoatSoFar, new DialogCallback() { @Override public void ok(CompetitorDTO newScratchBoat) { - sailingService.setORCPerformanceCurveScratchBoat(object.getC().getName(), object.getA().getName(), object.getB().getName(), + sailingServiceWrite.setORCPerformanceCurveScratchBoat(object.getC().getName(), object.getA().getName(), object.getB().getName(), newScratchBoat, new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -843,7 +843,7 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel protected void setImpliedWind(RaceColumnDTOAndFleetDTOWithNameBasedEquality object) { final String raceDisplayName = object.getC().getName() + "/" + object.getA().getName() + "/" + object.getB().getName(); - sailingService.getImpliedWindSource(object.getC().getName(), object.getA().getName(), object.getB().getName(), + sailingServiceWrite.getImpliedWindSource(object.getC().getName(), object.getA().getName(), object.getB().getName(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -854,10 +854,10 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel @Override public void onSuccess(ImpliedWindSource result) { - new ImpliedWindSourceEditDialog(object, result, availableLeaderboardList, stringMessages, errorReporter, sailingService, userService, new DialogCallback() { + new ImpliedWindSourceEditDialog(object, result, availableLeaderboardList, stringMessages, errorReporter, sailingServiceWrite, userService, new DialogCallback() { @Override public void ok(ImpliedWindSource editedObject) { - sailingService.setImpliedWindSource(object.getC().getName(), object.getA().getName(), object.getB().getName(), editedObject, + sailingServiceWrite.setImpliedWindSource(object.getC().getName(), object.getA().getName(), object.getB().getName(), editedObject, new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -889,7 +889,7 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel */ protected Consumer>> getRaceCompetitorProvider( RaceColumnDTOAndFleetDTOWithNameBasedEquality raceSlotIdentifier) { - return callback -> sailingService.getCompetitorsAndBoatsOfRace(raceSlotIdentifier.getC().getName(), + return callback -> sailingServiceWrite.getCompetitorsAndBoatsOfRace(raceSlotIdentifier.getC().getName(), raceSlotIdentifier.getA().getName(), raceSlotIdentifier.getB().getName(), new AsyncCallback>() { @Override public void onFailure(Throwable e) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardDialog.java index e25d879f40d..05be674358b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardDialog.java @@ -19,12 +19,17 @@ public abstract class AbstractLeaderboardDialog validator, DialogCallback callback) { super(title, null, stringMessages.ok(), stringMessages.cancel(), validator, callback); + nameTextBox = createTextBox(leaderboardDescriptor.getName()); + nameTextBox.setVisibleLength(50); + nameTextBox.ensureDebugId("NameTextBox"); + nameTextBox.setEnabled(false); // name is not editable; see also bug5282 this.stringMessages = stringMessages; this.leaderboardDescriptor = leaderboardDescriptor; } @Override protected LD getResult() { + // setting the name is relevant only for the FlexibleLeaderboard and RegattaLeaderboardWithElimination creation: leaderboardDescriptor.setName(nameTextBox.getValue().trim()); // avoid trailing blank issues; leaderboard names may appear in URLs leaderboardDescriptor.setDisplayName(displayNameTextBox.getValue().trim().isEmpty() ? null : displayNameTextBox.getValue()); leaderboardDescriptor.setDiscardThresholds(discardThresholdBoxes==null?null:discardThresholdBoxes.getDiscardThresholds()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRaceManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRaceManagementPanel.java index d4ba6e4ea7a..b9403959e83 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRaceManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRaceManagementPanel.java @@ -10,7 +10,7 @@ import com.google.gwt.view.client.SelectionChangeEvent.Handler; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.dto.RaceDTO; import com.sap.sailing.gwt.ui.client.RegattaRefresher; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sse.gwt.client.ErrorReporter; @@ -27,12 +27,12 @@ public abstract class AbstractRaceManagementPanel extends AbstractEventManagemen protected final VerticalPanel selectedRaceContentPanel; - public AbstractRaceManagementPanel(final SailingServiceAsync sailingService, ErrorReporter errorReporter, + public AbstractRaceManagementPanel(final SailingServiceWriteAsync sailingService, ErrorReporter errorReporter, RegattaRefresher regattaRefresher, boolean actionButtonsEnabled, StringMessages stringMessages) { this(sailingService, null, errorReporter, regattaRefresher, actionButtonsEnabled, stringMessages); } - public AbstractRaceManagementPanel(final SailingServiceAsync sailingService, + public AbstractRaceManagementPanel(final SailingServiceWriteAsync sailingService, UserService userService, ErrorReporter errorReporter, RegattaRefresher regattaRefresher, boolean actionButtonsEnabled, StringMessages stringMessages) { super(sailingService, userService, regattaRefresher, errorReporter, actionButtonsEnabled, stringMessages); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaLogFixesAddMappingsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaLogFixesAddMappingsDialog.java index a4d1ea1f4c4..31c7dd4a3e7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaLogFixesAddMappingsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaLogFixesAddMappingsDialog.java @@ -18,6 +18,7 @@ import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTO; import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.DeviceIdentifierDTO; import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO; @@ -44,7 +45,7 @@ public class AbstractRegattaLogFixesAddMappingsDialog extends DataEntryDialog> callback) { super(stringMessages.add(stringMessages.deviceMappings()), stringMessages.add(stringMessages.deviceMappings()), @@ -62,22 +63,22 @@ public class AbstractRegattaLogFixesAddMappingsDialog extends DataEntryDialog(sailingService, userService, stringMessages, errorReporter, + competitorTable = new CompetitorTableWrapper<>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ false, /* enable pager */ true, /* filterCompetitorWithBoat */ false, /* filterCompetitorsWithoutBoat */ false); markTable = new MarkTableWrapper>( - /* multiSelection */ false, sailingService, stringMessages, errorReporter); - boatTable = new BoatTableWrapper>(sailingService, userService, stringMessages, + /* multiSelection */ false, sailingServiceWrite, stringMessages, errorReporter); + boatTable = new BoatTableWrapper>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ false, /* enable Pager */ true, /* allowActions */ false); registerSelectionChangeHandler(competitorTable.getSelectionModel(), this::mappedToSelectionChanged); registerSelectionChangeHandler(markTable.getSelectionModel(), this::mappedToSelectionChanged); registerSelectionChangeHandler(boatTable.getSelectionModel(), this::mappedToSelectionChanged); - getBoatRegistrations(sailingService, errorReporter); - getCompetitorRegistrations(sailingService, errorReporter); - getMarks(sailingService, errorReporter); + getBoatRegistrations(sailingServiceWrite, errorReporter); + getCompetitorRegistrations(sailingServiceWrite, errorReporter); + getMarks(sailingServiceWrite, errorReporter); } private void getMarks(SailingServiceAsync sailingService, final ErrorReporter errorReporter) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaLogSensorDataAddMappingsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaLogSensorDataAddMappingsDialog.java index bfcf5aae454..3a7c0804cda 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaLogSensorDataAddMappingsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractRegattaLogSensorDataAddMappingsDialog.java @@ -17,6 +17,7 @@ import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTO; import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.DeviceIdentifierDTO; import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO; @@ -40,7 +41,7 @@ public abstract class AbstractRegattaLogSensorDataAddMappingsDialog extends Data private BoatDTO boatToSelect; private boolean inInstableTransitionState = false; - public AbstractRegattaLogSensorDataAddMappingsDialog(final SailingServiceAsync sailingService, final UserService userService, + public AbstractRegattaLogSensorDataAddMappingsDialog(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final ErrorReporter errorReporter, final StringMessages stringMessages, String leaderboardName, DialogCallback> callback) { super(stringMessages.add(stringMessages.deviceMappings()), stringMessages.add(stringMessages.deviceMappings()), @@ -52,16 +53,16 @@ public abstract class AbstractRegattaLogSensorDataAddMappingsDialog extends Data } }, true, callback); this.stringMessages = stringMessages; - deviceIdTable = new TrackFileImportDeviceIdentifierTableWrapper(sailingService, stringMessages, errorReporter); + deviceIdTable = new TrackFileImportDeviceIdentifierTableWrapper(sailingServiceWrite, stringMessages, errorReporter); deviceIdTable.removeTrackNameColumn(); importWidgetHolder = new SimplePanel(); deviceIdTable.getSelectionModel().addSelectionChangeHandler( event -> deviceSelectionChanged(deviceIdTable.getSelectionModel().getSelectedObject())); - boatTable = new BoatTableWrapper>(sailingService, userService, stringMessages, + boatTable = new BoatTableWrapper>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ false, /* enable Pager */ true, /* allowActions */ false); - competitorTable = new CompetitorTableWrapper<>(sailingService, userService, stringMessages, errorReporter, + competitorTable = new CompetitorTableWrapper<>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true, /* filterCompetitorWithBoat */ false, /* filterCompetitorsWithoutBoat */ false); boatTable.getSelectionModel().addSelectionChangeHandler(event -> { @@ -74,8 +75,8 @@ public abstract class AbstractRegattaLogSensorDataAddMappingsDialog extends Data }); this.leaderboardName = leaderboardName; - getBoatRegistrations(sailingService, errorReporter); - getCompetitorRegistrations(sailingService, errorReporter); + getBoatRegistrations(sailingServiceWrite, errorReporter); + getCompetitorRegistrations(sailingServiceWrite, errorReporter); } private void getBoatRegistrations(final SailingServiceAsync sailingService, final ErrorReporter errorReporter) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractTrackedRacesListComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractTrackedRacesListComposite.java index ad3deb9c396..6d4bfa4e564 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractTrackedRacesListComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractTrackedRacesListComposite.java @@ -45,7 +45,7 @@ import com.sap.sailing.domain.common.dto.RaceDTO; import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.RegattasDisplayer; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; import com.sap.sailing.gwt.ui.shared.RegattaDTO; @@ -86,7 +86,7 @@ public abstract class AbstractTrackedRacesListComposite extends AbstractComposit private Label noTrackedRacesLabel; - protected final SailingServiceAsync sailingService; + protected final SailingServiceWriteAsync sailingService; protected final ErrorReporter errorReporter; protected final RegattaRefresher regattaRefresher; protected final StringMessages stringMessages; @@ -109,11 +109,11 @@ public abstract class AbstractTrackedRacesListComposite extends AbstractComposit } public AbstractTrackedRacesListComposite(Component parent, ComponentContext context, - final SailingServiceAsync sailingService, + final SailingServiceWriteAsync sailingServiceWrite, final ErrorReporter errorReporter, final RegattaRefresher regattaRefresher, final StringMessages stringMessages, boolean hasMultiSelection, UserService userService) { super(parent, context); - this.sailingService = sailingService; + this.sailingService = sailingServiceWrite; this.errorReporter = errorReporter; this.regattaRefresher = regattaRefresher; this.multiSelection = hasMultiSelection; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java index 824acde52e5..dd60c87ed86 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java @@ -20,7 +20,7 @@ import com.sap.sailing.gwt.ui.adminconsole.coursecreation.CourseTemplatePanel; import com.sap.sailing.gwt.ui.adminconsole.coursecreation.MarkPropertiesPanel; import com.sap.sailing.gwt.ui.adminconsole.coursecreation.MarkRolePanel; import com.sap.sailing.gwt.ui.adminconsole.coursecreation.MarkTemplatePanel; -import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint; +import com.sap.sailing.gwt.ui.client.AbstractSailingWriteEntryPoint; import com.sap.sailing.gwt.ui.client.LeaderboardGroupsDisplayer; import com.sap.sailing.gwt.ui.client.LeaderboardGroupsRefresher; import com.sap.sailing.gwt.ui.client.LeaderboardsDisplayer; @@ -61,7 +61,7 @@ import com.sap.sse.security.ui.client.component.UserGroupManagementPanel; import com.sap.sse.security.ui.client.i18n.StringMessages; import com.sap.sse.security.ui.client.usermanagement.UserManagementPanel; -public class AdminConsoleEntryPoint extends AbstractSailingEntryPoint +public class AdminConsoleEntryPoint extends AbstractSailingWriteEntryPoint implements RegattaRefresher, LeaderboardsRefresher, LeaderboardGroupsRefresher { private final AdminConsoleTableResources tableResources = GWT.create(AdminConsoleTableResources.class); @@ -349,7 +349,7 @@ public class AdminConsoleEntryPoint extends AbstractSailingEntryPoint }, getStringMessages().igtimiAccounts(), SecuredDomainType.IGTIMI_ACCOUNT.getPermission(DefaultActions.values())); - ExpeditionDeviceConfigurationsPanel expeditionDeviceConfigurationsPanel = new ExpeditionDeviceConfigurationsPanel(getSailingService(), this, getStringMessages()); + ExpeditionDeviceConfigurationsPanel expeditionDeviceConfigurationsPanel = new ExpeditionDeviceConfigurationsPanel(getSailingService(), this, getStringMessages(), getUserService()); expeditionDeviceConfigurationsPanel.ensureDebugId("ExpeditionDeviceConfigurations"); panel.addToTabPanel(connectorsTabPanel, new DefaultRefreshableAdminConsolePanel(expeditionDeviceConfigurationsPanel) { @Override @@ -370,7 +370,7 @@ public class AdminConsoleEntryPoint extends AbstractSailingEntryPoint getSailingService(), getUserService(), this, getStringMessages(), this, eventManagementPanel); panel.addToTabPanel(connectorsTabPanel, new DefaultRefreshableAdminConsolePanel(structureImportUrlsManagementPanel), getStringMessages().manage2Sail() + " " + getStringMessages().regattaStructureImport(), - SecuredDomainType.REGATTA.getPermission(DefaultActions.CREATE)); // TODO bug4763 provide the default CREATE ownership for REGATTA / EVENT + SecuredDomainType.REGATTA.getPermission(DefaultActions.CREATE)); /* ADVANCED */ final HorizontalTabLayoutPanel advancedTabPanel = panel.addVerticalTab(getStringMessages().advanced(), diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AssignRacesToMediaDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AssignRacesToMediaDialog.java index 12e0ce63946..2261019b8e6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AssignRacesToMediaDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AssignRacesToMediaDialog.java @@ -15,7 +15,7 @@ import com.sap.sailing.domain.common.dto.TrackedRaceDTO; import com.sap.sailing.domain.common.media.MediaTrack; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.RegattasDisplayer; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sse.gwt.client.ErrorReporter; @@ -32,7 +32,7 @@ public class AssignRacesToMediaDialog extends DataEntryDialog refreshableBoatSelectionModel; private Button allowReloadButton; - public BoatPanel(final SailingServiceAsync sailingService, final UserService userService, + public BoatPanel(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final StringMessages stringMessages, final ErrorReporter errorReporter) { super(); - this.boatTable = new BoatTableWrapper<>(sailingService, userService, stringMessages, errorReporter, + this.boatTable = new BoatTableWrapper<>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ true, /* enablePager */ true, 100, true); this.refreshableBoatSelectionModel = (RefreshableMultiSelectionModel) boatTable.getSelectionModel(); VerticalPanel mainPanel = new VerticalPanel(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatRegistrationsPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatRegistrationsPanel.java index 779772d6ec4..4f7047efd54 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatRegistrationsPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatRegistrationsPanel.java @@ -19,7 +19,7 @@ import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.VerticalPanel; import com.sap.sailing.domain.common.dto.BoatDTO; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.Util; import com.sap.sse.gwt.client.ErrorReporter; @@ -66,7 +66,7 @@ public class BoatRegistrationsPanel extends FlowPanel implements BusyDisplay { * whether the pool of "all" boats is to be restricted to those obtained from the leaderboard, or * to all boats in the server's boat store */ - protected BoatRegistrationsPanel(final SailingServiceAsync sailingService, final UserService userService, + protected BoatRegistrationsPanel(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final StringMessages stringMessages, final ErrorReporter errorReporter, boolean editable, String leaderboardName, boolean canBoatsOfCompetitorsChangePerRace, String boatClass, Runnable validator, Consumer>> registeredBoatsRetriever, @@ -88,9 +88,9 @@ public class BoatRegistrationsPanel extends FlowPanel implements BusyDisplay { final HorizontalPanel boatRegistrationPanel = new HorizontalPanel(); final CaptionPanel allBoatsPanel = new CaptionPanel(stringMessages.boatPool()); final CaptionPanel registeredBoatsPanel = new CaptionPanel(stringMessages.registeredBoats()); - allBoatsTable = new BoatTableWrapper<>(sailingService, userService, stringMessages, errorReporter, /* multiSelection */ + allBoatsTable = new BoatTableWrapper<>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ true, /* enablePager */true, 20, false); - registeredBoatsTable = new BoatTableWrapper<>(sailingService, userService, stringMessages, errorReporter, /* multiSelection */ + registeredBoatsTable = new BoatTableWrapper<>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ true, /* enablePager */false, 20, false); allBoatsPanel.add(allBoatsTable); registeredBoatsPanel.add(registeredBoatsTable); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java index 6e0a9c0dc4a..e23ef6f0738 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatTableWrapper.java @@ -21,7 +21,7 @@ import com.google.gwt.user.client.ui.Label; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.ui.adminconsole.ColorColumn.ColorRetriever; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.Color; import com.sap.sse.common.Util; @@ -44,16 +44,17 @@ import com.sap.sse.security.ui.client.component.editacl.EditACLDialog; public class BoatTableWrapper> extends TableWrapper { private final LabeledAbstractFilterablePanel filterField; + private final SailingServiceWriteAsync sailingServiceWrite; - public BoatTableWrapper(SailingServiceAsync sailingService, final UserService userService, StringMessages stringMessages, + public BoatTableWrapper(SailingServiceWriteAsync sailingServiceWrite, final UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, boolean multiSelection, boolean enablePager, boolean allowActions) { - this(sailingService, userService, stringMessages, errorReporter, multiSelection, enablePager, DEFAULT_PAGING_SIZE, + this(sailingServiceWrite, userService, stringMessages, errorReporter, multiSelection, enablePager, DEFAULT_PAGING_SIZE, allowActions); } - public BoatTableWrapper(SailingServiceAsync sailingService, final UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, + public BoatTableWrapper(SailingServiceWriteAsync sailingServiceWrite, final UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, boolean multiSelection, boolean enablePager, int pagingSize, boolean allowActions) { - super(sailingService, stringMessages, errorReporter, multiSelection, enablePager, pagingSize, + super(sailingServiceWrite, stringMessages, errorReporter, multiSelection, enablePager, pagingSize, new EntityIdentityComparator() { @Override public boolean representSameEntity(BoatDTO dto1, BoatDTO dto2) { @@ -64,6 +65,7 @@ public class BoatTableWrapper> exte return t.getIdAsString().hashCode(); } }); + this.sailingServiceWrite = sailingServiceWrite; ListHandler boatColumnListHandler = getColumnSortHandler(); // boats table @@ -169,7 +171,6 @@ public class BoatTableWrapper> exte }; filterField.setUpdatePermissionFilterForCheckbox(boat -> userService.hasPermission(boat, DefaultActions.UPDATE)); registerSelectionModelOnNewDataProvider(filterField.getAllListDataProvider()); - // BoatTable edit features final HasPermissions type = SecuredDomainType.BOAT; AccessControlledActionsColumn boatActionColumn = create( @@ -178,15 +179,13 @@ public class BoatTableWrapper> exte this::openEditBoatDialog); boatActionColumn.addAction(BoatConfigImagesBarCell.ACTION_REFRESH, this::allowUpdate); final DialogConfig editOwnerShipDialog = EditOwnershipDialog.create( - userService.getUserManagementService(), SecuredDomainType.BOAT, null, stringMessages); + userService.getUserManagementService(), SecuredDomainType.BOAT, boatDTO -> refresh(Collections.singleton(boatDTO)), stringMessages); boatActionColumn.addAction(BoatConfigImagesBarCell.ACTION_CHANGE_OWNERSHIP, CHANGE_OWNERSHIP, editOwnerShipDialog::openOwnershipDialog); - final EditACLDialog.DialogConfig configACL = EditACLDialog .create(userService.getUserManagementService(), type, null, stringMessages); boatActionColumn.addAction(BoatConfigImagesBarCell.ACTION_CHANGE_ACL, DefaultActions.CHANGE_ACL, configACL::openACLDialog); - mainPanel.insert(filterField, 0); table.addColumnSortHandler(boatColumnListHandler); table.addColumn(boatNameColumn, stringMessages.name()); @@ -215,7 +214,7 @@ public class BoatTableWrapper> exte public void refreshBoatList(boolean loadOnlyStandaloneBoats, final Callback, Throwable> callback) { if (loadOnlyStandaloneBoats) { - sailingService.getStandaloneBoats(new AsyncCallback>() { + sailingServiceWrite.getStandaloneBoats(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Remote Procedure Call getBoats() - Failure: " + caught.getMessage()); @@ -234,7 +233,7 @@ public class BoatTableWrapper> exte } }); } else { - sailingService.getAllBoats(new AsyncCallback>() { + sailingServiceWrite.getAllBoats(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Remote Procedure Call getBoats() - Failure: " + caught.getMessage()); @@ -263,7 +262,7 @@ public class BoatTableWrapper> exte final BoatEditDialog dialog = new BoatEditDialog(getStringMessages(), originalBoat, boatClassName, new DialogCallback() { @Override public void ok(BoatDTO boat) { - sailingService.addOrUpdateBoat(boat, new AsyncCallback() { + sailingServiceWrite.addOrUpdateBoat(boat, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Error trying to update boat: " + caught.getMessage()); @@ -299,7 +298,7 @@ public class BoatTableWrapper> exte public void allowUpdate(final Iterable boats) { List serializableSingletonList = new ArrayList(); Util.addAll(boats, serializableSingletonList); - sailingService.allowBoatResetToDefaults(serializableSingletonList, new AsyncCallback() { + sailingServiceWrite.allowBoatResetToDefaults(serializableSingletonList, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Error trying to allow resetting boats " + boats diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatWithCertificateTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatWithCertificateTableWrapper.java index 9a2fc1821a7..181efa14a94 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatWithCertificateTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/BoatWithCertificateTableWrapper.java @@ -19,7 +19,7 @@ import com.google.gwt.user.client.ui.Label; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.orc.ORCCertificate; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.util.NaturalComparator; import com.sap.sse.gwt.client.ErrorReporter; @@ -43,11 +43,11 @@ public class BoatWithCertificateTableWrapper unlinkAction; private final Function isLinkedChecker; - public BoatWithCertificateTableWrapper(SailingServiceAsync sailingService, final UserService userService, + public BoatWithCertificateTableWrapper(SailingServiceWriteAsync sailingServiceWrite, final UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, boolean multiSelection, boolean enablePager, int pagingSize, boolean allowActions, Consumer unlinkAction, SecuredDTO objectToCheckUpdatePermissionFor, Function isLinkedChecker) { - super(sailingService, stringMessages, errorReporter, multiSelection, enablePager, pagingSize, + super(sailingServiceWrite, stringMessages, errorReporter, multiSelection, enablePager, pagingSize, new EntityIdentityComparator() { @Override public boolean representSameEntity(BoatDTO dto1, BoatDTO dto2) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CertificatesTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CertificatesTableWrapper.java index b4f941de445..6933c15776b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CertificatesTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CertificatesTableWrapper.java @@ -18,7 +18,7 @@ import com.google.gwt.user.cellview.client.TextColumn; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.orc.ORCCertificate; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; @@ -35,9 +35,9 @@ public class CertificatesTableWrapper filterField; - public CertificatesTableWrapper(SailingServiceAsync sailingService, final UserService userService, StringMessages stringMessages, + public CertificatesTableWrapper(SailingServiceWriteAsync sailingServiceWrite, final UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, boolean multiSelection, boolean enablePager, int pagingSize) { - super(sailingService, stringMessages, errorReporter, multiSelection, enablePager, pagingSize, new EntityIdentityComparator() { + super(sailingServiceWrite, stringMessages, errorReporter, multiSelection, enablePager, pagingSize, new EntityIdentityComparator() { @Override public boolean representSameEntity(ORCCertificate cert1, ORCCertificate cert2) { return cert1.getId().equals(cert2.getId()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactBoatTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactBoatTableWrapper.java index dee2696f1aa..b6a18932377 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactBoatTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactBoatTableWrapper.java @@ -21,7 +21,7 @@ import com.google.gwt.user.client.ui.Label; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.gwt.ui.adminconsole.ColorColumn.ColorRetriever; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.Color; import com.sap.sse.common.filter.Filter; @@ -35,9 +35,9 @@ public class CompactBoatTableWrapper filterField; private final Set boatsRegisteredWithRegatta; - public CompactBoatTableWrapper(SailingServiceAsync sailingService, StringMessages stringMessages, + public CompactBoatTableWrapper(SailingServiceWriteAsync sailingServiceWrite, StringMessages stringMessages, ErrorReporter errorReporter, boolean multiSelection, boolean enablePager) { - super(sailingService, stringMessages, errorReporter, multiSelection, enablePager, + super(sailingServiceWrite, stringMessages, errorReporter, multiSelection, enablePager, new EntityIdentityComparator() { @Override public boolean representSameEntity(BoatDTO dto1, BoatDTO dto2) { @@ -206,12 +206,12 @@ public class CompactBoatTableWrapper>() { + sailingServiceWrite.getBoatRegistrationsForLeaderboard(leaderboardName, new AsyncCallback>() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(getStringMessages().unableToObtainBoatsRegisteredWith(leaderboardName, caught.getMessage())); @@ -230,7 +230,7 @@ public class CompactBoatTableWrapper>() { + sailingServiceWrite.getAllBoats(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Remote Procedure Call getAllBoats() - Failure: " + caught.getMessage()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactCompetitorTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactCompetitorTableWrapper.java index 553058a4c47..78ed9040011 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactCompetitorTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompactCompetitorTableWrapper.java @@ -21,7 +21,7 @@ import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.gwt.ui.client.FlagImageRenderer; import com.sap.sailing.gwt.ui.client.FlagImageResolverImpl; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.util.NaturalComparator; import com.sap.sse.gwt.client.ErrorReporter; @@ -45,9 +45,9 @@ public class CompactCompetitorTableWrapper filterField; private final Map boatsForCompetitors; - public CompactCompetitorTableWrapper(SailingServiceAsync sailingService, StringMessages stringMessages, ErrorReporter errorReporter, + public CompactCompetitorTableWrapper(SailingServiceWriteAsync sailingServiceWrite, StringMessages stringMessages, ErrorReporter errorReporter, boolean multiSelection, boolean enablePager, UserService userService) { - super(sailingService, stringMessages, errorReporter, multiSelection, enablePager, + super(sailingServiceWrite, stringMessages, errorReporter, multiSelection, enablePager, new EntityIdentityComparator() { @Override public boolean representSameEntity(CompetitorDTO dto1, CompetitorDTO dto2) { @@ -191,7 +191,7 @@ public class CompactCompetitorTableWrapper result) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorDescriptorTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorDescriptorTableWrapper.java index 3f10ad46039..faa93c00570 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorDescriptorTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorDescriptorTableWrapper.java @@ -20,7 +20,7 @@ import com.sap.sailing.domain.common.CompetitorDescriptor; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.gwt.ui.client.FlagImageRenderer; import com.sap.sailing.gwt.ui.client.FlagImageResolverImpl; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.CountryCode; import com.sap.sse.common.util.NaturalComparator; @@ -85,9 +85,9 @@ public class CompetitorDescriptorTableWrapper() { @Override public boolean representSameEntity(CompetitorDescriptor dto1, CompetitorDescriptor dto2) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java index dc06308d474..00adc7e4c20 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorEditDialog.java @@ -102,7 +102,6 @@ public abstract class CompetitorEditDialog this.ensureDebugId("CompetitorEditDialog"); this.stringMessages = stringMessages; this.competitorToEdit = competitorToEdit; - this.name = createTextBox(competitorToEdit.getName()); name.ensureDebugId("NameTextBox"); this.shortName = createTextBox(competitorToEdit.getShortName()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorInvitationHelper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorInvitationHelper.java index cf625080d91..9996d3a46cd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorInvitationHelper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorInvitationHelper.java @@ -5,7 +5,7 @@ import java.util.Set; import com.google.gwt.i18n.client.LocaleInfo; import com.google.gwt.user.client.rpc.AsyncCallback; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sse.common.Util.Pair; @@ -17,12 +17,12 @@ import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; public class CompetitorInvitationHelper { private StringMessages stringMessages; - private SailingServiceAsync sailingService; + private SailingServiceWriteAsync sailingServiceWrite; private ErrorReporter errorReporter; - public CompetitorInvitationHelper(SailingServiceAsync sailingService, StringMessages stringMessages, ErrorReporter errorReporter) { + public CompetitorInvitationHelper(SailingServiceWriteAsync sailingServiceWrite, StringMessages stringMessages, ErrorReporter errorReporter) { this.stringMessages = stringMessages; - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.errorReporter = errorReporter; } @@ -50,11 +50,11 @@ public class CompetitorInvitationHelper { } private void openChooseEventDialogAndSendMails(final Set competitors, final String leaderboardName) { - new SelectEventAndHostnameDialog(sailingService, stringMessages, errorReporter, leaderboardName, new DialogCallback>() { + new SelectEventAndHostnameDialog(sailingServiceWrite, stringMessages, errorReporter, leaderboardName, new DialogCallback>() { @Override public void ok(Pair result) { - sailingService.inviteCompetitorsForTrackingViaEmail(result.getB(), result.getA(), leaderboardName, + sailingServiceWrite.inviteCompetitorsForTrackingViaEmail(result.getB(), result.getA(), leaderboardName, competitors, stringMessages.appstoreSapSailInsight(), stringMessages.playstoreInsightApp(), diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorPanel.java index 91de341b95f..fbb2abbc9f3 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorPanel.java @@ -9,10 +9,12 @@ import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.VerticalPanel; import com.sap.sailing.domain.common.CompetitorDescriptor; +import com.sap.sailing.domain.common.dto.BoatClassDTO; +import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTOImpl; import com.sap.sailing.gwt.ui.adminconsole.CompetitorImportProviderSelectionDialog.MatchImportedCompetitorsDialogFactory; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel; @@ -32,19 +34,21 @@ public class CompetitorPanel extends SimplePanel implements BusyDisplay { private final CompetitorTableWrapper> competitorTable; private final RefreshableMultiSelectionModel refreshableCompetitorSelectionModel; private final String leaderboardName; - + private final String boatClassName; private final BusyIndicator busyIndicator; - public CompetitorPanel(final SailingServiceAsync sailingService, final UserService userService, final StringMessages stringMessages, + public CompetitorPanel(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final StringMessages stringMessages, final ErrorReporter errorReporter) { - this(sailingService, userService, null, stringMessages, errorReporter); + this(sailingServiceWrite, userService, /* leaderboardName */ null, /* boatClassName */ null, /* createWithBoatByDefault */ true, + stringMessages, errorReporter); } - public CompetitorPanel(final SailingServiceAsync sailingService, final UserService userService, final String leaderboardName, - final StringMessages stringMessages, final ErrorReporter errorReporter) { + public CompetitorPanel(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final String leaderboardName, + String boatClassName, boolean createWithBoatByDefault, final StringMessages stringMessages, final ErrorReporter errorReporter) { super(); this.leaderboardName = leaderboardName; - this.competitorTable = new CompetitorTableWrapper<>(sailingService, userService, stringMessages, errorReporter, /* multiSelection */ true, /* enablePager */ true, + this.boatClassName = boatClassName; + this.competitorTable = new CompetitorTableWrapper<>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ true, /* enablePager */ true, /* filterCompetitorWithBoat */ false, /* filterCompetitorsWithoutBoat */ false); this.refreshableCompetitorSelectionModel = (RefreshableMultiSelectionModel) competitorTable.getSelectionModel(); busyIndicator = new SimpleBusyIndicator(false, 0.8f); @@ -53,35 +57,30 @@ public class CompetitorPanel extends SimplePanel implements BusyDisplay { this.setWidget(mainPanel); final AccessControlledButtonPanel buttonPanel = new AccessControlledButtonPanel(userService, COMPETITOR); mainPanel.add(buttonPanel); - final Button refreshButton = buttonPanel.addUnsecuredAction(stringMessages.refresh(), this::refreshCompetitorList); refreshButton.ensureDebugId("RefreshButton"); - final Button allowReloadButton = buttonPanel.addUnsecuredAction(stringMessages.allowReload(), () -> competitorTable.allowUpdate(refreshableCompetitorSelectionModel.getSelectedSet())); refreshableCompetitorSelectionModel.addSelectionChangeHandler( event -> allowReloadButton.setEnabled(!refreshableCompetitorSelectionModel.getSelectedSet().isEmpty())); allowReloadButton.setEnabled(!refreshableCompetitorSelectionModel.getSelectedSet().isEmpty()); - final Button addCompetitorButton = buttonPanel.addCreateAction(stringMessages.add(), - this::openAddCompetitorDialog); + ()->openAddCompetitorDialog(createWithBoatByDefault)); addCompetitorButton.ensureDebugId("AddCompetitorButton"); - buttonPanel.addUnsecuredAction(stringMessages.selectAll(), () -> { for (CompetitorDTO c : competitorTable.getDataProvider().getList()) { refreshableCompetitorSelectionModel.setSelected(c, true); } }); - buttonPanel.addCreateAction(stringMessages.importCompetitors(), () -> { - sailingService.getCompetitorProviderNames(new AsyncCallback>() { + sailingServiceWrite.getCompetitorProviderNames(new AsyncCallback>() { @Override public void onSuccess(Iterable providerNames) { MatchImportedCompetitorsDialogFactory matchCompetitorsDialogFactory = getMatchCompetitorsDialogFactory( - sailingService, userService, stringMessages, errorReporter); + sailingServiceWrite, userService, stringMessages, errorReporter); CompetitorImportProviderSelectionDialog dialog = new CompetitorImportProviderSelectionDialog( - matchCompetitorsDialogFactory, CompetitorPanel.this, providerNames, sailingService, + matchCompetitorsDialogFactory, CompetitorPanel.this, providerNames, sailingServiceWrite, stringMessages, errorReporter); dialog.show(); } @@ -93,34 +92,31 @@ public class CompetitorPanel extends SimplePanel implements BusyDisplay { } }); }); - // only if this competitor panel is connected to a leaderboard, we want to enable invitations if (leaderboardName != null) { buttonPanel.addCreateAction(stringMessages.inviteSelectedCompetitors(), () -> { final Set competitors = refreshableCompetitorSelectionModel.getSelectedSet(); - final CompetitorInvitationHelper helper = new CompetitorInvitationHelper(sailingService, stringMessages, + final CompetitorInvitationHelper helper = new CompetitorInvitationHelper(sailingServiceWrite, stringMessages, errorReporter); helper.inviteCompetitors(competitors, leaderboardName); }); } - mainPanel.add(busyIndicator); mainPanel.add(competitorTable); - if (leaderboardName != null) { refreshCompetitorList(); } } private MatchImportedCompetitorsDialogFactory getMatchCompetitorsDialogFactory( - final SailingServiceAsync sailingService, final UserService userService, final StringMessages stringMessages, + final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final StringMessages stringMessages, final ErrorReporter errorReporter) { return new MatchImportedCompetitorsDialogFactory() { @Override public MatchImportedCompetitorsDialog createMatchImportedCompetitorsDialog( final Iterable competitorDescriptors, final Iterable competitors) { - ImportCompetitorCallback importCompetitorCallback = new ImportCompetitorCallback(sailingService, errorReporter, stringMessages) { + ImportCompetitorCallback importCompetitorCallback = new ImportCompetitorCallback(sailingServiceWrite, errorReporter, stringMessages) { @Override public void registerCompetitors(Set competitorDTOs) { super.registerCompetitors(competitorDTOs); @@ -128,15 +124,18 @@ public class CompetitorPanel extends SimplePanel implements BusyDisplay { } }; return new MatchImportedCompetitorsDialog(competitorDescriptors, competitors, stringMessages, - sailingService, userService, errorReporter, importCompetitorCallback); + sailingServiceWrite, userService, errorReporter, importCompetitorCallback); } }; } - private void openAddCompetitorDialog() { + private void openAddCompetitorDialog(boolean createWithBoatByDefault) { CompetitorWithBoatDTOImpl competitorDTO = new CompetitorWithBoatDTOImpl(); - competitorDTO.setBoat(null); - competitorTable.openEditCompetitorWithoutBoatDialog(competitorDTO); + BoatClassDTO boatClassDTO = new BoatClassDTO(boatClassName, /* hullLength */ null, /* hullBeam */ null); + BoatDTO boatDTO = new BoatDTO(); + boatDTO.setBoatClass(boatClassDTO); + competitorDTO.setBoat(boatDTO); + competitorTable.openCompetitorWithBoatAddDialog(competitorDTO, createWithBoatByDefault); } public void refreshCompetitorList() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorRegistrationsPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorRegistrationsPanel.java index 0982c885fdb..110df35d54c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorRegistrationsPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorRegistrationsPanel.java @@ -24,7 +24,7 @@ import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTOImpl; import com.sap.sailing.domain.common.dto.CompetitorWithToolTipDTO; import com.sap.sailing.gwt.ui.adminconsole.CompetitorImportProviderSelectionDialog.MatchImportedCompetitorsDialogFactory; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.Util; import com.sap.sse.gwt.client.ErrorReporter; @@ -76,7 +76,7 @@ public class CompetitorRegistrationsPanel extends FlowPanel implements BusyDispl * to all competitors in the server's competitor store * @param additionalWidgetsBeforeTables widgets to be inserted above / before the competitor tables; may be {@code null} or empty */ - protected CompetitorRegistrationsPanel(final SailingServiceAsync sailingService, final UserService userService, + protected CompetitorRegistrationsPanel(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final StringMessages stringMessages, final ErrorReporter errorReporter, boolean editable, String leaderboardName, boolean canBoatsOfCompetitorsChangePerRace, String boatClass, Runnable validator, Consumer>> registeredCompetitorsRetriever, @@ -87,7 +87,7 @@ public class CompetitorRegistrationsPanel extends FlowPanel implements BusyDispl this.leaderboardName = leaderboardName; this.busyIndicator = new SimpleBusyIndicator(); this.registeredCompetitorsRetriever = registeredCompetitorsRetriever; - this.importCompetitorCallback = new RaceOrRegattaImportCompetitorCallback(this, sailingService, errorReporter, stringMessages); + this.importCompetitorCallback = new RaceOrRegattaImportCompetitorCallback(this, sailingServiceWrite, errorReporter, stringMessages); final HorizontalPanel buttonPanel = new HorizontalPanel(); addCompetitorButton = new Button(stringMessages.add(stringMessages.competitor())); addCompetitorButton.addClickHandler(new ClickHandler() { @@ -112,7 +112,7 @@ public class CompetitorRegistrationsPanel extends FlowPanel implements BusyDispl @Override public void onClick(ClickEvent event) { Set competitors = registeredCompetitorsTable.getSelectionModel().getSelectedSet(); - CompetitorInvitationHelper helper = new CompetitorInvitationHelper(sailingService, stringMessages, + CompetitorInvitationHelper helper = new CompetitorInvitationHelper(sailingServiceWrite, stringMessages, errorReporter); helper.inviteCompetitors(competitors, leaderboardName); } @@ -121,13 +121,13 @@ public class CompetitorRegistrationsPanel extends FlowPanel implements BusyDispl competitorImportButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - sailingService.getCompetitorProviderNames(new AsyncCallback>() { + sailingServiceWrite.getCompetitorProviderNames(new AsyncCallback>() { @Override public void onSuccess(Iterable providerNames) { MatchImportedCompetitorsDialogFactory matchCompetitorsDialogFactory = getMatchCompetitorsDialogFactory( - sailingService, userService, stringMessages, errorReporter); + sailingServiceWrite, userService, stringMessages, errorReporter); CompetitorImportProviderSelectionDialog dialog = new CompetitorImportProviderSelectionDialog( - matchCompetitorsDialogFactory, CompetitorRegistrationsPanel.this, providerNames, sailingService, + matchCompetitorsDialogFactory, CompetitorRegistrationsPanel.this, providerNames, sailingServiceWrite, stringMessages, errorReporter); dialog.show(); } @@ -143,9 +143,9 @@ public class CompetitorRegistrationsPanel extends FlowPanel implements BusyDispl final HorizontalPanel competitorRegistrationPanel = new HorizontalPanel(); final CaptionPanel allCompetitorsPanel = new CaptionPanel(stringMessages.competitorPool()); final CaptionPanel registeredCompetitorsPanel = new CaptionPanel(stringMessages.registeredCompetitors()); - allCompetitorsTable = new CompetitorTableWrapper<>(sailingService, userService, stringMessages, errorReporter, /* multiSelection */ + allCompetitorsTable = new CompetitorTableWrapper<>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ true, /* enablePager */true, /* filterCompetitorWithBoat */ canBoatsOfCompetitorsChangePerRace, /* filterCompetitorsWithoutBoat */ !canBoatsOfCompetitorsChangePerRace); - registeredCompetitorsTable = new CompetitorTableWrapper<>(sailingService, userService, stringMessages, errorReporter, /* multiSelection */ + registeredCompetitorsTable = new CompetitorTableWrapper<>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ true, /* enablePager */false, /* filterCompetitorWithBoat */ false, /* filterCompetitorsWithoutBoat */ false); registeredCompetitorsTable.getSelectionModel().addSelectionChangeHandler(event -> validateAndUpdate()); allCompetitorsPanel.add(allCompetitorsTable); @@ -205,7 +205,7 @@ public class CompetitorRegistrationsPanel extends FlowPanel implements BusyDispl } private MatchImportedCompetitorsDialogFactory getMatchCompetitorsDialogFactory( - final SailingServiceAsync sailingService, final UserService userService, final StringMessages stringMessages, + final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final StringMessages stringMessages, final ErrorReporter errorReporter) { return new MatchImportedCompetitorsDialogFactory() { @Override @@ -213,7 +213,7 @@ public class CompetitorRegistrationsPanel extends FlowPanel implements BusyDispl final Iterable competitorDescriptors, final Iterable competitors) { return new MatchImportedCompetitorsDialog(competitorDescriptors, competitors, stringMessages, - sailingService, userService, errorReporter, importCompetitorCallback); + sailingServiceWrite, userService, errorReporter, importCompetitorCallback); } }; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorSelectionDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorSelectionDialog.java index 6077e0a43d4..425b9ee5a42 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorSelectionDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorSelectionDialog.java @@ -6,7 +6,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.celltable.RefreshableSingleSelectionModel; @@ -32,13 +32,13 @@ import com.sap.sse.security.ui.client.UserService; public class CompetitorSelectionDialog extends DataEntryDialog { private final CompetitorTableWrapper> competitorTable; - public CompetitorSelectionDialog(SailingServiceAsync sailingService, UserService userService, + public CompetitorSelectionDialog(SailingServiceWriteAsync sailingServiceWrite, UserService userService, ErrorReporter errorReporter, String title, String message, Consumer>> competitorProvider, StringMessages stringMessages, CompetitorDTO initialSelection, DialogCallback callback) { super(title, message, stringMessages.ok(), stringMessages.cancel(), /* validator */ null, callback); - competitorTable = new CompetitorTableWrapper<>(sailingService, userService, stringMessages, errorReporter, + competitorTable = new CompetitorTableWrapper<>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true, /* filter with boat */ false, /* filter without boat */ false); competitorProvider.accept(new AsyncCallback>() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java index 040f346ada6..3cb51c625c8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorTableWrapper.java @@ -29,7 +29,7 @@ import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.ui.adminconsole.ColorColumn.ColorRetriever; import com.sap.sailing.gwt.ui.client.FlagImageRenderer; import com.sap.sailing.gwt.ui.client.FlagImageResolverImpl; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.Color; import com.sap.sse.common.Util; @@ -82,9 +82,9 @@ public class CompetitorTableWrapper() { @Override public boolean representSameEntity(CompetitorDTO dto1, CompetitorDTO dto2) { @@ -331,7 +331,7 @@ public class CompetitorTableWrapper editOwnerShipDialog = EditOwnershipDialog.create(userService.getUserManagementService(), SecuredDomainType.COMPETITOR, - null, stringMessages); + competitorDTO -> refresh(Collections.singleton(competitorDTO)), stringMessages); competitorActionColumn.addAction(CompetitorConfigImagesBarCell.ACTION_CHANGE_OWNERSHIP, CHANGE_OWNERSHIP, editOwnerShipDialog::openOwnershipDialog); final EditACLDialog.DialogConfig configACL = EditACLDialog @@ -399,9 +399,9 @@ public class CompetitorTableWrapper() { @Override public void ok(final CompetitorWithBoatDTO competitor) { - sailingService.addOrUpdateCompetitorWithBoat(competitor, new AsyncCallback() { + sailingServiceWrite.addOrUpdateCompetitorWithBoat(competitor, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Error trying to update competitor with boat: " + caught.getMessage()); @@ -459,11 +459,31 @@ public class CompetitorTableWrapper() { + @Override + public void ok(final CompetitorWithBoatDTO competitor) { + if (competitor.hasBoat()) { + sailingServiceWrite.addOrUpdateCompetitorWithBoat(competitor, createAddCompetitorCallback()); + } else { + sailingServiceWrite.addOrUpdateCompetitorWithoutBoat(competitor, createAddCompetitorCallback()); + } + } + + @Override + public void cancel() { + } + }); + dialog.show(); + + } + void openEditCompetitorWithoutBoatDialog(final CompetitorDTO originalCompetitor) { final CompetitorEditDialog dialog = CompetitorEditDialog.create(getStringMessages(), originalCompetitor, new DialogCallback() { @Override public void ok(final CompetitorDTO competitor) { - sailingService.addOrUpdateCompetitorWithoutBoat(competitor, new AsyncCallback() { + sailingServiceWrite.addOrUpdateCompetitorWithoutBoat(competitor, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Error trying to update competitor: " + caught.getMessage()); @@ -496,7 +516,7 @@ public class CompetitorTableWrapper competitors) { List serializableSingletonList = new ArrayList<>(); Util.addAll(competitors, serializableSingletonList); - sailingService.allowCompetitorResetToDefaults(serializableSingletonList, new AsyncCallback() { + sailingServiceWrite.allowCompetitorResetToDefaults(serializableSingletonList, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Error trying to allow resetting competitors " + competitors @@ -534,4 +554,19 @@ public class CompetitorTableWrapper AsyncCallback createAddCompetitorCallback() { + return new AsyncCallback() { + @Override + public void onFailure(Throwable caught) { + errorReporter.reportError("Error trying to add competitor: " + caught.getMessage()); + } + + @Override + public void onSuccess(T addedCompetitor) { + getFilterField().add(addedCompetitor); + getDataProvider().refresh(); + } + }; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorToBoatMappingsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorToBoatMappingsDialog.java index eb8359d4409..43fe990a268 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorToBoatMappingsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorToBoatMappingsDialog.java @@ -18,7 +18,7 @@ import com.google.gwt.view.client.ListDataProvider; import com.google.gwt.view.client.SelectionChangeEvent; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.Util; import com.sap.sse.gwt.client.ErrorReporter; @@ -60,15 +60,15 @@ public class CompetitorToBoatMappingsDialog extends DataEntryDialog competitorsAndBoats, DialogCallback> callback, UserService userService) { super(stringMessages.actionEditCompetitorToBoatAssignments(), null, stringMessages.ok(), stringMessages.cancel(), new CompetitorToBoatMappingValidator(), callback); this.stringMessages = stringMessages; this.competitorToBoatMappings = new HashMap<>(competitorsAndBoats); - this.competitorTable = new CompactCompetitorTableWrapper<>(sailingService, stringMessages, errorReporter, + this.competitorTable = new CompactCompetitorTableWrapper<>(sailingServiceWrite, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true, userService); - this.boatTable = new CompactBoatTableWrapper<>(sailingService, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true); + this.boatTable = new CompactBoatTableWrapper<>(sailingServiceWrite, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true); ImagesBarColumn competitorActionColumn = new ImagesBarColumn<>(new CompactCompetitorConfigImagesBarCell(stringMessages)); competitorActionColumn.setFieldUpdater(new FieldUpdater() { @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorToBoatMappingsViewPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorToBoatMappingsViewPanel.java index 1de886e2b12..53c638fa75e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorToBoatMappingsViewPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorToBoatMappingsViewPanel.java @@ -10,7 +10,7 @@ import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.view.client.SelectionChangeEvent; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.async.MarkedAsyncCallback; @@ -30,25 +30,25 @@ public class CompetitorToBoatMappingsViewPanel extends SimplePanel { private final String leaderboardName; private final String raceColumnName; private final String fleetName; - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final StringMessages stringMessages; private final ErrorReporter errorReporter; private final RefreshableSelectionModel refreshableCompetitorSelectionModel; - public CompetitorToBoatMappingsViewPanel(final SailingServiceAsync sailingService, final StringMessages stringMessages, + public CompetitorToBoatMappingsViewPanel(final SailingServiceWriteAsync sailingServiceWrite, final StringMessages stringMessages, final ErrorReporter errorReporter, final String leaderboardName, final String raceColumnName, final String fleetName, UserService userService) { super(); - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.stringMessages = stringMessages; this.leaderboardName = leaderboardName; this.raceColumnName = raceColumnName; this.fleetName = fleetName; this.errorReporter = errorReporter; - this.competitorTable = new CompactCompetitorTableWrapper<>(sailingService, stringMessages, errorReporter, + this.competitorTable = new CompactCompetitorTableWrapper<>(sailingServiceWrite, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true, userService); - this.boatTable = new CompactBoatTableWrapper<>(sailingService, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true); + this.boatTable = new CompactBoatTableWrapper<>(sailingServiceWrite, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true); refreshableCompetitorSelectionModel = competitorTable.getSelectionModel(); refreshableCompetitorSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() { public void onSelectionChange(SelectionChangeEvent event) { @@ -94,7 +94,7 @@ public class CompetitorToBoatMappingsViewPanel extends SimplePanel { } private void selectBoatForCompetitor(CompetitorDTO selectedCompetitor) { - sailingService.getBoatLinkedToCompetitorForRace(leaderboardName, + sailingServiceWrite.getBoatLinkedToCompetitorForRace(leaderboardName, raceColumnName, fleetName, selectedCompetitor.getIdAsString(), new MarkedAsyncCallback( new AsyncCallback() { @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorWithBoatCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorWithBoatCreateDialog.java index 271c6ef0882..2225922d200 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorWithBoatCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorWithBoatCreateDialog.java @@ -14,7 +14,7 @@ import com.google.gwt.view.client.SelectionChangeEvent; import com.sap.sailing.domain.common.dto.BoatClassDTO; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTO; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.Color; import com.sap.sse.common.Distance; @@ -43,7 +43,7 @@ public class CompetitorWithBoatCreateDialog extends AbstractCompetitorWithBoatDi * The boat class is the default shown boat class for new boats. Set null if your boat is * already initialized or you don't want a default boat class. */ - public CompetitorWithBoatCreateDialog(SailingServiceAsync sailingService, final UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, CompetitorWithBoatDTO competitorToEdit, + public CompetitorWithBoatCreateDialog(SailingServiceWriteAsync sailingServiceWrite, final UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, CompetitorWithBoatDTO competitorToEdit, DialogCallback callback, String boatClass) { super("Add competitor with boat", stringMessages, competitorToEdit, callback, boatClass); this.ensureDebugId("CompetitorWithBoatCreateDialog"); @@ -64,7 +64,7 @@ public class CompetitorWithBoatCreateDialog extends AbstractCompetitorWithBoatDi }); newBoatPanel = new VerticalPanel(); existingBoatPanel = new VerticalPanel(); - this.existingBoatsTable = new BoatTableWrapper<>(sailingService, userService, stringMessages, errorReporter, /* multiSelection */ false, + this.existingBoatsTable = new BoatTableWrapper<>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true, /* pagingSize*/ 10, false); existingBoatsTable.refreshBoatList(true, /* callback */ null); this.existingBoatsTable.getSelectionModel().addSelectionChangeHandler(new SelectionChangeEvent.Handler() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorWithBoatEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorWithBoatEditDialog.java index e8e0ac34af5..3bd08ca3b99 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorWithBoatEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorWithBoatEditDialog.java @@ -4,12 +4,8 @@ import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; -import com.sap.sailing.domain.common.dto.BoatClassDTO; -import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTO; import com.sap.sailing.gwt.ui.client.StringMessages; -import com.sap.sse.common.Color; -import com.sap.sse.common.Distance; /** * An edit for a competitor with a boat @@ -27,24 +23,10 @@ public class CompetitorWithBoatEditDialog extends AbstractCompetitorWithBoatDial */ public CompetitorWithBoatEditDialog(StringMessages stringMessages, CompetitorWithBoatDTO competitorToEdit, DialogCallback callback, String boatClass) { - super("Edit competitor with boat", stringMessages, competitorToEdit, callback, boatClass); + super(stringMessages.editCompetitorWithBoat(), stringMessages, competitorToEdit, callback, boatClass); this.ensureDebugId("CompetitorWithBoatEditDialog"); } - @Override - protected BoatDTO getBoat() { - BoatDTO result = null; - Color boatColor; - if (boatDisplayColorTextBox.isValid()) { - boatColor = boatDisplayColorTextBox.getColor(); - } else { - boatColor = new InvalidColor(new IllegalArgumentException(boatDisplayColorTextBox.getValue()), getStringMessages()); - } - BoatClassDTO boatClass = new BoatClassDTO(boatClassNameTextBox.getValue(), Distance.NULL, Distance.NULL); - result = new BoatDTO(getCompetitorToEdit().getBoat().getIdAsString(), boatNameTextBox.getValue(), boatClass, sailIdTextBox.getValue(), boatColor); - return result; - } - @Override protected Widget getAdditionalWidget() { VerticalPanel result = new VerticalPanel(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorWithOptionalBoatAddDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorWithOptionalBoatAddDialog.java new file mode 100644 index 00000000000..f332c059f18 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CompetitorWithOptionalBoatAddDialog.java @@ -0,0 +1,134 @@ +package com.sap.sailing.gwt.ui.adminconsole; + +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.user.client.ui.CheckBox; +import com.google.gwt.user.client.ui.Grid; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.SuggestBox; +import com.google.gwt.user.client.ui.VerticalPanel; +import com.google.gwt.user.client.ui.Widget; +import com.sap.sailing.domain.common.dto.BoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTO; +import com.sap.sailing.gwt.ui.client.StringMessages; + +/** + * An Add dialog for a competitor with an optional boat. If {@link #withBoatCheckBox} is checked the + * {@link #boatDataPanel} is visible and validated. While the dialog always returns a + * {@link CompetitorWithBoatDTO}, the resulting object may still have {@link CompetitorWithBoatDTO#hasBoat() hasBoat()==false} + * in which case the {@link #withBoatCheckBox} was not ticked. + * + * @author Dmitry Bilyk + */ + +public class CompetitorWithOptionalBoatAddDialog extends AbstractCompetitorWithBoatDialog { + + private final CheckBox withBoatCheckBox; + private final VerticalPanel boatDataPanel; + + /** + * The class creates the UI-dialog to type in the Data about a competitor. + * + * @param competitorToAdd + * The 'competitorToAdd' parameter contains the competitor which should be initialized. + * @param createWithBoatByDefault + * decides the default setting of the {@link #withBoatCheckBox}. + * @param boatClass + * The boat class is the default shown boat class for new boats. Set null if your boat is + * already initialized or you don't want a default boat class. + */ + public CompetitorWithOptionalBoatAddDialog(StringMessages stringMessages, CompetitorWithBoatDTO competitorToAdd, + boolean createWithBoatByDefault, DialogCallback callback) { + this(stringMessages, competitorToAdd, new CheckBox(stringMessages.withBoat()), createWithBoatByDefault, callback); + } + + public CompetitorWithOptionalBoatAddDialog(StringMessages stringMessages, CompetitorWithBoatDTO competitorToAdd, + CheckBox withBoatCheckBox, boolean createWithBoatByDefault, DialogCallback callback) { + super(stringMessages.addCompetitor(), stringMessages, competitorToAdd, callback, null, + new CompetitorWithOptionalBoatAddDialog.CompetitorWithOptionalBoatValidator(withBoatCheckBox, stringMessages)); + this.withBoatCheckBox = withBoatCheckBox; + this.withBoatCheckBox.ensureDebugId("WithBoatCheckBox"); + this.withBoatCheckBox.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + boatDataPanel.setVisible(withBoatCheckBox.getValue()); + validateAndUpdate(); + } + }); + this.withBoatCheckBox.setValue(createWithBoatByDefault); + boatDataPanel = new VerticalPanel(); + boatDataPanel.setVisible(createWithBoatByDefault); + this.ensureDebugId("CompetitorWithBoatAddDialog"); + } + + @Override + protected Widget getAdditionalWidget() { + VerticalPanel result = new VerticalPanel(); + result.add(super.getAdditionalWidget()); + result.add(withBoatCheckBox); + boatDataPanel.add(createHeadlineLabel(getStringMessages().boat())); + Grid grid = new Grid(5, 2); + grid.setWidget(0, 0, new Label(getStringMessages().name())); + grid.setWidget(0, 1, boatNameTextBox); + grid.setWidget(1, 0, new Label(getStringMessages().sailNumber())); + grid.setWidget(1, 1, sailIdTextBox); + grid.setWidget(2, 0, new Label(getStringMessages().boatClass())); + grid.setWidget(2, 1, boatClassNameTextBox); + grid.setWidget(3, 0, new Label(getStringMessages().color())); + grid.setWidget(3, 1, boatDisplayColorTextBox); + boatDataPanel.add(grid); + result.add(boatDataPanel); + return result; + } + + @Override + protected CompetitorWithBoatDTO getResult() { + CompetitorWithBoatDTO competitorWithOptionalBoat = super.getResult(); + if (!withBoatCheckBox.getValue()) { + competitorWithOptionalBoat.setBoat(null); + } + return competitorWithOptionalBoat; + } + + @Override + protected void setBoatClassNameEnabled(SuggestBox boatClassNameTextBox, boolean enabled) { + super.setBoatClassNameEnabled(boatClassNameTextBox, true); + } + + protected static class CompetitorWithOptionalBoatValidator + extends CompetitorWithoutBoatValidator { + private final StringMessages stringMessages; + private final CheckBox withBoatCheckBox; + + public CompetitorWithOptionalBoatValidator(CheckBox withBoatCheckBox, StringMessages stringMessages) { + super(stringMessages); + this.withBoatCheckBox = withBoatCheckBox; + this.stringMessages = stringMessages; + } + + @Override + public String getErrorMessage(CompetitorWithBoatDTO competitorToValidate) { + String result = super.getErrorMessage(competitorToValidate); + if (withBoatCheckBox.getValue()) { + if (result == null) { + BoatDTO boatToValidate = competitorToValidate.getBoat(); + boolean invalidSailId = boatToValidate.getSailId() == null || boatToValidate.getSailId().isEmpty(); + boolean invalidName = boatToValidate.getName() == null || boatToValidate.getName().isEmpty(); + if (invalidSailId && invalidName) { + result = stringMessages.pleaseEnterASailNumberOrABoatName(); + } else if (boatToValidate.getColor() != null && boatToValidate.getColor() instanceof InvalidColor) { + result = boatToValidate.getColor().getAsHtml(); + } else if (isBoatClassInvalid(boatToValidate)) { + result = stringMessages.pleaseEnterABoatClass(); + } + } + } + return result; + } + + private boolean isBoatClassInvalid(BoatDTO boatToValidate) { + return boatToValidate.getBoatClass().getName() == null || boatToValidate.getBoatClass().getName().isEmpty(); + } + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ControlPointTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ControlPointTableWrapper.java index dcf4dbaa9ba..9ae0b31116b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ControlPointTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ControlPointTableWrapper.java @@ -1,7 +1,7 @@ package com.sap.sailing.gwt.ui.adminconsole; import com.google.gwt.user.cellview.client.TextColumn; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.ControlPointDTO; import com.sap.sailing.gwt.ui.shared.GateDTO; @@ -11,9 +11,9 @@ import com.sap.sse.gwt.client.celltable.EntityIdentityComparator; import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel; public class ControlPointTableWrapper> extends TableWrapper { - public ControlPointTableWrapper(boolean multiSelection, SailingServiceAsync sailingService, final StringMessages stringMessages, + public ControlPointTableWrapper(boolean multiSelection, SailingServiceWriteAsync sailingServiceWrite, final StringMessages stringMessages, ErrorReporter errorReporter) { - super(sailingService, stringMessages, errorReporter, multiSelection, /* enablePager */ true, + super(sailingServiceWrite, stringMessages, errorReporter, multiSelection, /* enablePager */ true, new EntityIdentityComparator() { @Override public boolean representSameEntity(ControlPointDTO dto1, ControlPointDTO dto2) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CopyCourseAndCompetitorsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CopyCourseAndCompetitorsDialog.java index 50dde3bccc1..9f5e0123ae8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CopyCourseAndCompetitorsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CopyCourseAndCompetitorsDialog.java @@ -11,7 +11,7 @@ import com.google.gwt.user.client.ui.Widget; import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SelectionChangeEvent.Handler; import com.sap.sailing.gwt.ui.adminconsole.AbstractLeaderboardConfigPanel.RaceColumnDTOAndFleetDTOWithNameBasedEquality; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.Distance; import com.sap.sse.gwt.client.ErrorReporter; @@ -26,11 +26,11 @@ public class CopyCourseAndCompetitorsDialog extends DataEntryDialog races, String leaderboardName, Distance buoyZoneRadius, DialogCallback dialogCallback) { super(stringMessages.selectRaces(), stringMessages.selectRaces(), stringMessages.ok(), stringMessages.cancel(), @@ -48,7 +48,7 @@ public class CopyCourseAndCompetitorsDialog extends DataEntryDialog>( - sailingService, stringMessages, errorReporter, /* multiSelection */ true); + sailingServiceWrite, stringMessages, errorReporter, /* multiSelection */ true); racesTable.setSelectedLeaderboardName(leaderboardName); racesTable.getDataProvider().getList().addAll(races); racesTable.getSelectionModel().addSelectionChangeHandler(new Handler() { @@ -62,7 +62,7 @@ public class CopyCourseAndCompetitorsDialog extends DataEntryDialog racesToCopyTo = racesTable .getSelectionModel().getSelectedSet(); return new CourseAndCompetitorCopyOperation(racesToCopyTo, courseCheckBox.getValue(), competitorCheckBox.getValue(), - priorityBox.getValue(), sailingService, errorReporter); + priorityBox.getValue(), sailingServiceWrite, errorReporter); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CourseAndCompetitorCopyOperation.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CourseAndCompetitorCopyOperation.java index 4ae06cfd35e..a98d150c6de 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CourseAndCompetitorCopyOperation.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CourseAndCompetitorCopyOperation.java @@ -4,7 +4,7 @@ import java.util.Set; import com.google.gwt.user.client.rpc.AsyncCallback; import com.sap.sailing.gwt.ui.adminconsole.AbstractLeaderboardConfigPanel.RaceColumnDTOAndFleetDTOWithNameBasedEquality; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Triple; import com.sap.sse.gwt.client.ErrorReporter; @@ -16,15 +16,15 @@ public class CourseAndCompetitorCopyOperation { final boolean copyCompetitors; final Integer priority; final private ErrorReporter errorReporter; - final private SailingServiceAsync sailingService; + final private SailingServiceWriteAsync sailingServiceWrite; public CourseAndCompetitorCopyOperation( Set racesToCopyTo, - boolean copyCourse, boolean copyCompetitors, Integer priority, SailingServiceAsync sailingService, ErrorReporter errorReporter) { + boolean copyCourse, boolean copyCompetitors, Integer priority, SailingServiceWriteAsync sailingServiceWrite, ErrorReporter errorReporter) { this.raceLogsToCopyTo = racesToCopyTo; this.copyCourse = copyCourse; this.copyCompetitors = copyCompetitors; - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.errorReporter = errorReporter; this.priority = priority; } @@ -65,7 +65,7 @@ public class CourseAndCompetitorCopyOperation { Set> toRacelogs = convertToRacelogs(leaderboardName); if (copyCourse) { - sailingService.copyCourseToOtherRaceLogs(fromTriple, toRacelogs, getPriority(), new AsyncCallback() { + sailingServiceWrite.copyCourseToOtherRaceLogs(fromTriple, toRacelogs, getPriority(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Could not copy course and competitors: " + caught.getMessage()); @@ -81,7 +81,7 @@ public class CourseAndCompetitorCopyOperation { } if (copyCompetitors) { - sailingService.copyCompetitorsToOtherRaceLogs(fromTriple, toRacelogs, new AsyncCallback() { + sailingServiceWrite.copyCompetitorsToOtherRaceLogs(fromTriple, toRacelogs, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Could not copy course and competitors: " + caught.getMessage()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CourseManagementWidget.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CourseManagementWidget.java index 088a8077ba4..c22facba2f1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CourseManagementWidget.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CourseManagementWidget.java @@ -29,7 +29,7 @@ import com.sap.sailing.domain.common.dto.RaceDTO; import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLegTypes; import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveLegImpl; import com.sap.sailing.gwt.ui.adminconsole.WaypointCreationDialog.DefaultPassingInstructionProvider; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.ControlPointDTO; import com.sap.sailing.gwt.ui.shared.GateDTO; @@ -57,7 +57,7 @@ public abstract class CourseManagementWidget implements IsWidget { protected final ControlPointTableWrapper> multiMarkControlPoints; protected final WaypointTableWrapper> waypoints; protected final Grid mainPanel; - protected final SailingServiceAsync sailingService; + protected final SailingServiceWriteAsync sailingServiceWrite; protected final ErrorReporter errorReporter; protected final StringMessages stringMessages; protected final HorizontalPanel waypointsBtnsPanel; @@ -134,9 +134,9 @@ public abstract class CourseManagementWidget implements IsWidget { * ORC PCS leg data. By default, these actions are enabled, particularly to cover the case where this * widget is used without an existing {@code TrackedRace} and only with a race log. */ - public CourseManagementWidget(final SailingServiceAsync sailingService, ErrorReporter errorReporter, + public CourseManagementWidget(final SailingServiceWriteAsync sailingServiceWrite, ErrorReporter errorReporter, final StringMessages stringMessages, final UserService userService, final Supplier showOrcPcsLegEditActions) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.errorReporter = errorReporter; this.stringMessages = stringMessages; this.userService = userService; @@ -145,11 +145,11 @@ public abstract class CourseManagementWidget implements IsWidget { mainPanel.setCellPadding(5); mainPanel.getRowFormatter().setVerticalAlign(0, HasVerticalAlignment.ALIGN_TOP); waypoints = new WaypointTableWrapper>( - /* multiSelection */ false, sailingService, stringMessages, errorReporter); + /* multiSelection */ false, sailingServiceWrite, stringMessages, errorReporter); multiMarkControlPoints = new ControlPointTableWrapper>( - /* multiSelection */ false, sailingService, stringMessages, errorReporter); + /* multiSelection */ false, sailingServiceWrite, stringMessages, errorReporter); marks = new MarkTableWrapper>( - /* multiSelection */ true, sailingService, stringMessages, errorReporter); + /* multiSelection */ true, sailingServiceWrite, stringMessages, errorReporter); marks.getSelectionModel().addSelectionChangeHandler(new SelectionChangeEvent.Handler() { @Override public void onSelectionChange(SelectionChangeEvent event) { @@ -359,7 +359,7 @@ public abstract class CourseManagementWidget implements IsWidget { } private void addMultiMarkControlPoint() { - new GateCreationDialog(sailingService, errorReporter, stringMessages, tableRes, + new GateCreationDialog(sailingServiceWrite, errorReporter, stringMessages, tableRes, marks.getDataProvider().getList(), new DataEntryDialog.DialogCallback() { @Override public void cancel() {} @@ -376,7 +376,7 @@ public abstract class CourseManagementWidget implements IsWidget { allControlPoints.addAll(multiMarkControlPoints.getDataProvider().getList()); allControlPoints.addAll(marks.getDataProvider().getList()); final int insertIndex = getInsertIndex(waypoints, beforeSelection); - new WaypointCreationDialog(sailingService, errorReporter, stringMessages, tableRes, allControlPoints, + new WaypointCreationDialog(sailingServiceWrite, errorReporter, stringMessages, tableRes, allControlPoints, new DefaultPassingInstructionProvider() { @Override public PassingInstruction getDefaultPassingInstruction(int numberOfMarksInControlPoint, String controlPointIdAsString) { @@ -418,7 +418,7 @@ public abstract class CourseManagementWidget implements IsWidget { public abstract void refresh(); protected void updateWaypointsAndControlPoints(RaceCourseDTO raceCourseDTO, String leaderboardName) { - this.sailingService.getLeaderboardWithSecurity(leaderboardName, + this.sailingServiceWrite.getLeaderboardWithSecurity(leaderboardName, new AsyncCallback() { @Override public void onFailure(Throwable caught) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CreateRegattaCallback.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CreateRegattaCallback.java index cc9cddaa879..7202ff0de89 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CreateRegattaCallback.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/CreateRegattaCallback.java @@ -14,7 +14,7 @@ import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO; import com.sap.sailing.domain.common.dto.SeriesCreationParametersDTO; import com.sap.sailing.gwt.ui.client.EventsRefresher; import com.sap.sailing.gwt.ui.client.RegattaRefresher; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; @@ -31,17 +31,17 @@ import com.sap.sse.security.ui.client.UserService; public class CreateRegattaCallback implements DialogCallback{ - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final ErrorReporter errorReporter; private final EventsRefresher eventsRefresher; private final RegattaRefresher regattaRefresher; private final StringMessages stringMessages; private final List existingEvents; - public CreateRegattaCallback(UserService userService, SailingServiceAsync sailingService, + public CreateRegattaCallback(UserService userService, SailingServiceWriteAsync sailingServiceWrite, StringMessages stringMessages, ErrorReporter errorReporter, RegattaRefresher regattaRefresher, EventsRefresher eventsRefresher, List existingEvents) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.errorReporter = errorReporter; this.regattaRefresher = regattaRefresher; this.eventsRefresher = eventsRefresher; @@ -67,7 +67,7 @@ public class CreateRegattaCallback implements DialogCallback{ seriesDTO.hasSplitFleetContiguousScoring(), seriesDTO.getMaximumNumberOfDiscards()); seriesStructure.put(seriesDTO.getName(), seriesPair); } - sailingService.createRegatta(newRegatta.getName(), + sailingServiceWrite.createRegatta(newRegatta.getName(), newRegatta.boatClass == null ? null : newRegatta.boatClass.getName(), newRegatta.canBoatsOfCompetitorsChangePerRace, newRegatta.competitorRegistrationType, newRegatta.registrationLinkSecret, newRegatta.startDate, newRegatta.endDate, @@ -105,7 +105,7 @@ public class CreateRegattaCallback implements DialogCallback{ // at the end, using -1 as "insertIndex." raceColumnNamesToAddWithInsertIndex.add(new Pair<>(newRaceColumn.getName(), -1)); } - sailingService.addRaceColumnsToSeries(newRegatta.getRegattaIdentifier(), series.getName(), raceColumnNamesToAddWithInsertIndex, + sailingServiceWrite.addRaceColumnsToSeries(newRegatta.getRegattaIdentifier(), series.getName(), raceColumnNamesToAddWithInsertIndex, new AsyncCallback>() { @Override public void onFailure(Throwable caught) { @@ -135,11 +135,11 @@ public class CreateRegattaCallback implements DialogCallback{ } private void openCreateDefaultRegattaLeaderboardDialog(final RegattaDTO newRegatta, final List existingEvents) { - CreateDefaultRegattaLeaderboardDialog dialog = new CreateDefaultRegattaLeaderboardDialog(sailingService, + CreateDefaultRegattaLeaderboardDialog dialog = new CreateDefaultRegattaLeaderboardDialog(sailingServiceWrite, stringMessages, errorReporter, newRegatta, new DialogCallback() { @Override public void ok(RegattaName regattaIdentifier) { - sailingService.createRegattaLeaderboard(regattaIdentifier, + sailingServiceWrite.createRegattaLeaderboard(regattaIdentifier, /* displayName */ null, new int[] {}, new AsyncCallback() { @Override @@ -179,7 +179,7 @@ public class CreateRegattaCallback implements DialogCallback{ * @param eventToLinkRegattaTo an event that has at least one {@link EventDTO#getLeaderboardGroups() leaderboard group} */ private void openRegattaLeaderboardToLeaderboardGroupOfEventLinkingDialog(final StrippedLeaderboardDTO newRegattaLeaderboard, EventDTO eventToLinkRegattaTo) { - LinkRegattaLeaderboardToLeaderboardGroupOfEventDialog dialog = new LinkRegattaLeaderboardToLeaderboardGroupOfEventDialog(sailingService, stringMessages, errorReporter, newRegattaLeaderboard, eventToLinkRegattaTo, + LinkRegattaLeaderboardToLeaderboardGroupOfEventDialog dialog = new LinkRegattaLeaderboardToLeaderboardGroupOfEventDialog(sailingServiceWrite, stringMessages, errorReporter, newRegattaLeaderboard, eventToLinkRegattaTo, new DialogCallback() { @Override public void ok(final LeaderboardGroupDTO selectedLeaderboardGroup) { @@ -188,9 +188,9 @@ public class CreateRegattaCallback implements DialogCallback{ leaderboardNames.add(leaderboard.getName()); } leaderboardNames.add(newRegattaLeaderboard.getName()); - sailingService.updateLeaderboardGroup(selectedLeaderboardGroup.getId(), + sailingServiceWrite.updateLeaderboardGroup(selectedLeaderboardGroup.getId(), selectedLeaderboardGroup.getName(), selectedLeaderboardGroup.getName(), - selectedLeaderboardGroup.description, selectedLeaderboardGroup.getDisplayName(), + selectedLeaderboardGroup.getDescription(), selectedLeaderboardGroup.getDisplayName(), leaderboardNames, selectedLeaderboardGroup.getOverallLeaderboardDiscardThresholds(), selectedLeaderboardGroup.getOverallLeaderboardScoringSchemeType(), new MarkedAsyncCallback(new AsyncCallback() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceConfigurationListComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceConfigurationListComposite.java index 2a60a4430d0..d443c5d5380 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceConfigurationListComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceConfigurationListComposite.java @@ -18,7 +18,7 @@ import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.view.client.ListDataProvider; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.DeviceConfigurationWithSecurityDTO; import com.sap.sse.common.Util; @@ -50,13 +50,13 @@ public class DeviceConfigurationListComposite extends Composite { private final Label noConfigurationsLabel; - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final ErrorReporter errorReporter; protected final StringMessages stringMessages; - public DeviceConfigurationListComposite(SailingServiceAsync sailingService, ErrorReporter errorReporter, + public DeviceConfigurationListComposite(SailingServiceWriteAsync sailingServiceWrite, ErrorReporter errorReporter, StringMessages stringMessages, final UserService userService) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.errorReporter = errorReporter; this.stringMessages = stringMessages; mainPanel = new SimplePanel(); @@ -88,7 +88,7 @@ public class DeviceConfigurationListComposite extends Composite { } public void refreshTable() { - sailingService.getDeviceConfigurations(new AsyncCallback>() { + sailingServiceWrite.getDeviceConfigurations(new AsyncCallback>() { @Override public void onSuccess(List result) { if (configurationsDataProvider.getList().isEmpty()) { @@ -141,7 +141,7 @@ public class DeviceConfigurationListComposite extends Composite { new DefaultActionsImagesBarCell(stringMessages), userService); actionColumn.addAction(ACTION_DELETE, DELETE, config -> { if (Window.confirm(stringMessages.doYouReallyWantToRemoveDeviceConfiguration(config.getName()))) { - sailingService.removeDeviceConfiguration(config.id, new AsyncCallback() { + sailingServiceWrite.removeDeviceConfiguration(config.id, new AsyncCallback() { @Override public void onSuccess(Boolean result) { refreshTable(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceConfigurationPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceConfigurationPanel.java index 8bb5a9b2ef1..3b9598e342f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceConfigurationPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceConfigurationPanel.java @@ -18,6 +18,7 @@ import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SelectionChangeEvent.Handler; import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.DeviceConfigurationDTO; import com.sap.sailing.gwt.ui.shared.DeviceConfigurationWithSecurityDTO; @@ -29,7 +30,7 @@ import com.sap.sse.security.ui.client.UserService; import com.sap.sse.security.ui.client.component.SelectedElementsCountingButton; public class DeviceConfigurationPanel extends SimplePanel implements DeviceConfigurationDetailComposite.DeviceConfigurationFactory { - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final UserService userService; private final StringMessages stringMessages; private final ErrorReporter errorReporter; @@ -42,13 +43,13 @@ public class DeviceConfigurationPanel extends SimplePanel implements DeviceConfi private final RefreshableMultiSelectionModel refreshableMultiSelectionModel; - public DeviceConfigurationPanel(SailingServiceAsync sailingService, UserService userService, + public DeviceConfigurationPanel(SailingServiceWriteAsync sailingServiceWrite, UserService userService, StringMessages stringMessages, ErrorReporter reporter) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.userService = userService; this.stringMessages = stringMessages; this.errorReporter = reporter; - listComposite = new DeviceConfigurationListComposite(sailingService, errorReporter, stringMessages, + listComposite = new DeviceConfigurationListComposite(sailingServiceWrite, errorReporter, stringMessages, userService); refreshableMultiSelectionModel = listComposite.getSelectionModel(); setupUi(); @@ -113,7 +114,7 @@ public class DeviceConfigurationPanel extends SimplePanel implements DeviceConfi grid.setWidget(0, 0, listComposite); grid.getRowFormatter().setVerticalAlign(0, HasVerticalAlignment.ALIGN_TOP); grid.getColumnFormatter().getElement(1).getStyle().setPaddingTop(2.0, Unit.EM); - detailComposite = new DeviceConfigurationDetailComposite(sailingService, getUserService(), errorReporter, stringMessages, this); + detailComposite = new DeviceConfigurationDetailComposite(sailingServiceWrite, getUserService(), errorReporter, stringMessages, this); detailComposite.setVisible(false); grid.setWidget(0, 1, detailComposite); } @@ -135,7 +136,7 @@ public class DeviceConfigurationPanel extends SimplePanel implements DeviceConfi @Override public void obtainAndSetNameForConfigurationAndAdd( final DeviceConfigurationWithSecurityDTO configurationToObtainAndSetNameForAndAdd) { - sailingService.getDeviceConfigurations( + sailingServiceWrite.getDeviceConfigurations( new MarkedAsyncCallback<>(new AsyncCallback>() { @Override public void onSuccess(List allConfigurations) { @@ -143,7 +144,7 @@ public class DeviceConfigurationPanel extends SimplePanel implements DeviceConfi @Override public void ok(String nameForNewDeviceConfiguration) { configurationToObtainAndSetNameForAndAdd.name = nameForNewDeviceConfiguration; - sailingService.createOrUpdateDeviceConfiguration(configurationToObtainAndSetNameForAndAdd, + sailingServiceWrite.createOrUpdateDeviceConfiguration(configurationToObtainAndSetNameForAndAdd, new MarkedAsyncCallback<>(new AsyncCallback() { @Override public void onSuccess(Void result) { @@ -178,7 +179,7 @@ public class DeviceConfigurationPanel extends SimplePanel implements DeviceConfi private void removeConfiguration() { detailComposite.setConfiguration(null); for (DeviceConfigurationDTO config : refreshableMultiSelectionModel.getSelectedSet()) { - sailingService.removeDeviceConfiguration(config.id, new AsyncCallback() { + sailingServiceWrite.removeDeviceConfiguration(config.id, new AsyncCallback() { @Override public void onSuccess(Boolean result) { listComposite.refreshTable(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceIdentifierTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceIdentifierTableWrapper.java index 03ce7c9dabc..1d0f871376e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceIdentifierTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceIdentifierTableWrapper.java @@ -1,7 +1,7 @@ package com.sap.sailing.gwt.ui.adminconsole; import com.google.gwt.user.cellview.client.TextColumn; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.DeviceIdentifierDTO; import com.sap.sse.gwt.client.ErrorReporter; @@ -10,9 +10,9 @@ import com.sap.sse.gwt.client.celltable.RefreshableMultiSelectionModel; public class DeviceIdentifierTableWrapper extends TableWrapper> { - public DeviceIdentifierTableWrapper(SailingServiceAsync sailingService, StringMessages stringMessages, + public DeviceIdentifierTableWrapper(SailingServiceWriteAsync sailingServiceWrite, StringMessages stringMessages, ErrorReporter errorReporter) { - super(sailingService, stringMessages, errorReporter, /* multiSelection */ true, /* enablePager */ false, + super(sailingServiceWrite, stringMessages, errorReporter, /* multiSelection */ true, /* enablePager */ false, new EntityIdentityComparator() { @Override public boolean representSameEntity(DeviceIdentifierDTO dto1, DeviceIdentifierDTO dto2) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceMappingTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceMappingTableWrapper.java index 1acbad82626..c60fe9088c6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceMappingTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/DeviceMappingTableWrapper.java @@ -7,7 +7,7 @@ import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; import com.google.gwt.user.cellview.client.TextColumn; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.ui.client.MappableToDeviceFormatter; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO; @@ -16,9 +16,9 @@ import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.celltable.RefreshableSingleSelectionModel; public class DeviceMappingTableWrapper extends TableWrapper> { - public DeviceMappingTableWrapper(SailingServiceAsync sailingService, final StringMessages stringMessages, + public DeviceMappingTableWrapper(SailingServiceWriteAsync sailingServiceWrite, final StringMessages stringMessages, ErrorReporter errorReporter) { - super(sailingService, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true, + super(sailingServiceWrite, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true, /* leaving EntityIdentityComparator null, reducing comparison to equals/hashCode which is well * defined on DeviceMappingDTO */ null); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EditCompetitorsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EditCompetitorsDialog.java old mode 100644 new mode 100755 index 5a67cf0be7c..d42ec8f7b0f --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EditCompetitorsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EditCompetitorsDialog.java @@ -4,18 +4,20 @@ import java.util.List; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTO; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.dialog.DataEntryDialog; import com.sap.sse.security.ui.client.UserService; public class EditCompetitorsDialog extends DataEntryDialog> { - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final UserService userService; private final StringMessages stringMessages; private final ErrorReporter errorReporter; private final String leaderboardName; + private final String boatClassName; + private final boolean createWithBoatByDefault; protected static class CompetitorsValidator implements Validator> { public CompetitorsValidator() { @@ -28,14 +30,18 @@ public class EditCompetitorsDialog extends DataEntryDialog> callback) { - super(stringMessages.actionEditCompetitors(), null, stringMessages.ok(), stringMessages.cancel(), new CompetitorsValidator(), callback); - this.sailingService = sailingService; + public EditCompetitorsDialog(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, + final String leaderboardName, final String boatClassName, boolean createWithBoatByDefault, + final StringMessages stringMessages, final ErrorReporter errorReporter, DialogCallback> callback) { + super(stringMessages.actionEditCompetitors(), null, stringMessages.ok(), stringMessages.cancel(), + new CompetitorsValidator(), callback); + this.sailingServiceWrite = sailingServiceWrite; this.userService = userService; this.stringMessages = stringMessages; this.errorReporter = errorReporter; this.leaderboardName = leaderboardName; + this.boatClassName = boatClassName; + this.createWithBoatByDefault = createWithBoatByDefault; } @Override @@ -45,7 +51,8 @@ public class EditCompetitorsDialog extends DataEntryDialog existingEvents, List availableLeaderboardGroups, - SailingServiceAsync sailingService, StringMessages stringMessages, DialogCallback callback) { - super(new EventParameterValidator(stringMessages, existingEvents), sailingService, stringMessages, + SailingServiceWriteAsync sailingServiceWrite, StringMessages stringMessages, DialogCallback callback) { + super(new EventParameterValidator(stringMessages, existingEvents), sailingServiceWrite, stringMessages, availableLeaderboardGroups, /* leaderboardGroups */ Collections.emptyList(), callback); nameEntryField = createTextBox(null); nameEntryField.setVisibleLength(50); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java index 09e4a469c50..c2cebf01d63 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventDialog.java @@ -25,7 +25,7 @@ import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.dto.CourseAreaDTO; import com.sap.sailing.domain.common.windfinder.AvailableWindFinderSpotCollections; import com.sap.sailing.gwt.ui.client.DataEntryDialogWithDateTimeBox; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; import com.sap.sailing.gwt.ui.shared.EventDTO; @@ -128,11 +128,11 @@ public abstract class EventDialog extends DataEntryDialogWithDateTimeBox availableLeaderboardGroups, Iterable leaderboardGroupsOfEvent, DialogCallback callback) { super(stringMessages.event(), null, stringMessages.ok(), stringMessages.cancel(), validator, callback); - this.storageServiceAvailable = new FileStorageServiceConnectionTestObservable(sailingService); + this.storageServiceAvailable = new FileStorageServiceConnectionTestObservable(sailingServiceWrite); this.stringMessages = stringMessages; this.availableLeaderboardGroupsByName = new HashMap<>(); for (final LeaderboardGroupDTO lgDTO : availableLeaderboardGroups) { @@ -163,7 +163,7 @@ public abstract class EventDialog extends DataEntryDialogWithDateTimeBox suggestedWindFinderSpotCollections = AvailableWindFinderSpotCollections diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventEditDialog.java index 593f8412492..9461dfcd82d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventEditDialog.java @@ -4,7 +4,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; @@ -12,8 +12,8 @@ import com.sap.sse.gwt.client.controls.datetime.DateTimeInput.Accuracy; public class EventEditDialog extends EventDialog { public EventEditDialog(EventDTO event, Collection otherExistingEvents, List availableLeaderboardGroups, - SailingServiceAsync sailingService, StringMessages stringMessages, DialogCallback callback) { - super(new EventParameterValidator(stringMessages, otherExistingEvents), sailingService, stringMessages, availableLeaderboardGroups, event.getLeaderboardGroups(), callback); + SailingServiceWriteAsync sailingServiceWrite, StringMessages stringMessages, DialogCallback callback) { + super(new EventParameterValidator(stringMessages, otherExistingEvents), sailingServiceWrite, stringMessages, availableLeaderboardGroups, event.getLeaderboardGroups(), callback); nameEntryField = createTextBox(event.getName()); nameEntryField.setVisibleLength(50); descriptionEntryField = createTextArea(event.getDescription()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventListComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventListComposite.java index 5606464bb3c..f88e6cb0f62 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventListComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventListComposite.java @@ -46,7 +46,7 @@ import com.sap.sailing.gwt.ui.client.EntryPointLinkFactory; import com.sap.sailing.gwt.ui.client.EventsRefresher; import com.sap.sailing.gwt.ui.client.LeaderboardGroupsDisplayer; import com.sap.sailing.gwt.ui.client.RegattaRefresher; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.controls.MultipleLinkCell; import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; @@ -85,7 +85,7 @@ import com.sap.sse.security.ui.client.component.editacl.EditACLDialog; * @author Frank Mittag (C5163974) */ public class EventListComposite extends Composite implements EventsRefresher, LeaderboardGroupsDisplayer { - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final UserService userService; private final ErrorReporter errorReporter; private final StringMessages stringMessages; @@ -117,10 +117,10 @@ public class EventListComposite extends Composite implements EventsRefresher, Le private final EventsRefresher eventsRefresher; private final HandleTabSelectable handleTabSelectable; - public EventListComposite(final SailingServiceAsync sailingService, UserService userService, final ErrorReporter errorReporter, + public EventListComposite(final SailingServiceWriteAsync sailingServiceWrite, UserService userService, final ErrorReporter errorReporter, RegattaRefresher regattaRefresher, EventsRefresher eventsRefresher, final HandleTabSelectable handleTabSelectable, final StringMessages stringMessages) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.userService = userService; this.stringMessages = stringMessages; this.errorReporter = errorReporter; @@ -160,7 +160,6 @@ public class EventListComposite extends Composite implements EventsRefresher, Le final RefreshableMultiSelectionModel selectionModel = (RefreshableMultiSelectionModel) eventTable.getSelectionModel(); refreshableEventSelectionModel = selectionModel; eventTable.setVisible(false); - final Button refresh = buttonPanel.addUnsecuredAction(stringMessages.refresh(), this::fillEvents); refresh.ensureDebugId("RefreshEventsButton"); final Button create = buttonPanel.addCreateAction(stringMessages.actionAddEvent(), this::openCreateEventDialog); @@ -168,7 +167,6 @@ public class EventListComposite extends Composite implements EventsRefresher, Le final Button remove = buttonPanel.addRemoveAction(stringMessages.remove(), refreshableEventSelectionModel, true, () -> removeEvents(refreshableEventSelectionModel.getSelectedSet())); remove.ensureDebugId("RemoveEventsButton"); - this.refreshableEventSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() { @Override public void onSelectionChange(SelectionChangeEvent event) { @@ -198,7 +196,6 @@ public class EventListComposite extends Composite implements EventsRefresher, Le FlushableCellTable table = new FlushableCellTable(/* pageSize */10000, tableRes); eventListDataProvider.addDataDisplay(table); table.setWidth("100%"); - SelectionCheckboxColumn eventSelectionCheckboxColumn = new SelectionCheckboxColumn( tableRes.cellTableStyle().cellTableCheckboxSelected(), tableRes.cellTableStyle().cellTableCheckboxDeselected(), @@ -212,11 +209,9 @@ public class EventListComposite extends Composite implements EventsRefresher, Le return t.id.hashCode(); } },filterTextbox.getAllListDataProvider(),table); - AnchorCell anchorCell = new AnchorCell(); final TextColumn eventUUidColumn = new AbstractSortableTextColumn( event -> event.getId() == null ? "" : event.getId().toString()); - Column eventNameColumn = new Column(anchorCell) { @Override public SafeHtml getValue(EventDTO event) { @@ -227,28 +222,24 @@ public class EventListComposite extends Composite implements EventsRefresher, Le return ANCHORTEMPLATE.cell(UriUtils.fromString(link), event.getName()); } }; - TextColumn venueNameColumn = new TextColumn() { @Override public String getValue(EventDTO event) { return event.venue != null ? event.venue.getName() : ""; } }; - TextColumn startEndDateColumn = new TextColumn() { @Override public String getValue(EventDTO event) { return DateAndTimeFormatterUtil.formatDateRange(event.startDate, event.endDate); } }; - TextColumn isPublicColumn = new TextColumn() { @Override public String getValue(EventDTO event) { return event.isPublic ? stringMessages.yes() : stringMessages.no(); } }; - SafeHtmlCell courseAreasCell = new SafeHtmlCell(); Column courseAreasColumn = new Column(courseAreasCell) { @Override @@ -270,7 +261,6 @@ public class EventListComposite extends Composite implements EventsRefresher, Le return builder.toSafeHtml(); } }; - MultipleLinkCell leaderboardGroupsCell = new MultipleLinkCell(true); Column> leaderboardGroupsColumn = new Column>( leaderboardGroupsCell) { @@ -283,7 +273,6 @@ public class EventListComposite extends Composite implements EventsRefresher, Le return links; } }; - leaderboardGroupsCell.setOnLinkClickHandler(new ValueUpdater() { @Override public void update(String value) { @@ -293,7 +282,6 @@ public class EventListComposite extends Composite implements EventsRefresher, Le params); } }); - TextColumn imagesColumn = new TextColumn() { @Override public String getValue(EventDTO event) { @@ -305,7 +293,6 @@ public class EventListComposite extends Composite implements EventsRefresher, Le return result; } }; - TextColumn videosColumn = new TextColumn() { @Override public String getValue(EventDTO event) { @@ -317,10 +304,8 @@ public class EventListComposite extends Composite implements EventsRefresher, Le return result; } }; - final SecuredDTOOwnerColumn groupColumn = SecuredDTOOwnerColumn.getGroupOwnerColumn(); final SecuredDTOOwnerColumn userColumn = SecuredDTOOwnerColumn.getUserOwnerColumn(); - final AccessControlledActionsColumn actionsColumn = create( new EventConfigImagesBarCell(stringMessages), userService); actionsColumn.addAction(EventConfigImagesBarCell.ACTION_UPDATE, UPDATE, this::openEditEventDialog); @@ -339,7 +324,6 @@ public class EventListComposite extends Composite implements EventsRefresher, Le config.openOwnershipDialog(t); } }); - final EditACLDialog.DialogConfig configACL = EditACLDialog.create( userService.getUserManagementService(), EVENT, event -> fillEvents(), stringMessages); actionsColumn.addAction(EventConfigImagesBarCell.ACTION_CHANGE_ACL, DefaultActions.CHANGE_ACL, @@ -350,10 +334,9 @@ public class EventListComposite extends Composite implements EventsRefresher, Le configACL.openACLDialog(e); } }); - final MigrateGroupOwnershipDialog.DialogConfig migrateDialogConfig = MigrateGroupOwnershipDialog .create(userService.getUserManagementService(), (event, dto) -> { - sailingService.updateGroupOwnerForEventHierarchy(event.id, dto, new AsyncCallback() { + sailingServiceWrite.updateGroupOwnerForEventHierarchy(event.id, dto, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(stringMessages.errorUpdatingOwnership(event.getName())); @@ -373,7 +356,6 @@ public class EventListComposite extends Composite implements EventsRefresher, Le migrateDialogConfig.openDialog(t); } }); - eventNameColumn.setSortable(true); venueNameColumn.setSortable(true); isPublicColumn.setSortable(true); @@ -382,11 +364,9 @@ public class EventListComposite extends Composite implements EventsRefresher, Le leaderboardGroupsColumn.setSortable(true); groupColumn.setSortable(true); userColumn.setSortable(true); - final ListHandler columnSortHandler = getEventTableColumnSortHandler(eventListDataProvider.getList(), eventSelectionCheckboxColumn, eventNameColumn, venueNameColumn, startEndDateColumn, isPublicColumn, courseAreasColumn, leaderboardGroupsColumn, groupColumn, userColumn); - table.addColumn(eventSelectionCheckboxColumn, eventSelectionCheckboxColumn.getHeader()); table.addColumn(eventNameColumn, stringMessages.event()); table.addColumn(venueNameColumn, stringMessages.venue()); @@ -401,10 +381,8 @@ public class EventListComposite extends Composite implements EventsRefresher, Le table.addColumn(eventUUidColumn, stringMessages.id()); table.addColumn(actionsColumn, stringMessages.actions()); table.setSelectionModel(eventSelectionCheckboxColumn.getSelectionModel(), eventSelectionCheckboxColumn.getSelectionManager()); - table.addColumnSortHandler(columnSortHandler); table.getColumnSortList().push(startEndDateColumn); - return table; } @@ -473,7 +451,7 @@ public class EventListComposite extends Composite implements EventsRefresher, Le for (EventDTO event : events) { eventIds.add(event.id); } - sailingService.removeEvents(eventIds, new AsyncCallback() { + sailingServiceWrite.removeEvents(eventIds, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Error trying to remove the events:" + caught.getMessage()); @@ -487,7 +465,7 @@ public class EventListComposite extends Composite implements EventsRefresher, Le } private void removeEvent(final EventDTO event) { - sailingService.removeEvent(event.id, new AsyncCallback() { + sailingServiceWrite.removeEvent(event.id, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Error trying to remove event " + event.getName() + ": " + caught.getMessage()); @@ -505,7 +483,7 @@ public class EventListComposite extends Composite implements EventsRefresher, Le final List existingLeaderboardGroups = new ArrayList(); Util.addAll(availableLeaderboardGroups, existingLeaderboardGroups); EventCreateDialog dialog = new EventCreateDialog(Collections.unmodifiableCollection(existingEvents), existingLeaderboardGroups, - sailingService, stringMessages, new DialogCallback() { + sailingServiceWrite, stringMessages, new DialogCallback() { @Override public void cancel() { } @@ -520,17 +498,17 @@ public class EventListComposite extends Composite implements EventsRefresher, Le } private void openCreateDefaultRegattaDialog(final EventDTO createdEvent) { - CreateDefaultRegattaDialog dialog = new CreateDefaultRegattaDialog(sailingService, stringMessages, errorReporter, new DialogCallback() { + CreateDefaultRegattaDialog dialog = new CreateDefaultRegattaDialog(sailingServiceWrite, stringMessages, errorReporter, new DialogCallback() { @Override public void cancel() { } @Override public void ok(Void editedObject) { - sailingService.getRegattas(new AsyncCallback>() { + sailingServiceWrite.getRegattas(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { - sailingService.getEvents(new AsyncCallback>() { + sailingServiceWrite.getEvents(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { openCreateRegattaDialog(Collections.emptyList(), Collections.emptyList(), createdEvent); @@ -546,7 +524,7 @@ public class EventListComposite extends Composite implements EventsRefresher, Le @Override public void onSuccess(final List existingRegattas) { - sailingService.getEvents(new AsyncCallback>() { + sailingServiceWrite.getEvents(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { openCreateRegattaDialog(existingRegattas, Collections.emptyList(), createdEvent); @@ -567,8 +545,8 @@ public class EventListComposite extends Composite implements EventsRefresher, Le private void openCreateRegattaDialog(List existingRegattas, List existingEvents, EventDTO createdEvent) { - RegattaWithSeriesAndFleetsCreateDialog dialog = new RegattaWithSeriesAndFleetsCreateDialog(existingRegattas, existingEvents, createdEvent, sailingService, stringMessages, - new CreateRegattaCallback(userService, sailingService, stringMessages, errorReporter, regattaRefresher, + RegattaWithSeriesAndFleetsCreateDialog dialog = new RegattaWithSeriesAndFleetsCreateDialog(existingRegattas, existingEvents, createdEvent, sailingServiceWrite, stringMessages, + new CreateRegattaCallback(userService, sailingServiceWrite, stringMessages, errorReporter, regattaRefresher, eventsRefresher, existingEvents)); dialog.ensureDebugId("RegattaCreateDialog"); dialog.show(); @@ -581,7 +559,7 @@ public class EventListComposite extends Composite implements EventsRefresher, Le LeaderboardGroupCreateDialog leaderboardGroupCreateDialog = new LeaderboardGroupCreateDialog(existingLeaderboardGroups, stringMessages, new DialogCallback() { @Override public void ok(final LeaderboardGroupDescriptor newGroup) { - sailingService.createLeaderboardGroup(newGroup.getName(), newGroup.getDescription(), + sailingServiceWrite.createLeaderboardGroup(newGroup.getName(), newGroup.getDescription(), newGroup.getDisplayName(), newGroup.isDisplayLeaderboardsInReverseOrder(), newGroup.getOverallLeaderboardDiscardThresholds(), newGroup.getOverallLeaderboardScoringSchemeType(), new MarkedAsyncCallback( new AsyncCallback() { @@ -627,7 +605,7 @@ public class EventListComposite extends Composite implements EventsRefresher, Le List existingLeaderboardGroups = new ArrayList(); Util.addAll(availableLeaderboardGroups, existingLeaderboardGroups); EventEditDialog dialog = new EventEditDialog(selectedEvent, Collections.unmodifiableCollection(existingEvents), - existingLeaderboardGroups, sailingService, stringMessages, + existingLeaderboardGroups, sailingServiceWrite, stringMessages, new DialogCallback() { @Override public void cancel() { @@ -645,8 +623,8 @@ public class EventListComposite extends Composite implements EventsRefresher, Le Pair, List> courseAreasToAddAndRemove = getCourseAreasToAdd(oldEvent, updatedEvent); final List courseAreasToAdd = courseAreasToAddAndRemove.getA(); final List courseAreasToRemove = courseAreasToAddAndRemove.getB(); - final Iterable updatedEventLeaderboardGroupIds = updatedEvent.getLeaderboardGroupIds(); - sailingService.updateEvent(oldEvent.id, oldEvent.getName(), updatedEvent.getDescription(), + final List updatedEventLeaderboardGroupIds = updatedEvent.getLeaderboardGroupIds(); + sailingServiceWrite.updateEvent(oldEvent.id, oldEvent.getName(), updatedEvent.getDescription(), updatedEvent.startDate, updatedEvent.endDate, updatedEvent.venue, updatedEvent.isPublic, updatedEventLeaderboardGroupIds, updatedEvent.getOfficialWebsiteURL(), @@ -666,7 +644,7 @@ public class EventListComposite extends Composite implements EventsRefresher, Le for (CourseAreaDTO courseAreaToAdd : courseAreasToAdd) { namesOfCourseAreasToAdd[i++] = courseAreaToAdd.getName(); } - sailingService.createCourseAreas(oldEvent.id, namesOfCourseAreasToAdd, new AsyncCallback() { + sailingServiceWrite.createCourseAreas(oldEvent.id, namesOfCourseAreasToAdd, new AsyncCallback() { @Override public void onFailure(Throwable t) { errorReporter.reportError("Error trying to add course area to sailing event " + oldEvent.getName() @@ -680,7 +658,7 @@ public class EventListComposite extends Composite implements EventsRefresher, Le for (CourseAreaDTO courseAreaToRemove : courseAreasToRemove) { idsOfCourseAreasToRemove[j++] = courseAreaToRemove.id; } - sailingService.removeCourseAreas(oldEvent.id, idsOfCourseAreasToRemove, new AsyncCallback() { + sailingServiceWrite.removeCourseAreas(oldEvent.id, idsOfCourseAreasToRemove, new AsyncCallback() { @Override public void onFailure(Throwable t) { errorReporter.reportError("Error trying to remove course area from sailing event " + oldEvent.getName() @@ -691,7 +669,7 @@ public class EventListComposite extends Composite implements EventsRefresher, Le public void onSuccess(Void result) { fillEvents(); if (!oldEvent.getName().equals(updatedEvent.getName())) { - sailingService.renameEvent(oldEvent.id, updatedEvent.getName(), new AsyncCallback() { + sailingServiceWrite.renameEvent(oldEvent.id, updatedEvent.getName(), new AsyncCallback() { @Override public void onSuccess(Void result) { } @@ -723,7 +701,7 @@ public class EventListComposite extends Composite implements EventsRefresher, Le for (CourseAreaDTO courseAreaDTO : newEvent.venue.getCourseAreas()) { courseAreaNames.add(courseAreaDTO.getName()); } - sailingService.createEvent(newEvent.getName(), newEvent.getDescription(), newEvent.startDate, newEvent.endDate, + sailingServiceWrite.createEvent(newEvent.getName(), newEvent.getDescription(), newEvent.startDate, newEvent.endDate, newEvent.venue.getName(), newEvent.isPublic, courseAreaNames, newEvent.getOfficialWebsiteURL(), newEvent.getBaseURL(), newEvent.getSailorsInfoWebsiteURLs(), newEvent.getImages(), newEvent.getVideos(), newEvent.getLeaderboardGroupIds(), new AsyncCallback() { @@ -738,7 +716,7 @@ public class EventListComposite extends Composite implements EventsRefresher, Le if (newEvent.getLeaderboardGroups().isEmpty()) { // show simple Dialog DataEntryDialog dialog = new CreateDefaultLeaderboardGroupDialog( - sailingService, stringMessages, errorReporter, new DialogCallback() { + sailingServiceWrite, stringMessages, errorReporter, new DialogCallback() { @Override public void ok(Void editedObject) { openLeaderboardGroupCreationDialog(existingLeaderboardGroups, newEvent); @@ -764,7 +742,7 @@ public class EventListComposite extends Composite implements EventsRefresher, Le @Override public void fillEvents() { - sailingService.getEvents(new AsyncCallback>() { + sailingServiceWrite.getEvents(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Remote Procedure Call getEvents() - Failure: " + caught.getMessage()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventManagementPanel.java index 611b90c8035..2de1552e918 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/EventManagementPanel.java @@ -11,7 +11,7 @@ import com.google.gwt.view.client.SelectionChangeEvent.Handler; import com.sap.sailing.gwt.ui.client.EventsRefresher; import com.sap.sailing.gwt.ui.client.LeaderboardGroupsDisplayer; import com.sap.sailing.gwt.ui.client.RegattaRefresher; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; @@ -32,26 +32,22 @@ public class EventManagementPanel extends SimplePanel implements EventsRefresher private final CaptionPanel eventsPanel; private final RefreshableMultiSelectionModel refreshableEventSelectionModel; - public EventManagementPanel(final SailingServiceAsync sailingService, UserService userService, final ErrorReporter errorReporter, + public EventManagementPanel(final SailingServiceWriteAsync sailingServiceWrite, UserService userService, final ErrorReporter errorReporter, RegattaRefresher regattaRefresher, final StringMessages stringMessages, final HandleTabSelectable handleTabSelectable) { VerticalPanel mainPanel = new VerticalPanel(); setWidget(mainPanel); mainPanel.setWidth("100%"); - eventsPanel = new CaptionPanel(stringMessages.events()); mainPanel.add(eventsPanel); VerticalPanel eventsContentPanel = new VerticalPanel(); eventsPanel.setContentWidget(eventsContentPanel); - - eventListComposite = new EventListComposite(sailingService, userService, errorReporter, regattaRefresher, this, handleTabSelectable, stringMessages); + eventListComposite = new EventListComposite(sailingServiceWrite, userService, errorReporter, regattaRefresher, this, handleTabSelectable, stringMessages); eventListComposite.ensureDebugId("EventListComposite"); eventsContentPanel.add(eventListComposite); - - eventDetailsComposite = new EventDetailsComposite(sailingService, errorReporter, stringMessages); + eventDetailsComposite = new EventDetailsComposite(sailingServiceWrite, errorReporter, stringMessages); eventDetailsComposite.ensureDebugId("EventDetailsComposite"); eventDetailsComposite.setVisible(false); mainPanel.add(eventDetailsComposite); - refreshableEventSelectionModel = eventListComposite.getRefreshableMultiSelectionModel(); refreshableEventSelectionModel.addSelectionChangeHandler(new Handler() { @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java index cbc140aaf46..b5bab27b2db 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneAfterImportHandler.java @@ -10,7 +10,7 @@ import java.util.UUID; import com.google.gwt.user.client.rpc.AsyncCallback; import com.sap.sailing.domain.common.RegattaNameAndRaceName; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO; import com.sap.sailing.gwt.ui.shared.EventDTO; @@ -41,7 +41,7 @@ import com.sap.sse.security.ui.client.UserService; */ public class ExpeditionAllInOneAfterImportHandler { - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final UserService userService; private final ErrorReporter errorReporter; private final StringMessages stringMessages; @@ -60,11 +60,11 @@ public class ExpeditionAllInOneAfterImportHandler { public ExpeditionAllInOneAfterImportHandler(UUID eventId, String regattaName, String leaderboardName, String leaderboardGroupName, List> raceEntries, List gpsDeviceIds, List sensorDeviceIds, String sensorImporterType, - Iterable startTimes, final SailingServiceAsync sailingService, final UserService userService, final ErrorReporter errorReporter, + Iterable startTimes, final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final ErrorReporter errorReporter, final StringMessages stringMessages) { this.leaderboardGroupName = leaderboardGroupName; this.sensorImporterType = sensorImporterType; - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.userService = userService; this.errorReporter = errorReporter; this.stringMessages = stringMessages; @@ -72,25 +72,25 @@ public class ExpeditionAllInOneAfterImportHandler { this.regattaName = regattaName; this.startTimes = startTimes; // TODO from the start times, suggest the user to split the session into one session per start, with start tracking at n minutes before start - sailingService.getEventById(eventId, false, new DataLoadingCallback() { + sailingServiceWrite.getEventById(eventId, false, new DataLoadingCallback() { @Override public void onSuccess(EventDTO result) { event = result; - sailingService.getRegattaByName(regattaName, new DataLoadingCallback() { + sailingServiceWrite.getRegattaByName(regattaName, new DataLoadingCallback() { @Override public void onSuccess(RegattaDTO result) { regatta = result; - sailingService.getLeaderboard(leaderboardName, + sailingServiceWrite.getLeaderboard(leaderboardName, new DataLoadingCallback() { @Override public void onSuccess(StrippedLeaderboardDTO result) { leaderboard = result; - sailingService.getTrackFileImportDeviceIds(gpsDeviceIds, + sailingServiceWrite.getTrackFileImportDeviceIds(gpsDeviceIds, new DataLoadingCallback>() { @Override public void onSuccess(List result) { gpsFixesDeviceIDs = result; - sailingService.getTrackFileImportDeviceIds(sensorDeviceIds, + sailingServiceWrite.getTrackFileImportDeviceIds(sensorDeviceIds, new DataLoadingCallback>() { @Override public void onSuccess(List result) { @@ -109,19 +109,19 @@ public class ExpeditionAllInOneAfterImportHandler { } private class RegattaLogCompetitorRegistrationAndSelectionDialog extends RegattaLogCompetitorRegistrationDialog { - public RegattaLogCompetitorRegistrationAndSelectionDialog(String boatClass, SailingServiceAsync sailingService, final UserService userService, + public RegattaLogCompetitorRegistrationAndSelectionDialog(String boatClass, SailingServiceWriteAsync sailingServiceWrite, final UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, boolean editable, String leaderboardName, boolean canBoatsOfCompetitorsChangePerRace) { - this(boatClass, sailingService, userService, stringMessages, errorReporter, editable, leaderboardName, + this(boatClass, sailingServiceWrite, userService, stringMessages, errorReporter, editable, leaderboardName, canBoatsOfCompetitorsChangePerRace, new ValidatorForCompetitorRegistrationDialog(stringMessages), new CallbackForCompetitorRegistrationDialog()); } - public RegattaLogCompetitorRegistrationAndSelectionDialog(String boatClass, SailingServiceAsync sailingService, final UserService userService, + public RegattaLogCompetitorRegistrationAndSelectionDialog(String boatClass, SailingServiceWriteAsync sailingServiceWrite, final UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, boolean editable, String leaderboardName, boolean canBoatsOfCompetitorsChangePerRace, ValidatorForCompetitorRegistrationDialog validator, CallbackForCompetitorRegistrationDialog callback) { - super(boatClass, sailingService, userService, stringMessages, errorReporter, editable, leaderboardName, + super(boatClass, sailingServiceWrite, userService, stringMessages, errorReporter, editable, leaderboardName, canBoatsOfCompetitorsChangePerRace, validator, callback); validator.setCompetitorRegistrationsPanel(competitorRegistrationsPanel); callback.setCompetitorRegistrationsPanel(competitorRegistrationsPanel); @@ -154,7 +154,7 @@ public class ExpeditionAllInOneAfterImportHandler { if (competitors.isEmpty()) { Notification.notify(stringMessages.importCanceledNoCompetitorAdded(), NotificationType.ERROR); } else { - sailingService.setCompetitorRegistrationsInRegattaLog(leaderboard.getName(), + sailingServiceWrite.setCompetitorRegistrationsInRegattaLog(leaderboard.getName(), competitors, new AsyncCallback() { @Override public void onSuccess(Void result) { @@ -176,7 +176,7 @@ public class ExpeditionAllInOneAfterImportHandler { private void showCompetitorRegistration() { new RegattaLogCompetitorRegistrationAndSelectionDialog(regatta.boatClass == null ? null : regatta.boatClass.getName(), - sailingService, userService, stringMessages, errorReporter, true, leaderboard.getName(), + sailingServiceWrite, userService, stringMessages, errorReporter, true, leaderboard.getName(), leaderboard.canBoatsOfCompetitorsChangePerRace).show(); } @@ -187,7 +187,7 @@ public class ExpeditionAllInOneAfterImportHandler { final CompetitorDTO competitor = mappedCompetitors.iterator().next(); saveCompetitorGPSMapping(mappedCompetitors, Collections.singleton(new DeviceMappingDTO(deviceIdentifierDTO, deviceIdentifierDTO.from, deviceIdentifierDTO.to, competitor, null))); } else { - new RegattaLogFixesAddMappingsDialog(sailingService, userService, errorReporter, stringMessages, + new RegattaLogFixesAddMappingsDialog(sailingServiceWrite, userService, errorReporter, stringMessages, leaderboard.getName(), gpsFixesDeviceIDs, new CancelImportDialogCallback>() { @@ -212,7 +212,7 @@ public class ExpeditionAllInOneAfterImportHandler { final CompetitorDTO competitor = mappedCompetitors.iterator().next(); saveCompetitorSensorFixMapping(Collections.singleton(new TypedDeviceMappingDTO(deviceIdentifierDTO, deviceIdentifierDTO.from, deviceIdentifierDTO.to, competitor, null, sensorImporterType))); } else if (sensorFixesDeviceIDs.size() > 0) { - new RegattaLogSensorDataAddMappingsDialog(sailingService, userService, errorReporter, stringMessages, leaderboard.getName(), + new RegattaLogSensorDataAddMappingsDialog(sailingServiceWrite, userService, errorReporter, stringMessages, leaderboard.getName(), sensorFixesDeviceIDs, sensorImporterType, new CancelImportDialogCallback>() { @@ -246,7 +246,7 @@ public class ExpeditionAllInOneAfterImportHandler { raceNames.add(new Pair(raceName, raceColumnName)); } - sailingService.removeAndUntrackRaces(racesToStopAndStartTrackingFor, new AsyncCallback() { + sailingServiceWrite.removeAndUntrackRaces(racesToStopAndStartTrackingFor, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Failed to track race after import!"); @@ -254,7 +254,7 @@ public class ExpeditionAllInOneAfterImportHandler { @Override public void onSuccess(Void result) { - sailingService.startRaceLogTracking(leaderboardRaceColumnFleetNames, /* trackWind */ false, + sailingServiceWrite.startRaceLogTracking(leaderboardRaceColumnFleetNames, /* trackWind */ false, /* correctWindByDeclination */ true, new AsyncCallback() { @Override public void onSuccess(Void result) { @@ -280,7 +280,7 @@ public class ExpeditionAllInOneAfterImportHandler { this.callback = callback; for (TypedDeviceMappingDTO mapping : mappings) { callCount++; - sailingService.addTypedDeviceMappingToRegattaLog(leaderboardName, mapping, new AsyncCallback() { + sailingServiceWrite.addTypedDeviceMappingToRegattaLog(leaderboardName, mapping, new AsyncCallback() { @Override public void onSuccess(Void result) { callCount--; @@ -308,7 +308,7 @@ public class ExpeditionAllInOneAfterImportHandler { this.callback = callback; for (DeviceMappingDTO mapping : mappings) { callCount++; - sailingService.addDeviceMappingToRegattaLog(leaderboardName, mapping, new AsyncCallback() { + sailingServiceWrite.addDeviceMappingToRegattaLog(leaderboardName, mapping, new AsyncCallback() { @Override public void onSuccess(Void result) { callCount--; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java index 0961d10d01b..601e1ecb446 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionAllInOneImportPanel.java @@ -31,7 +31,7 @@ import com.sap.sailing.gwt.ui.adminconsole.resulthandling.ExpeditionDataImportRe import com.sap.sailing.gwt.ui.adminconsole.resulthandling.ExpeditionDataImportResultsDialog; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.RegattasDisplayer; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sse.gwt.client.ErrorReporter; @@ -49,7 +49,7 @@ public class ExpeditionAllInOneImportPanel extends Composite implements Regattas private final RegattaSuggestOracle regattaOracle; - public ExpeditionAllInOneImportPanel(final StringMessages stringMessages, final SailingServiceAsync sailingService, final UserService userService, + public ExpeditionAllInOneImportPanel(final StringMessages stringMessages, final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final ErrorReporter errorReporter, final RegattaRefresher regattaRefresher) { final FormPanel formPanel = new FormPanel(); final BusyIndicator busyIndicator = new SimpleBusyIndicator(); @@ -160,7 +160,7 @@ public class ExpeditionAllInOneImportPanel extends Composite implements Regattas new ExpeditionAllInOneAfterImportHandler(response.getEventId(), response.getRegattaName(), response.getLeaderboardName(), response.getLeaderboardGroupName(), response.getRaceEntries(), response.getGpsDeviceIds(), response.getSensorDeviceIds(), response.getSensorFixImporterType(), - response.getStartTimes(), sailingService, userService, + response.getStartTimes(), sailingServiceWrite, userService, errorReporter, stringMessages); regattaRefresher.fillRegattas(); } else { @@ -172,7 +172,7 @@ public class ExpeditionAllInOneImportPanel extends Composite implements Regattas public void onSelection(SelectionEvent event) { final String selected = event.getSelectedItem().getReplacementString(); if (selected != null) { - sailingService.getRegattaByName(selected, new AsyncCallback() { + sailingServiceWrite.getRegattaByName(selected, new AsyncCallback() { @Override public void onSuccess(RegattaDTO result) { validation.run(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionDeviceConfigurationsPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionDeviceConfigurationsPanel.java index 2b54159f9d8..70b80bc9204 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionDeviceConfigurationsPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ExpeditionDeviceConfigurationsPanel.java @@ -1,6 +1,12 @@ package com.sap.sailing.gwt.ui.adminconsole; -import java.util.Arrays; +import static com.sap.sse.security.shared.HasPermissions.DefaultActions.CHANGE_OWNERSHIP; +import static com.sap.sse.security.shared.HasPermissions.DefaultActions.DELETE; +import static com.sap.sse.security.shared.HasPermissions.DefaultActions.UPDATE; +import static com.sap.sse.security.ui.client.component.AccessControlledActionsColumn.create; +import static com.sap.sse.security.ui.client.component.DefaultActionsImagesBarCell.ACTION_DELETE; +import static com.sap.sse.security.ui.client.component.DefaultActionsImagesBarCell.ACTION_UPDATE; + import java.util.Collections; import java.util.Comparator; import java.util.HashSet; @@ -8,11 +14,9 @@ import java.util.List; import java.util.Set; import java.util.UUID; -import com.google.gwt.cell.client.FieldUpdater; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.text.shared.SafeHtmlRenderer; import com.google.gwt.user.cellview.client.AbstractCellTable; import com.google.gwt.user.cellview.client.CellTable; import com.google.gwt.user.cellview.client.Column; @@ -30,57 +34,45 @@ import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.view.client.ListDataProvider; +import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.expeditionconnector.ExpeditionDeviceConfiguration; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.util.NaturalComparator; import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources; import com.sap.sse.gwt.client.ErrorReporter; -import com.sap.sse.gwt.client.IconResources; import com.sap.sse.gwt.client.celltable.BaseCelltable; import com.sap.sse.gwt.client.celltable.EntityIdentityComparator; -import com.sap.sse.gwt.client.celltable.ImagesBarCell; -import com.sap.sse.gwt.client.celltable.ImagesBarColumn; import com.sap.sse.gwt.client.celltable.RefreshableSingleSelectionModel; import com.sap.sse.gwt.client.dialog.DataEntryDialog; import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel; +import com.sap.sse.security.shared.HasPermissions; +import com.sap.sse.security.shared.HasPermissions.DefaultActions; +import com.sap.sse.security.shared.dto.OwnershipDTO; +import com.sap.sse.security.ui.client.UserService; +import com.sap.sse.security.ui.client.component.AccessControlledActionsColumn; +import com.sap.sse.security.ui.client.component.DefaultActionsImagesBarCell; +import com.sap.sse.security.ui.client.component.EditOwnershipDialog; +import com.sap.sse.security.ui.client.component.SecuredDTOOwnerColumn; +import com.sap.sse.security.ui.client.component.EditOwnershipDialog.DialogConfig; +import com.sap.sse.security.ui.client.component.editacl.EditACLDialog; public class ExpeditionDeviceConfigurationsPanel extends FlowPanel { private final StringMessages stringMessages; - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final ErrorReporter errorReporter; private final CellTable allDeviceConfigurations; private final LabeledAbstractFilterablePanel filterDeviceConfigurationsPanel; private final RefreshableSingleSelectionModel refreshableDeviceConfigurationsSelectionModel; + private final UserService userService; - public static class DeviceConfigurationImagesBarCell extends ImagesBarCell { - public static final String ACTION_REMOVE = "ACTION_REMOVE"; - public static final String ACTION_EDIT = "ACTION_EDIT"; - private final StringMessages stringMessages; - - public DeviceConfigurationImagesBarCell(StringMessages stringMessages) { - super(); - this.stringMessages = stringMessages; - } - - public DeviceConfigurationImagesBarCell(SafeHtmlRenderer renderer, StringMessages stringConstants) { - super(); - this.stringMessages = stringConstants; - } - - @Override - protected Iterable getImageSpecs() { - return Arrays.asList( - new ImageSpec(ACTION_EDIT, stringMessages.actionEdit(), makeImagePrototype(IconResources.INSTANCE.editIcon())), - new ImageSpec(ACTION_REMOVE, stringMessages.actionRemove(), makeImagePrototype(IconResources.INSTANCE.removeIcon()))); - } - } - - public ExpeditionDeviceConfigurationsPanel(final SailingServiceAsync sailingService, final ErrorReporter errorReporter, final StringMessages stringMessages) { - this.sailingService = sailingService; + public ExpeditionDeviceConfigurationsPanel(final SailingServiceWriteAsync sailingServiceWrite, + final ErrorReporter errorReporter, final StringMessages stringMessages, final UserService userService) { + this.sailingServiceWrite = sailingServiceWrite; this.errorReporter = errorReporter; this.stringMessages = stringMessages; - + this.userService = userService; AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class); allDeviceConfigurations = new BaseCelltable<>(/* pageSize */10000, tableRes); final ListDataProvider filteredDeviceConfigurations = new ListDataProvider<>(); @@ -148,29 +140,38 @@ public class ExpeditionDeviceConfigurationsPanel extends FlowPanel { deviceConfigurationColumnListHandler.setComparator(deviceConfigurationBoatIdColumn, Comparator.comparing(ExpeditionDeviceConfiguration::getExpeditionBoatId, Comparator.nullsLast(Comparator.naturalOrder()))); allDeviceConfigurations.addColumn(deviceConfigurationBoatIdColumn, stringMessages.expeditionBoatId()); - ImagesBarColumn deviceConfigurationActionColumn = new ImagesBarColumn( - new DeviceConfigurationImagesBarCell(stringMessages)); - deviceConfigurationActionColumn.setFieldUpdater(new FieldUpdater() { - @Override - public void update(int index, ExpeditionDeviceConfiguration deviceConfiguration, String value) { - if (DeviceConfigurationImagesBarCell.ACTION_REMOVE.equals(value)) { - if (Window.confirm(stringMessages.doYouReallyWantToRemoveExpeditionDeviceConfiguration(deviceConfiguration.getName()))) { - removeDeviceConfiguration(deviceConfiguration, filterDeviceConfigurationsPanel); - } - } else if (DeviceConfigurationImagesBarCell.ACTION_EDIT.equals(value)) { - new EditDeviceConfigurationDialog(filterDeviceConfigurationsPanel, sailingService, stringMessages, errorReporter, deviceConfiguration).show(); - } + final AccessControlledActionsColumn actionsColumn = create( + new DefaultActionsImagesBarCell(stringMessages), userService); + actionsColumn.addAction(ACTION_DELETE, DELETE, deviceConfiguration -> { + if (Window.confirm(stringMessages + .doYouReallyWantToRemoveExpeditionDeviceConfiguration(deviceConfiguration.getName()))) { + removeDeviceConfiguration(deviceConfiguration, filterDeviceConfigurationsPanel); } }); - allDeviceConfigurations.addColumn(deviceConfigurationActionColumn, stringMessages.actions()); + actionsColumn.addAction(ACTION_UPDATE, UPDATE, deviceConfiguration -> { + new EditDeviceConfigurationDialog(filterDeviceConfigurationsPanel, sailingServiceWrite, stringMessages, + errorReporter, deviceConfiguration).show(); + }); + final HasPermissions type = SecuredDomainType.EXPEDITION_DEVICE_CONFIGURATION; + final DialogConfig config = EditOwnershipDialog + .create(userService.getUserManagementService(), type, deviceConfiguration -> refresh(), stringMessages); + actionsColumn.addAction(DefaultActionsImagesBarCell.ACTION_CHANGE_OWNERSHIP, CHANGE_OWNERSHIP, + deviceConfiguration -> config.openOwnershipDialog(deviceConfiguration)); + final EditACLDialog.DialogConfig configACL = EditACLDialog + .create(userService.getUserManagementService(), type, deviceConfiguration -> refresh(), stringMessages); + actionsColumn.addAction(DefaultActionsImagesBarCell.ACTION_CHANGE_ACL, DefaultActions.CHANGE_ACL, + deviceConfiguration -> configACL.openACLDialog(deviceConfiguration)); + SecuredDTOOwnerColumn.configureOwnerColumns(allDeviceConfigurations, deviceConfigurationColumnListHandler, + stringMessages); + allDeviceConfigurations.addColumn(actionsColumn, stringMessages.actions()); allDeviceConfigurations.addColumnSortHandler(deviceConfigurationColumnListHandler); - updateAllAccounts(sailingService, filterDeviceConfigurationsPanel, stringMessages, errorReporter); + updateAllAccounts(sailingServiceWrite, filterDeviceConfigurationsPanel, stringMessages, errorReporter); Button addAccountButton = new Button(stringMessages.add()); addAccountButton.ensureDebugId("addExpeditionDeviceConfiguration"); addAccountButton.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - addAccount(); + addDeviceConfiguration(); } }); add(addAccountButton); @@ -185,7 +186,7 @@ public class ExpeditionDeviceConfigurationsPanel extends FlowPanel { } public void refresh() { - updateAllAccounts(sailingService, filterDeviceConfigurationsPanel, stringMessages, errorReporter); + updateAllAccounts(sailingServiceWrite, filterDeviceConfigurationsPanel, stringMessages, errorReporter); } private abstract class AbstractDeviceConfigurationDialog extends DataEntryDialog { @@ -231,13 +232,18 @@ public class ExpeditionDeviceConfigurationsPanel extends FlowPanel { } private class AddDeviceConfigurationDialog extends AbstractDeviceConfigurationDialog { - public AddDeviceConfigurationDialog(final LabeledAbstractFilterablePanel filterAccountsPanel, - final SailingServiceAsync sailingService, final StringMessages stringMessages, final ErrorReporter errorReporter) { - super(filterAccountsPanel, sailingService, stringMessages, errorReporter, stringMessages.addExpeditionDeviceConfiguration(), + private final UserService userService; + + public AddDeviceConfigurationDialog( + final LabeledAbstractFilterablePanel filterAccountsPanel, + final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, + final StringMessages stringMessages, final ErrorReporter errorReporter) { + super(filterAccountsPanel, sailingServiceWrite, + stringMessages, errorReporter, stringMessages.addExpeditionDeviceConfiguration(), new DialogCallback() { @Override public void ok(final ExpeditionDeviceConfiguration editedObject) { - sailingService.addOrReplaceExpeditionDeviceConfiguration(editedObject, new AsyncCallback() { + sailingServiceWrite.addOrReplaceExpeditionDeviceConfiguration(editedObject, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(stringMessages.errorUpdatingExpeditionDeviceConfiguration(editedObject.getName(), @@ -255,12 +261,15 @@ public class ExpeditionDeviceConfigurationsPanel extends FlowPanel { public void cancel() { } }); + this.userService = userService; ensureDebugId("AddExpeditionDeviceConfigurationDialog"); } @Override protected ExpeditionDeviceConfiguration getResult() { - return new ExpeditionDeviceConfiguration(boatName.getText(), UUID.randomUUID(), boatId.getValue()); + final ExpeditionDeviceConfiguration result = new ExpeditionDeviceConfiguration(boatName.getText(), UUID.randomUUID(), boatId.getValue()); + result.setOwnership(new OwnershipDTO(userService.getCurrentUser().asStrippedUser(), userService.getCurrentTenant())); + return result; } } @@ -268,13 +277,13 @@ public class ExpeditionDeviceConfigurationsPanel extends FlowPanel { private final ExpeditionDeviceConfiguration valueToEdit; public EditDeviceConfigurationDialog(final LabeledAbstractFilterablePanel filterAccountsPanel, - final SailingServiceAsync sailingService, final StringMessages stringMessages, final ErrorReporter errorReporter, + final SailingServiceWriteAsync sailingServiceWrite, final StringMessages stringMessages, final ErrorReporter errorReporter, final ExpeditionDeviceConfiguration valueToEdit) { - super(filterAccountsPanel, sailingService, stringMessages, errorReporter, stringMessages.editExpeditionDeviceConfiguration(), + super(filterAccountsPanel, sailingServiceWrite, stringMessages, errorReporter, stringMessages.editExpeditionDeviceConfiguration(), new DialogCallback() { @Override public void ok(final ExpeditionDeviceConfiguration editedObject) { - sailingService.addOrReplaceExpeditionDeviceConfiguration(editedObject, new AsyncCallback() { + sailingServiceWrite.addOrReplaceExpeditionDeviceConfiguration(editedObject, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(stringMessages.errorUpdatingExpeditionDeviceConfiguration(editedObject.getName(), @@ -326,13 +335,13 @@ public class ExpeditionDeviceConfigurationsPanel extends FlowPanel { }); } - private void addAccount() { - new AddDeviceConfigurationDialog(filterDeviceConfigurationsPanel, sailingService, stringMessages, errorReporter).show(); + private void addDeviceConfiguration() { + new AddDeviceConfigurationDialog(filterDeviceConfigurationsPanel, sailingServiceWrite, userService, stringMessages, errorReporter).show(); } private void removeDeviceConfiguration(final ExpeditionDeviceConfiguration expeditionDeviceConfiguration, final LabeledAbstractFilterablePanel filterDeviceConfigurationsPanel) { - sailingService.removeExpeditionDeviceConfiguration(expeditionDeviceConfiguration, new AsyncCallback() { + sailingServiceWrite.removeExpeditionDeviceConfiguration(expeditionDeviceConfiguration, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(stringMessages.errorTryingToRemoveExpeditionDeviceConfiguration(expeditionDeviceConfiguration.getName(), caught.getMessage())); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FileStorageServiceConnectionTestObservable.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FileStorageServiceConnectionTestObservable.java index 4442d44e924..52ed902cec6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FileStorageServiceConnectionTestObservable.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FileStorageServiceConnectionTestObservable.java @@ -5,7 +5,7 @@ import java.util.List; import com.google.gwt.i18n.client.LocaleInfo; import com.google.gwt.user.client.rpc.AsyncCallback; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sse.gwt.client.filestorage.FileStorageManagementGwtServiceAsync; import com.sap.sse.gwt.shared.filestorage.FileStorageServicePropertyErrorsDTO; @@ -22,9 +22,9 @@ public class FileStorageServiceConnectionTestObservable { private List observer = new ArrayList<>(); private boolean value; - public FileStorageServiceConnectionTestObservable(SailingServiceAsync sailingService) { + public FileStorageServiceConnectionTestObservable(SailingServiceWriteAsync sailingServiceWrite) { value = false; - sailingService.testFileStorageServiceProperties(null, LocaleInfo.getCurrentLocale().getLocaleName(), + sailingServiceWrite.testFileStorageServiceProperties(null, LocaleInfo.getCurrentLocale().getLocaleName(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardCreateDialog.java index c254bdf162b..4931d6fd035 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardCreateDialog.java @@ -13,9 +13,7 @@ public class FlexibleLeaderboardCreateDialog extends FlexibleLeaderboardDialog { Collection existingEvents, ErrorReporter errorReporter, DialogCallback callback) { super(stringMessages.createFlexibleLeaderboard(), new LeaderboardDescriptor(), stringMessages, existingEvents, errorReporter, new FlexibleLeaderboardDialog.LeaderboardParameterValidator(stringMessages, existingLeaderboards), callback); - nameTextBox = createTextBox(null); - nameTextBox.ensureDebugId("NameTextBox"); - nameTextBox.setVisibleLength(50); + nameTextBox.setEnabled(true); // a name can be selected during FlexibleLeaderboard creation displayNameTextBox = createTextBox(null); displayNameTextBox.ensureDebugId("DisplayNameTextBox"); displayNameTextBox.setVisibleLength(50); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardEditDialog.java index 643f20dfab5..0d9c3b2e1f9 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/FlexibleLeaderboardEditDialog.java @@ -18,10 +18,8 @@ public class FlexibleLeaderboardEditDialog extends FlexibleLeaderboardDialog { DialogCallback callback) { super(stringMessages.editFlexibleLeaderboard(), leaderboard, stringMessages, existingEvents, errorReporter, new FlexibleLeaderboardDialog.LeaderboardParameterValidator( stringMessages, otherExistingLeaderboards), callback); - nameTextBox = createTextBox(leaderboard.getName()); displayNameTextBox = createTextBox(leaderboard.getDisplayName()); scoringSchemeListBox = createListBox(false); - nameTextBox.setVisibleLength(50); displayNameTextBox.setVisibleLength(50); int j = 0; for (ScoringSchemeType scoringSchemeType: ScoringSchemeType.values()) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/GateCreationDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/GateCreationDialog.java index e95d3cae2d6..1502536e6df 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/GateCreationDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/GateCreationDialog.java @@ -12,7 +12,7 @@ import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SelectionChangeEvent.Handler; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.GateDTO; import com.sap.sailing.gwt.ui.shared.MarkDTO; @@ -27,7 +27,7 @@ public class GateCreationDialog extends DataEntryDialog { private final TextBox shortName; private final StringMessages stringMessages; - public GateCreationDialog(SailingServiceAsync sailingService, ErrorReporter errorReporter, + public GateCreationDialog(SailingServiceWriteAsync sailingServiceWrite, ErrorReporter errorReporter, final StringMessages stringMessages, AdminConsoleTableResources tableRes, List marks, DialogCallback callback) { super(stringMessages.gate(), stringMessages.gate(), @@ -46,7 +46,7 @@ public class GateCreationDialog extends DataEntryDialog { name = createTextBox(""); shortName = createTextBox(""); marksWrapper = new MarkTableWrapper>( - /* multiSelection */ true, sailingService, stringMessages, errorReporter); + /* multiSelection */ true, sailingServiceWrite, stringMessages, errorReporter); marksWrapper.getDataProvider().getList().addAll(marks); marksWrapper.getSelectionModel().addSelectionChangeHandler(new Handler() { @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/IgtimiAccountsPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/IgtimiAccountsPanel.java index 3391017118e..1a662a1e402 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/IgtimiAccountsPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/IgtimiAccountsPanel.java @@ -36,7 +36,7 @@ import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.view.client.ListDataProvider; import com.sap.sailing.domain.common.security.SecuredDomainType; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.AccountWithSecurityDTO; import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources; @@ -67,7 +67,7 @@ import com.sap.sse.security.ui.client.component.editacl.EditACLDialog; public class IgtimiAccountsPanel extends FlowPanel { private final StringMessages stringMessages; - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final ErrorReporter errorReporter; private final LabeledAbstractFilterablePanel filterAccountsPanel; @@ -92,9 +92,9 @@ public class IgtimiAccountsPanel extends FlowPanel { } } - public IgtimiAccountsPanel(final SailingServiceAsync sailingService, final ErrorReporter errorReporter, + public IgtimiAccountsPanel(final SailingServiceWriteAsync sailingServiceWrite, final ErrorReporter errorReporter, final StringMessages stringMessages, final UserService userService) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.errorReporter = errorReporter; this.stringMessages = stringMessages; @@ -159,7 +159,7 @@ public class IgtimiAccountsPanel extends FlowPanel { : Window.Location.getProtocol(); final String hostname = Window.Location.getHostName(); final String port = Window.Location.getPort(); - this.sailingService.getIgtimiAuthorizationUrl(protocol, hostname, port, new AsyncCallback() { + this.sailingServiceWrite.getIgtimiAuthorizationUrl(protocol, hostname, port, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError( @@ -255,7 +255,7 @@ public class IgtimiAccountsPanel extends FlowPanel { } public void refresh() { - sailingService.getAllIgtimiAccountsWithSecurity(new AsyncCallback>() { + sailingServiceWrite.getAllIgtimiAccountsWithSecurity(new AsyncCallback>() { @Override public void onSuccess(Iterable result) { filterAccountsPanel.updateAll(result); @@ -291,7 +291,7 @@ public class IgtimiAccountsPanel extends FlowPanel { private TextBox eMail; private PasswordTextBox password; - public AddAccountDialog(final Runnable refresher, final SailingServiceAsync sailingService, + public AddAccountDialog(final Runnable refresher, final SailingServiceWriteAsync sailingServiceWrite, final StringMessages stringMessages, final ErrorReporter errorReporter) { super(stringMessages.addIgtimiUser(), stringMessages.addIgtimiUser(), stringMessages.ok(), stringMessages.cancel(), new Validator() { @@ -308,7 +308,7 @@ public class IgtimiAccountsPanel extends FlowPanel { }, /* animationEnabled */ true, new DialogCallback() { @Override public void ok(final UserData editedObject) { - sailingService.authorizeAccessToIgtimiUser(editedObject.geteMail(), + sailingServiceWrite.authorizeAccessToIgtimiUser(editedObject.geteMail(), editedObject.getPassword(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -365,12 +365,12 @@ public class IgtimiAccountsPanel extends FlowPanel { } private void addAccount() { - new AddAccountDialog(this::refresh, sailingService, stringMessages, errorReporter).show(); + new AddAccountDialog(this::refresh, sailingServiceWrite, stringMessages, errorReporter).show(); } private void removeAccount(final AccountWithSecurityDTO account, final ListDataProvider removeFrom) { - sailingService.removeIgtimiAccount(account.getEmail(), new AsyncCallback() { + sailingServiceWrite.removeIgtimiAccount(account.getEmail(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(stringMessages.errorTryingToRemoveIgtimiAccount(account.getEmail())); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImagesListComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImagesListComposite.java index 424eb0d589d..b6621909a19 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImagesListComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImagesListComposite.java @@ -29,7 +29,7 @@ import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.view.client.ListDataProvider; import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SingleSelectionModel; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; import com.sap.sse.common.media.MediaTagConstants; @@ -50,7 +50,7 @@ import com.sap.sse.gwt.client.media.ImageResizingTaskDTO; */ public class ImagesListComposite extends Composite { private final StringMessages stringMessages; - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private CellTable imageTable; private SingleSelectionModel imageSelectionModel; @@ -77,9 +77,9 @@ public class ImagesListComposite extends Composite { private final AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class); - public ImagesListComposite(final SailingServiceAsync sailingService, final StringMessages stringMessages, + public ImagesListComposite(final SailingServiceWriteAsync sailingServiceWrite, final StringMessages stringMessages, final FileStorageServiceConnectionTestObservable storageServiceAvailable) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.stringMessages = stringMessages; this.storageServiceAvailable = storageServiceAvailable; mainPanel = new SimplePanel(); @@ -274,7 +274,7 @@ public class ImagesListComposite extends Composite { } private void openCreateImageDialog(String initialTag) { - ImageCreateDialog dialog = new ImageCreateDialog(initialTag, sailingService, stringMessages, + ImageCreateDialog dialog = new ImageCreateDialog(initialTag, sailingServiceWrite, stringMessages, storageServiceAvailable, new DialogCallback() { @Override public void cancel() { @@ -294,7 +294,7 @@ public class ImagesListComposite extends Composite { } private void openEditImageDialog(final ImageDTO selectedImage) { - ImageEditDialog dialog = new ImageEditDialog(selectedImage, sailingService, stringMessages, + ImageEditDialog dialog = new ImageEditDialog(selectedImage, sailingServiceWrite, stringMessages, storageServiceAvailable, new DialogCallback() { @Override public void cancel() { @@ -327,7 +327,7 @@ public class ImagesListComposite extends Composite { * returned ImageDTOs */ protected void callResizingServiceAndUpdateTable(ImageResizingTaskDTO resizingTask, ImageDTO originalImage) { - sailingService.resizeImage(resizingTask, new AsyncCallback>() { + sailingServiceWrite.resizeImage(resizingTask, new AsyncCallback>() { @Override public void onFailure(Throwable caught) { Notification.notify(stringMessages.resizeUnsuccessful(caught.getMessage()), NotificationType.ERROR); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImpliedWindSourceEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImpliedWindSourceEditDialog.java index b435fde3b53..f96759ccc46 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImpliedWindSourceEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImpliedWindSourceEditDialog.java @@ -20,7 +20,7 @@ import com.sap.sailing.domain.common.orc.impl.FixedSpeedImpliedWindSourceImpl; import com.sap.sailing.domain.common.orc.impl.OtherRaceAsImpliedWindSourceImpl; import com.sap.sailing.domain.common.orc.impl.OwnMaxImpliedWindImpl; import com.sap.sailing.gwt.ui.adminconsole.AbstractLeaderboardConfigPanel.RaceColumnDTOAndFleetDTOWithNameBasedEquality; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTOWithSecurity; import com.sap.sse.common.Util.Triple; @@ -44,7 +44,7 @@ public class ImpliedWindSourceEditDialog extends DataEntryDialog availableLeaderboards, final StringMessages stringMessages, - ErrorReporter errorReporter, SailingServiceAsync sailingService, UserService userService, + ErrorReporter errorReporter, SailingServiceWriteAsync sailingServiceWrite, UserService userService, DialogCallback callback) { super(stringMessages.impliedWindSource(), stringMessages.provideImpliedWindSourceForRace( @@ -87,7 +87,7 @@ public class ImpliedWindSourceEditDialog extends DataEntryDialogvalidateAndUpdate()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImportCompetitorCallback.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImportCompetitorCallback.java index 8aec0bb13f7..6d1dffa0ed1 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImportCompetitorCallback.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ImportCompetitorCallback.java @@ -12,6 +12,7 @@ import com.sap.sailing.domain.common.CompetitorDescriptor; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTO; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; @@ -32,13 +33,13 @@ import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; * */ public class ImportCompetitorCallback implements DialogCallback, String>> { - protected final SailingServiceAsync sailingService; + protected final SailingServiceWriteAsync sailingServiceWrite; protected final ErrorReporter errorReporter; protected final StringMessages stringMessages; - public ImportCompetitorCallback(SailingServiceAsync sailingService, ErrorReporter errorReporter, + public ImportCompetitorCallback(SailingServiceWriteAsync sailingServiceWrite, ErrorReporter errorReporter, StringMessages stringMessages) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.errorReporter = errorReporter; this.stringMessages = stringMessages; } @@ -56,7 +57,7 @@ public class ImportCompetitorCallback implements DialogCallback(existingCompetitorsSelected), new MarkedAsyncCallback<>( + sailingServiceWrite.addOrUpdateCompetitors(new ArrayList<>(existingCompetitorsSelected), new MarkedAsyncCallback<>( new AsyncCallback>() { @Override public void onFailure(Throwable caught) { @@ -83,7 +84,7 @@ public class ImportCompetitorCallback implements DialogCallback competitorsForSaving, final Iterable competitorsForRegistration, String searchTag) { - sailingService.addCompetitors(competitorsForSaving, searchTag, new AsyncCallback>() { + sailingServiceWrite.addCompetitors(competitorsForSaving, searchTag, new AsyncCallback>() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(caught.getMessage()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ItemToMapToDeviceSelectionPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ItemToMapToDeviceSelectionPanel.java index fa77bb7a9ca..6be00926846 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ItemToMapToDeviceSelectionPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ItemToMapToDeviceSelectionPanel.java @@ -13,7 +13,7 @@ import com.google.gwt.view.client.SingleSelectionModel; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.MarkDTO; import com.sap.sse.gwt.client.ErrorReporter; @@ -34,14 +34,14 @@ public class ItemToMapToDeviceSelectionPanel implements IsWidget { void onSelectionChange(MarkDTO mark); } - public ItemToMapToDeviceSelectionPanel(SailingServiceAsync sailingService, final UserService userService, StringMessages stringMessages, + public ItemToMapToDeviceSelectionPanel(SailingServiceWriteAsync sailingServiceWrite, final UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, final SelectionChangedHandler handler, MappableToDevice selected) { this.selected = selected; this.errorReporter = errorReporter; - competitorTable = new CompetitorTableWrapper<>(sailingService, userService, stringMessages, errorReporter, /* multiSelection */ false, + competitorTable = new CompetitorTableWrapper<>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true, /* filterCompetitorWithBoat */ false, /* filterCompetitorsWithoutBoat */ false); - boatTable = new BoatTableWrapper<>(sailingService, userService, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true, /* allowActions */ false); - markTable = new MarkTableWrapper>(/* multiSelection */ false, sailingService, + boatTable = new BoatTableWrapper<>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true, /* allowActions */ false); + markTable = new MarkTableWrapper>(/* multiSelection */ false, sailingServiceWrite, stringMessages, errorReporter); competitorTable.getSelectionModel().addSelectionChangeHandler(new SelectionChangeEvent.Handler() { @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java old mode 100644 new mode 100755 index 6c62ee95e39..35c0ebf25ee --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java @@ -77,7 +77,7 @@ import com.sap.sailing.gwt.ui.client.LeaderboardsDisplayer; import com.sap.sailing.gwt.ui.client.LeaderboardsRefresher; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.RegattasDisplayer; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardEntryPoint; import com.sap.sailing.gwt.ui.leaderboard.ScoringSchemeTypeFormatter; @@ -136,7 +136,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel SafeHtml cell(SafeUri url, String displayName); } - public LeaderboardConfigPanel(final SailingServiceAsync sailingService, final UserService userService, + public LeaderboardConfigPanel(final SailingServiceWriteAsync sailingService, final UserService userService, RegattaRefresher regattaRefresher, final ErrorReporter errorReporter, StringMessages theStringConstants, final boolean showRaceDetails, LeaderboardsRefresher leaderboardsRefresher) { @@ -312,9 +312,10 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel }); leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_EDIT_COMPETITORS, UPDATE, leaderboardDTO -> { - EditCompetitorsDialog editCompetitorsDialog = new EditCompetitorsDialog(sailingService, userService, - leaderboardDTO.getName(), stringMessages, errorReporter, - new DialogCallback>() { + EditCompetitorsDialog editCompetitorsDialog = new EditCompetitorsDialog(sailingServiceWrite, userService, + leaderboardDTO.getName(), leaderboardDTO.boatClassName, + /* createWithBoatByDefault */ !leaderboardDTO.canBoatsOfCompetitorsChangePerRace, + stringMessages, errorReporter, new DialogCallback>() { @Override public void cancel() { } @@ -327,7 +328,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel }); leaderboardActionColumn.addAction(LeaderboardConfigImagesBarCell.ACTION_CONFIGURE_URL, READ, leaderboardDTO -> { - sailingService.getAvailableDetailTypesForLeaderboard(leaderboardDTO.getName(), null, + sailingServiceWrite.getAvailableDetailTypesForLeaderboard(leaderboardDTO.getName(), null, new AsyncCallback>() { @Override public void onFailure(Throwable caught) { @@ -420,7 +421,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel dialog.show(); break; case RegattaLeaderboardWithEliminations: - dialog = new RegattaLeaderboardWithEliminationsEditDialog(sailingService, userService, + dialog = new RegattaLeaderboardWithEliminationsEditDialog(sailingServiceWrite, userService, Collections.unmodifiableCollection(otherExistingLeaderboard), Collections.unmodifiableCollection(allRegattas), new LeaderboardDescriptorWithEliminations( @@ -435,7 +436,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel @Override public void ok(LeaderboardDescriptorWithEliminations result) { updateLeaderboard(oldLeaderboardName, result); - sailingService.setEliminatedCompetitors(oldLeaderboardName, + sailingServiceWrite.setEliminatedCompetitors(oldLeaderboardName, result.getEliminatedCompetitors(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -563,7 +564,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel protected void openUpdateFlexibleLeaderboardDialog(final StrippedLeaderboardDTO leaderboardDTO, final List otherExistingLeaderboard, final String oldLeaderboardName, final LeaderboardDescriptor descriptor) { - sailingService.getEvents(new MarkedAsyncCallback>(new AsyncCallback>() { + sailingServiceWrite.getEvents(new MarkedAsyncCallback>(new AsyncCallback>() { @Override public void onSuccess(List result) { openUpdateFlexibleLeaderboardDialog(leaderboardDTO, otherExistingLeaderboard, oldLeaderboardName, @@ -635,18 +636,18 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel final String fleetName = fleetDTO.getName(); final String raceName = LeaderboardNameConstants.DEFAULT_FLEET_NAME.equals(fleetName) ? raceColumnName : raceColumnName + ", " + fleetName; - ShowCompetitorToBoatMappingsDialog dialog = new ShowCompetitorToBoatMappingsDialog(sailingService, + ShowCompetitorToBoatMappingsDialog dialog = new ShowCompetitorToBoatMappingsDialog(sailingServiceWrite, stringMessages, errorReporter, selectedLeaderboardName, raceColumnName, fleetName, raceName, userService); dialog.center(); } private void setStartTime(RaceColumnDTO raceColumnDTO, FleetDTO fleetDTO) { - new SetStartTimeDialog(sailingService, errorReporter, getSelectedLeaderboardName(), raceColumnDTO.getName(), + new SetStartTimeDialog(sailingServiceWrite, errorReporter, getSelectedLeaderboardName(), raceColumnDTO.getName(), fleetDTO.getName(), stringMessages, new DialogCallback() { @Override public void ok(RaceLogSetStartTimeAndProcedureDTO editedObject) { - sailingService.setStartTimeAndProcedure(editedObject, new AsyncCallback() { + sailingServiceWrite.setStartTimeAndProcedure(editedObject, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(caught.getMessage()); @@ -670,12 +671,12 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel } private void setEndTime(RaceColumnDTO raceColumnDTO, FleetDTO fleetDTO) { - new SetFinishingAndFinishedTimeDialog(sailingService, errorReporter, getSelectedLeaderboardName(), + new SetFinishingAndFinishedTimeDialog(sailingServiceWrite, errorReporter, getSelectedLeaderboardName(), raceColumnDTO.getName(), fleetDTO.getName(), stringMessages, new DialogCallback() { @Override public void ok(RaceLogSetFinishingAndFinishTimeDTO editedObject) { - sailingService.setFinishingAndEndTime(editedObject, + sailingServiceWrite.setFinishingAndEndTime(editedObject, new AsyncCallback>() { @Override public void onFailure(Throwable caught) { @@ -701,7 +702,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel private void removeRaceColumn(final RaceColumnDTO raceColumnDTO) { final String selectedLeaderboardName = getSelectedLeaderboardName(); final String raceColumnString = raceColumnDTO.getRaceColumnName(); - sailingService.removeLeaderboardColumn(getSelectedLeaderboardName(), raceColumnString, + sailingServiceWrite.removeLeaderboardColumn(getSelectedLeaderboardName(), raceColumnString, new MarkedAsyncCallback(new AsyncCallback() { @Override public void onFailure(Throwable t) { @@ -723,7 +724,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel private void moveSelectedRaceColumnDown() { final String selectedLeaderboardName = getSelectedLeaderboardName(); final String selectedRaceColumnName = getSelectedRaceColumnWithFleet().getA().getRaceColumnName(); - sailingService.moveLeaderboardColumnDown(getSelectedLeaderboardName(), selectedRaceColumnName, + sailingServiceWrite.moveLeaderboardColumnDown(getSelectedLeaderboardName(), selectedRaceColumnName, new MarkedAsyncCallback(new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -746,7 +747,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel private void moveSelectedRaceColumnUp() { final String selectedLeaderboardName = getSelectedLeaderboardName(); final String selectedRaceColumnName = getSelectedRaceColumnWithFleet().getA().getRaceColumnName(); - sailingService.moveLeaderboardColumnUp(getSelectedLeaderboardName(), selectedRaceColumnName, + sailingServiceWrite.moveLeaderboardColumnUp(getSelectedLeaderboardName(), selectedRaceColumnName, new MarkedAsyncCallback(new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -778,7 +779,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel private void setIsMedalRace(String leaderboardName, final RaceColumnDTO raceInLeaderboard, final boolean isMedalRace) { - sailingService.updateIsMedalRace(leaderboardName, raceInLeaderboard.getRaceColumnName(), isMedalRace, + sailingServiceWrite.updateIsMedalRace(leaderboardName, raceInLeaderboard.getRaceColumnName(), isMedalRace, new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -824,7 +825,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel } } - sailingService.addColumnsToLeaderboard(leaderboardName, raceColumnsToAdd, + sailingServiceWrite.addColumnsToLeaderboard(leaderboardName, raceColumnsToAdd, new MarkedAsyncCallback(new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -880,7 +881,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel } private void createFlexibleLeaderboard() { - sailingService.getEvents(new MarkedAsyncCallback>(new AsyncCallback>() { + sailingServiceWrite.getEvents(new MarkedAsyncCallback>(new AsyncCallback>() { @Override public void onSuccess(List result) { createFlexibleLeaderboard(result); @@ -904,7 +905,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel @Override public void ok(final LeaderboardDescriptor newLeaderboard) { - sailingService.createFlexibleLeaderboard(newLeaderboard.getName(), + sailingServiceWrite.createFlexibleLeaderboard(newLeaderboard.getName(), newLeaderboard.getDisplayName(), newLeaderboard.getDiscardThresholds(), newLeaderboard.getScoringScheme(), newLeaderboard.getCourseAreaIds(), new MarkedAsyncCallback( @@ -939,7 +940,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel @Override public void ok(final LeaderboardDescriptor newLeaderboard) { RegattaName regattaIdentifier = new RegattaName(newLeaderboard.getRegattaName()); - sailingService.createRegattaLeaderboard(regattaIdentifier, newLeaderboard.getDisplayName(), + sailingServiceWrite.createRegattaLeaderboard(regattaIdentifier, newLeaderboard.getDisplayName(), newLeaderboard.getDiscardThresholds(), new AsyncCallback() { @Override @@ -961,7 +962,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel private void createRegattaLeaderboardWithEliminations() { RegattaLeaderboardWithEliminationsCreateDialog dialog = new RegattaLeaderboardWithEliminationsCreateDialog( - sailingService, userService, Collections.unmodifiableCollection(availableLeaderboardList), + sailingServiceWrite, userService, Collections.unmodifiableCollection(availableLeaderboardList), Collections.unmodifiableCollection(allRegattas), stringMessages, errorReporter, new DialogCallback() { @Override @@ -970,7 +971,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel @Override public void ok(final LeaderboardDescriptorWithEliminations newLeaderboard) { - sailingService.createRegattaLeaderboardWithEliminations(newLeaderboard.getName(), + sailingServiceWrite.createRegattaLeaderboardWithEliminations(newLeaderboard.getName(), newLeaderboard.getDisplayName(), newLeaderboard.getRegattaName(), new AsyncCallback() { @Override @@ -982,7 +983,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel @Override public void onSuccess(StrippedLeaderboardDTOWithSecurity result) { addLeaderboard(result); - sailingService.setEliminatedCompetitors(newLeaderboard.getName(), + sailingServiceWrite.setEliminatedCompetitors(newLeaderboard.getName(), newLeaderboard.getEliminatedCompetitors(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -1013,25 +1014,25 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel leaderboardSelectionModel.setSelected(result, true); } - private void updateLeaderboard(final String oldLeaderboardName, final LeaderboardDescriptor leaderboardToUpdate) { - sailingService.updateLeaderboard(oldLeaderboardName, leaderboardToUpdate.getName(), - leaderboardToUpdate.getDisplayName(), leaderboardToUpdate.getDiscardThresholds(), - leaderboardToUpdate.getCourseAreaIds(), new AsyncCallback() { + private void updateLeaderboard(final String leaderboardName, final LeaderboardDescriptor leaderboardToUpdate) { + sailingServiceWrite.updateLeaderboard(leaderboardName, leaderboardToUpdate.getDisplayName(), + leaderboardToUpdate.getDiscardThresholds(), leaderboardToUpdate.getCourseAreaIds(), + new AsyncCallback() { @Override public void onFailure(Throwable t) { errorReporter.reportError( - "Error trying to update leaderboard " + oldLeaderboardName + ": " + t.getMessage()); + "Error trying to update leaderboard " + leaderboardName + ": " + t.getMessage()); } @Override public void onSuccess(StrippedLeaderboardDTOWithSecurity updatedLeaderboard) { - refreshLeaderboardInTable(oldLeaderboardName, updatedLeaderboard); + refreshLeaderboardInTable(leaderboardName, updatedLeaderboard); } }); } private void reloadLeaderboardForTable(final String leaderboardName) { - sailingService.getLeaderboardWithSecurity(leaderboardName, + sailingServiceWrite.getLeaderboardWithSecurity(leaderboardName, new AsyncCallback() { @Override public void onSuccess(StrippedLeaderboardDTOWithSecurity result) { @@ -1066,7 +1067,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel for (StrippedLeaderboardDTO leaderboard : leaderboards) { leaderboardNames.add(leaderboard.getName()); } - sailingService.removeLeaderboards(leaderboardNames, new AsyncCallback() { + sailingServiceWrite.removeLeaderboards(leaderboardNames, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Error trying to remove the leaderboards:" + caught.getMessage()); @@ -1085,7 +1086,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel } private void removeLeaderboard(final StrippedLeaderboardDTOWithSecurity leaderBoard) { - sailingService.removeLeaderboard(leaderBoard.getName(), + sailingServiceWrite.removeLeaderboard(leaderBoard.getName(), new MarkedAsyncCallback(new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -1116,7 +1117,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel public void ok(PairingListTemplateDTO editedObject) { BusyDialog busyDialog = new BusyDialog(); busyDialog.show(); - sailingService.calculatePairingListTemplate(editedObject.getFlightCount(), + sailingServiceWrite.calculatePairingListTemplate(editedObject.getFlightCount(), editedObject.getGroupCount(), editedObject.getCompetitorCount(), editedObject.getFlightMultiplier(), editedObject.getBoatChangeFactor(), new AsyncCallback() { @@ -1146,7 +1147,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel private void openPairingListCreationDialog(StrippedLeaderboardDTOWithSecurity leaderboardDTO, PairingListTemplateDTO template) { PairingListCreationDialog dialog = new PairingListCreationDialog(leaderboardDTO, stringMessages, template, - sailingService, errorReporter); + sailingServiceWrite, errorReporter); dialog.show(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardDescriptor.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardDescriptor.java index 5eea1d1b060..f96e8b474ad 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardDescriptor.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardDescriptor.java @@ -90,7 +90,7 @@ public class LeaderboardDescriptor { this.displayName = displayName; } - public Iterable getCourseAreaIds() { + public List getCourseAreaIds() { return courseAreaIds; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupConfigPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupConfigPanel.java index 3a536390088..c1bcd1c574f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupConfigPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupConfigPanel.java @@ -56,7 +56,7 @@ import com.sap.sailing.gwt.ui.client.LeaderboardGroupsRefresher; import com.sap.sailing.gwt.ui.client.LeaderboardsDisplayer; import com.sap.sailing.gwt.ui.client.LeaderboardsRefresher; import com.sap.sailing.gwt.ui.client.RegattaRefresher; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.leaderboard.ScoringSchemeTypeFormatter; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; @@ -142,11 +142,11 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel private final Set permissionRestrictedComponent = new HashSet<>(); private final Label idLabel = new Label(); - public LeaderboardGroupConfigPanel(SailingServiceAsync sailingService, UserService userService, + public LeaderboardGroupConfigPanel(SailingServiceWriteAsync sailingServiceWrite, UserService userService, RegattaRefresher regattaRefresher, LeaderboardGroupsRefresher leaderboardGroupsRefresher, LeaderboardsRefresher leaderboardsRefresher, ErrorReporter errorReporter, StringMessages stringMessages) { - super(sailingService, regattaRefresher, errorReporter, stringMessages); + super(sailingServiceWrite, regattaRefresher, errorReporter, stringMessages); this.userService = userService; AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class); @@ -225,7 +225,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel public Iterable getSearchableStrings(StrippedLeaderboardDTO t) { List strings = new ArrayList(); strings.add(t.getName()); - strings.add(t.displayName); + strings.add(t.getDisplayName()); return strings; } @@ -357,7 +357,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel if (isSingleGroupSelected) { LeaderboardGroupDTO selectedGroup = getSelectedGroup(); setDescriptionEditable(false); - descriptionTextArea.setText(selectedGroup.description); + descriptionTextArea.setText(selectedGroup.getDescription()); } }); abortDescriptionButton.getElement().getStyle().setMarginRight(5, Unit.PX); @@ -471,13 +471,10 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel final CaptionPanel leaderboardGroupsCaptionPanel = new CaptionPanel(stringMessages.leaderboardGroups()); final VerticalPanel leaderboardGroupsContentPanel = new VerticalPanel(); leaderboardGroupsCaptionPanel.add(leaderboardGroupsContentPanel); - // Create functional elements for the leaderboard groups final AccessControlledButtonPanel buttonPanel = new AccessControlledButtonPanel(userService, LEADERBOARD_GROUP); leaderboardGroupsContentPanel.add(buttonPanel); - Label filterLeaderboardGroupsLbl = new Label(stringMessages.filterLeaderboardGroupsByName() + ":"); - //Create table for leaderboard groups groupsProvider = new ListDataProvider(); ListHandler leaderboardGroupsListHandler = new ListHandler(groupsProvider.getList()); @@ -487,9 +484,11 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel availableLeaderboardGroups, groupsProvider, stringMessages) { @Override public Iterable getSearchableStrings(LeaderboardGroupDTO t) { - List string = new ArrayList(); - string.add(t.getName()); - return string; + List strings = new ArrayList(); + strings.add(t.getName()); + strings.add(t.getDisplayName()); + strings.add(t.getDescription()); + return strings; } @Override @@ -501,22 +500,17 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel leaderboardGroupsContentPanel.add(groupsFilterablePanel); groupsFilterablePanel.setUpdatePermissionFilterForCheckbox( leaderboardGroup -> userService.hasPermission(leaderboardGroup, DefaultActions.UPDATE)); - final Button createButton = buttonPanel.addCreateAction(stringMessages.createNewLeaderboardGroup(), this::addNewGroup); createButton.ensureDebugId("CreateLeaderboardGroupButton"); - final Button refreshButton = buttonPanel.addUnsecuredAction(stringMessages.refresh(), () -> { leaderboardsRefresher.fillLeaderboards(); leaderboardGroupsRefresher.fillLeaderboardGroups(); }); refreshButton.ensureDebugId("RefreshLeaderboardGroupsButton"); - AnchorCell anchorCell = new AnchorCell(); - final TextColumn groupUUidColumn = new AbstractSortableTextColumn( group -> group.getId() == null ? "" : group.getId().toString()); - Column groupNameColumn = new Column(anchorCell) { @Override public SafeHtml getValue(LeaderboardGroupDTO group) { @@ -525,7 +519,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel + "&showRaceDetails=true&" + RaceBoardPerspectiveOwnSettings.PARAM_CAN_REPLAY_DURING_LIVE_RACES + "=true" + (debugParam != null && !debugParam.isEmpty() ? "&gwt.codesvr=" + debugParam : "")); return ANCHORTEMPLATE.cell(UriUtils.fromString(link), group.getName()); - } + } }; groupNameColumn.setSortable(true); leaderboardGroupsListHandler.setComparator(groupNameColumn, new Comparator() { @@ -534,21 +528,19 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel return new NaturalComparator(false).compare(group1.getName(), group2.getName()); } }); - TextColumn groupDescriptionColumn = new TextColumn() { @Override public String getValue(LeaderboardGroupDTO group) { - return group.description.length() <= 100 ? group.description : group.description.substring(0, 98) + "..."; + return group.getDescription().length() <= 100 ? group.getDescription() : group.getDescription().substring(0, 98) + "..."; } }; groupDescriptionColumn.setSortable(true); leaderboardGroupsListHandler.setComparator(groupDescriptionColumn, new Comparator() { @Override public int compare(LeaderboardGroupDTO group1, LeaderboardGroupDTO group2) { - return new NaturalComparator(false).compare(group1.description, group2.description); + return new NaturalComparator(false).compare(group1.getDescription(), group2.getDescription()); } }); - TextColumn groupDisplayNameColumn = new TextColumn() { @Override public String getValue(LeaderboardGroupDTO group) { @@ -563,7 +555,6 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel return new NaturalComparator(false).compare(group1.getDisplayName(), group2.getDisplayName()); } }); - TextColumn hasOverallLeaderboardColumn = new TextColumn() { @Override public String getValue(LeaderboardGroupDTO group) { @@ -582,7 +573,6 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel hasOverallLeaderboardColumn.getValue(group2)); } }); - final HasPermissions type = SecuredDomainType.LEADERBOARD_GROUP; final AccessControlledActionsColumn actionsColumn = create( new LeaderboardGroupConfigImagesBarCell(stringMessages), userService); @@ -616,10 +606,9 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel configACL.openACLDialog(e); } }); - final MigrateGroupOwnershipDialog.DialogConfig migrateDialogConfig = MigrateGroupOwnershipDialog .create(userService.getUserManagementService(), (lg, dto) -> { - sailingService.updateGroupOwnerForLeaderboardGroupHierarchy(lg.getId(), dto, + sailingServiceWrite.updateGroupOwnerForLeaderboardGroupHierarchy(lg.getId(), dto, new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -640,7 +629,6 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel migrateDialogConfig.openDialog(e); } }); - SelectionCheckboxColumn leaderboardTableSelectionColumn = new SelectionCheckboxColumn( tableResources.cellTableStyle().cellTableCheckboxSelected(), @@ -667,19 +655,14 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel groupsTable.addColumn(groupUUidColumn, stringMessages.id()); groupsTable.addColumn(actionsColumn, stringMessages.actions()); groupsTable.addColumnSortHandler(leaderboardGroupsListHandler); - refreshableGroupsSelectionModel = leaderboardTableSelectionColumn.getSelectionModel(); - removeButton = buttonPanel.addRemoveAction(stringMessages.remove(), refreshableGroupsSelectionModel, true, () -> removeLeaderboardGroups(refreshableGroupsSelectionModel.getSelectedSet())); removeButton.ensureDebugId("RemoveLeaderboardButton"); - refreshableGroupsSelectionModel.addSelectionChangeHandler(event -> groupSelectionChanged()); - groupsTable.setSelectionModel(refreshableGroupsSelectionModel, leaderboardTableSelectionColumn.getSelectionManager()); groupsProvider.addDataDisplay(groupsTable); leaderboardGroupsContentPanel.add(groupsTable); - return leaderboardGroupsCaptionPanel; } @@ -733,7 +716,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel */ private void refreshLeaderboardsList() { if (isSingleGroupSelected && getSelectedGroup() != null) { - sailingService.getLeaderboardsWithSecurity(new MarkedAsyncCallback>( + sailingServiceWrite.getLeaderboardsWithSecurity(new MarkedAsyncCallback>( new AsyncCallback>() { @Override public void onFailure(Throwable t) { @@ -764,7 +747,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel } private void createNewGroup(final LeaderboardGroupDescriptor newGroup) { - sailingService.createLeaderboardGroup(newGroup.getName(), newGroup.getDescription(), + sailingServiceWrite.createLeaderboardGroup(newGroup.getName(), newGroup.getDescription(), newGroup.getDisplayName(), newGroup.isDisplayLeaderboardsInReverseOrder(), newGroup.getOverallLeaderboardDiscardThresholds(), newGroup.getOverallLeaderboardScoringSchemeType(), new MarkedAsyncCallback( new AsyncCallback() { @@ -789,7 +772,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel for (StrippedLeaderboardDTO leaderboardDTO : groupToUpdate.leaderboards) { leaderboardNames.add(leaderboardDTO.getName()); } - sailingService.updateLeaderboardGroup(oldGroupId, oldGroupName, updateDescriptor.getName(), updateDescriptor.getDescription(), + sailingServiceWrite.updateLeaderboardGroup(oldGroupId, oldGroupName, updateDescriptor.getName(), updateDescriptor.getDescription(), updateDescriptor.getDisplayName(), leaderboardNames, updateDescriptor.getOverallLeaderboardDiscardThresholds(), updateDescriptor.getOverallLeaderboardScoringSchemeType(), new MarkedAsyncCallback( @@ -811,7 +794,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel refreshableGroupsSelectionModel.setSelected(groupToUpdate, false); } groupToUpdate.setName(updateDescriptor.getName()); - groupToUpdate.description = updateDescriptor.getDescription(); + groupToUpdate.setDescription(updateDescriptor.getDescription()); groupToUpdate.setDisplayName(updateDescriptor.getDisplayName()); groupToUpdate.displayLeaderboardsInReverseOrder = updateDescriptor.isDisplayLeaderboardsInReverseOrder(); groupToUpdate.setOverallLeaderboardDiscardThresholds(updateDescriptor.getOverallLeaderboardDiscardThresholds()); @@ -841,7 +824,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel for (StrippedLeaderboardDTO leaderboardDTO : group.leaderboards) { leaderboardNames.add(leaderboardDTO.getName()); } - sailingService.updateLeaderboardGroup(group.getId(), group.getName(), group.getName(), group.description, + sailingServiceWrite.updateLeaderboardGroup(group.getId(), group.getName(), group.getName(), group.getDescription(), group.getDisplayName(), leaderboardNames, group.getOverallLeaderboardDiscardThresholds(), group.getOverallLeaderboardScoringSchemeType(), new MarkedAsyncCallback( @@ -863,7 +846,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel for (LeaderboardGroupDTO group : groups) { groupNames.add(group.getName()); } - sailingService.removeLeaderboardGroups(groupNames, new MarkedAsyncCallback( + sailingServiceWrite.removeLeaderboardGroups(groupNames, new MarkedAsyncCallback( new AsyncCallback() { @Override public void onFailure(Throwable t) { @@ -884,7 +867,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel private void removeLeaderboardGroup(final LeaderboardGroupDTO group) { Set groups = new HashSet(); groups.add(group.getName()); - sailingService.removeLeaderboardGroups(groups, new MarkedAsyncCallback( + sailingServiceWrite.removeLeaderboardGroups(groups, new MarkedAsyncCallback( new AsyncCallback() { @Override public void onFailure(Throwable t) { @@ -923,7 +906,7 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel //Display details of the group groupDetailsCaptionPanel.setCaptionText(stringMessages.detailsOfLeaderboardGroup() + " '" + selectedGroup.getName() + "'"); idLabel.setText(selectedGroup.getId().toString()); - descriptionTextArea.setText(selectedGroup.description); + descriptionTextArea.setText(selectedGroup.getDescription()); setDescriptionEditable(false); groupDetailsProvider.getList().clear(); @@ -1043,12 +1026,12 @@ public class LeaderboardGroupConfigPanel extends AbstractRegattaPanel LeaderboardGroupDTO selectedGroup = getSelectedGroup(); if (isSingleGroupSelected && selectedGroup != null) { if (newDescription != null && newDescription.length() > 0) { - selectedGroup.description = newDescription; + selectedGroup.setDescription(newDescription); setDescriptionEditable(false); updateGroup(selectedGroup); } else { Notification.notify(stringMessages.pleaseEnterNonEmptyDescription() + ".", NotificationType.ERROR); - descriptionTextArea.setText(selectedGroup.description); + descriptionTextArea.setText(selectedGroup.getDescription()); } } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupEditDialog.java index 09ea129c702..173ae398ac4 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardGroupEditDialog.java @@ -12,7 +12,7 @@ public class LeaderboardGroupEditDialog extends LeaderboardGroupDialog { // don't allow editing the overall leaderboard's scoring scheme if the group already uses an overall leaderboard getOverallLeaderboardScoringSchemeListBox().setEnabled(!group.hasOverallLeaderboard()); nameEntryField = createTextBox(group.getName(), 50); - descriptionEntryField = createTextArea(group.description); + descriptionEntryField = createTextArea(group.getDescription()); displayNameEntryField = createTextBox(group.getDisplayName()); displayLeaderboardsInReverseOrderCheckBox.setValue(group.displayLeaderboardsInReverseOrder); displayLeaderboardsInReverseOrderCheckBox.setEnabled(false); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MarkTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MarkTableWrapper.java index 888d91a713c..95647cf1cdd 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MarkTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MarkTableWrapper.java @@ -7,7 +7,7 @@ import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.user.cellview.client.Column; import com.google.gwt.user.cellview.client.TextColumn; import com.sap.sailing.gwt.ui.adminconsole.ColorColumn.ColorRetriever; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.MarkDTO; import com.sap.sse.common.Color; @@ -16,9 +16,9 @@ import com.sap.sse.gwt.client.celltable.EntityIdentityComparator; import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel; public class MarkTableWrapper> extends TableWrapper { - public MarkTableWrapper(boolean multiSelection, SailingServiceAsync sailingService, StringMessages stringMessages, + public MarkTableWrapper(boolean multiSelection, SailingServiceWriteAsync sailingServiceWrite, StringMessages stringMessages, ErrorReporter errorReporter) { - super(sailingService, stringMessages, errorReporter, multiSelection, true, + super(sailingServiceWrite, stringMessages, errorReporter, multiSelection, true, new EntityIdentityComparator() { @Override public boolean representSameEntity(MarkDTO dto1, MarkDTO dto2) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MatchImportedCompetitorsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MatchImportedCompetitorsDialog.java index 0826d4c7e07..fb661fa8189 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MatchImportedCompetitorsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MatchImportedCompetitorsDialog.java @@ -19,6 +19,7 @@ import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTO; import com.sap.sailing.gwt.ui.adminconsole.CompetitorDescriptorTableWrapper.CompetitorsToImportToExistingLinking; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; @@ -63,7 +64,7 @@ public class MatchImportedCompetitorsDialog extends DataEntryDialog CompetitorDescriptors, final Iterable existingCompetitor, StringMessages stringMessages, - SailingServiceAsync sailingService, final UserService userService, ErrorReporter errorReporter, + SailingServiceWriteAsync sailingServiceWrite, final UserService userService, ErrorReporter errorReporter, DialogCallback, String>> callback) { super(stringMessages.importCompetitors(), stringMessages.chooseWhichCompetitorsShouldBeImported(), stringMessages.ok(), stringMessages.cancel(), /* validator */ null, callback); this.stringMessages = stringMessages; - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.userService = userService; this.errorReporter = errorReporter; this.CompetitorDescriptors = CompetitorDescriptors; @@ -93,7 +94,7 @@ public class MatchImportedCompetitorsDialog extends DataEntryDialog(sailingService, userService, stringMessages, + existingCompetitorsTable = new CompetitorTableWrapper<>(sailingServiceWrite, userService, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */true, /* filterCompetitorWithBoat */ false, /* filterCompetitorsWithoutBoat */ false); final CompetitorsToImportToExistingLinking linker = new CompetitorsToImportToExistingLinking() { @@ -111,7 +112,7 @@ public class MatchImportedCompetitorsDialog extends DataEntryDialog(competitorImportMatcher, sailingService, + importedCompetitorsTable = new CompetitorDescriptorTableWrapper<>(competitorImportMatcher, sailingServiceWrite, stringMessages, errorReporter, /* multiSelection */ true, /* enablePager */false, /* unlinkCallback */ linker); importedCompetitorsTable.refreshCompetitorDescriptorList(CompetitorDescriptors); final RefreshableMultiSelectionModel importedCompetitorSelectionModel = importedCompetitorsTable.getSelectionModel(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MediaPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MediaPanel.java index 8fb424e5ab2..bfcaec31f2b 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MediaPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/MediaPanel.java @@ -54,7 +54,7 @@ import com.sap.sailing.gwt.ui.client.MediaServiceAsync; import com.sap.sailing.gwt.ui.client.MediaTracksRefresher; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.RegattasDisplayer; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.media.NewMediaWithRaceSelectionDialog; import com.sap.sailing.gwt.ui.client.media.TimeFormatUtil; @@ -94,7 +94,7 @@ import com.sap.sse.security.ui.client.component.editacl.EditACLDialog; public class MediaPanel extends FlowPanel implements MediaTracksRefresher { private static AdminConsoleTableResources tableResources = GWT.create(AdminConsoleTableResources.class); - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final LabeledAbstractFilterablePanel filterableMediaTracks; private List allMediaTracks; private final RegattaRefresher regattaRefresher; @@ -109,17 +109,17 @@ public class MediaPanel extends FlowPanel implements MediaTracksRefresher { private RefreshableMultiSelectionModel refreshableSelectionModel; private final FileStorageServiceConnectionTestObservable storageServiceAvailable; - public MediaPanel(Set regattasDisplayers, SailingServiceAsync sailingService, + public MediaPanel(Set regattasDisplayers, SailingServiceWriteAsync sailingServiceWrite, RegattaRefresher regattaRefresher, MediaServiceAsync mediaService, ErrorReporter errorReporter, StringMessages stringMessages, final UserService userService) { this.regattasDisplayers = regattasDisplayers; - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.userService = userService; this.regattaRefresher = regattaRefresher; this.mediaService = mediaService; this.stringMessages = stringMessages; this.errorReporter = errorReporter; - this.storageServiceAvailable = new FileStorageServiceConnectionTestObservable(sailingService); + this.storageServiceAvailable = new FileStorageServiceConnectionTestObservable(sailingServiceWrite); AccessControlledButtonPanel buttonAndFilterPanel = new AccessControlledButtonPanel(userService, SecuredDomainType.MEDIA_TRACK); add(buttonAndFilterPanel); @@ -140,7 +140,7 @@ public class MediaPanel extends FlowPanel implements MediaTracksRefresher { buttonAndFilterPanel.addCreateAction(stringMessages.multiVideoLinking(), new Command() { @Override public void execute() { - new MultiVideoDialog(sailingService, mediaService, stringMessages, errorReporter, new Runnable() { + new MultiVideoDialog(sailingServiceWrite, mediaService, stringMessages, errorReporter, new Runnable() { @Override public void run() { @@ -580,19 +580,15 @@ public class MediaPanel extends FlowPanel implements MediaTracksRefresher { removeMediaTrack(mediaTrack); } }); - final EditOwnershipDialog.DialogConfig configOwnership = EditOwnershipDialog.create( - userService.getUserManagementService(), type, - mediaTrack -> { - /* no refresh action */}, - stringMessages); - + final EditOwnershipDialog.DialogConfig configOwnership = EditOwnershipDialog + .create(userService.getUserManagementService(), type, mediaTrack -> mediaTrackListDataProvider.refresh(), stringMessages); final EditACLDialog.DialogConfig configACL = EditACLDialog.create( - userService.getUserManagementService(), type, mediaTrack -> mediaTrack.getAccessControlList(), stringMessages); + userService.getUserManagementService(), type, mediaTrack -> mediaTrack.getAccessControlList(), + stringMessages); actionsColumn.addAction(ACTION_CHANGE_OWNERSHIP, CHANGE_OWNERSHIP, configOwnership::openOwnershipDialog); actionsColumn.addAction(DefaultActionsImagesBarCell.ACTION_CHANGE_ACL, DefaultActions.CHANGE_ACL, mediaTrack -> configACL.openACLDialog(mediaTrack)); mediaTracksTable.addColumn(actionsColumn, stringMessages.actions()); - } protected void removeMediaTrack(MediaTrack mediaTrack) { @@ -612,7 +608,7 @@ public class MediaPanel extends FlowPanel implements MediaTracksRefresher { private void addUrlMediaTrack() { NewMediaWithRaceSelectionDialog dialog = new NewMediaWithRaceSelectionDialog(mediaService, - getDefaultStartTime(), stringMessages, sailingService, userService, errorReporter, regattaRefresher, + getDefaultStartTime(), stringMessages, sailingServiceWrite, userService, errorReporter, regattaRefresher, regattasDisplayers, storageServiceAvailable, new DialogCallback() { @Override @@ -653,7 +649,7 @@ public class MediaPanel extends FlowPanel implements MediaTracksRefresher { } private Date getLatestDate() { - sailingService.getRegattas(new MarkedAsyncCallback>(new AsyncCallback>() { + sailingServiceWrite.getRegattas(new MarkedAsyncCallback>(new AsyncCallback>() { @Override public void onSuccess(List result) { latestDate = getDateFromLatestRegatta(result); @@ -705,7 +701,7 @@ public class MediaPanel extends FlowPanel implements MediaTracksRefresher { public void openAssignedRacesDialog(final Context context, final Element parent, final ValueUpdater valueUpdater) { final MediaTrackWithSecurityDTO mediaTrack = (MediaTrackWithSecurityDTO) context.getKey(); - final AssignRacesToMediaDialog dialog = new AssignRacesToMediaDialog(sailingService, userService, mediaTrack, + final AssignRacesToMediaDialog dialog = new AssignRacesToMediaDialog(sailingServiceWrite, userService, mediaTrack, errorReporter, regattaRefresher, stringMessages, null, new DialogCallback>() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/PairingListCreationDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/PairingListCreationDialog.java index bbc3c8decab..be98259c343 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/PairingListCreationDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/PairingListCreationDialog.java @@ -1,6 +1,6 @@ package com.sap.sailing.gwt.ui.adminconsole; -import java.util.ArrayList; +import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -23,7 +23,7 @@ import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.PairingListDTO; import com.sap.sailing.domain.common.dto.PairingListTemplateDTO; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; import com.sap.sse.common.Util; @@ -36,7 +36,7 @@ import com.sap.sse.gwt.client.dialog.DataEntryDialog; public class PairingListCreationDialog extends DataEntryDialog { private final PairingListTemplateDTO template; - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final StrippedLeaderboardDTO leaderboardDTO; private final StringMessages stringMessages; @@ -51,13 +51,13 @@ public class PairingListCreationDialog extends DataEntryDialog() { @Override @@ -191,7 +191,7 @@ public class PairingListCreationDialog extends DataEntryDialog() { @Override @@ -211,7 +211,7 @@ public class PairingListCreationDialog extends DataEntryDialog>() { @Override public void onFailure(Throwable caught) { @@ -234,7 +234,7 @@ public class PairingListCreationDialog extends DataEntryDialog() { @@ -249,7 +249,7 @@ public class PairingListCreationDialog extends DataEntryDialog userService.hasPermission(leaderboard, DefaultActions.UPDATE), leaderboard.getName() + "/" + raceColumn.getName() + "/" + fleet.getName()); @@ -45,10 +46,10 @@ public class RaceBoatCertificatesPanel extends AbstractBoatCertificatesPanel { } @Override - protected void assignCertificates(SailingServiceAsync sailingService, + protected void assignCertificates(SailingServiceWriteAsync sailingServiceWrite, Map certificatesByBoatIdAsString, AsyncCallback> callback) { - sailingService.assignORCPerformanceCurveCertificates(leaderboardName, raceColumnName, fleetName, + sailingServiceWrite.assignORCPerformanceCurveCertificates(leaderboardName, raceColumnName, fleetName, certificatesByBoatIdAsString, callback); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceCourseManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceCourseManagementPanel.java index 7a911e4803c..e3f3c411e5f 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceCourseManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceCourseManagementPanel.java @@ -12,7 +12,7 @@ import com.google.gwt.user.client.ui.HorizontalPanel; import com.sap.sailing.domain.common.RankingMetrics; import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveLegImpl; import com.sap.sailing.gwt.ui.client.RegattaRefresher; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RaceCourseDTO; import com.sap.sse.gwt.client.ErrorReporter; @@ -32,14 +32,14 @@ import com.sap.sse.security.ui.client.UserService; public class RaceCourseManagementPanel extends AbstractRaceManagementPanel { private final CourseManagementWidget courseManagementWidget; - public RaceCourseManagementPanel(final SailingServiceAsync sailingService, final ErrorReporter errorReporter, + public RaceCourseManagementPanel(final SailingServiceWriteAsync sailingServiceWrite, final ErrorReporter errorReporter, RegattaRefresher regattaRefresher, final StringMessages stringMessages, final UserService userService) { - super(sailingService, userService, errorReporter, regattaRefresher, /* actionButtonsEnabled */ false, stringMessages); - courseManagementWidget = new CourseManagementWidget(sailingService, errorReporter, stringMessages, + super(sailingServiceWrite, userService, errorReporter, regattaRefresher, /* actionButtonsEnabled */ false, stringMessages); + courseManagementWidget = new CourseManagementWidget(sailingServiceWrite, errorReporter, stringMessages, userService, ()->selectedRaceHasOrcPcsRankingMetric()) { @Override protected void save() { - sailingService.updateRaceCourse(singleSelectedRace, createWaypointPairs(), new AsyncCallback() { + sailingServiceWrite.updateRaceCourse(singleSelectedRace, createWaypointPairs(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(stringMessages.errorUpdatingRaceCourse(caught.getMessage())); @@ -48,7 +48,7 @@ public class RaceCourseManagementPanel extends AbstractRaceManagementPanel { @Override public void onSuccess(Void result) { Notification.notify(stringMessages.successfullyUpdatedCourse(), NotificationType.INFO); - sailingService.setORCPerformanceCurveLegInfo(singleSelectedRace, getORCPerformanceCurveLegInfoByOneBasedWaypointIndex(), new AsyncCallback() { + sailingServiceWrite.setORCPerformanceCurveLegInfo(singleSelectedRace, getORCPerformanceCurveLegInfoByOneBasedWaypointIndex(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(stringMessages.errorUpdatingRaceCourse(caught.getMessage())); @@ -66,7 +66,7 @@ public class RaceCourseManagementPanel extends AbstractRaceManagementPanel { @Override protected LegGeometrySupplier getLegGeometrySupplier() { return (zeroBasedLegIndices, legTypes, callback)-> - sailingService.getLegGeometry(singleSelectedRace, zeroBasedLegIndices, legTypes, callback); + sailingServiceWrite.getLegGeometry(singleSelectedRace, zeroBasedLegIndices, legTypes, callback); } @Override @@ -74,7 +74,7 @@ public class RaceCourseManagementPanel extends AbstractRaceManagementPanel { if (singleSelectedRace != null && selectedRaceDTO != null) { mainPanel.setVisible(true); // TODO bug 1351: never use System.currentTimeMillis() on the client when trying to compare anything with "server time"; this one is not so urgent as it is reached only in the AdminConsole and we expect administrators to have proper client-side time settings - sailingService.getRaceCourse(singleSelectedRace, new Date(), new AsyncCallback() { + sailingServiceWrite.getRaceCourse(singleSelectedRace, new Date(), new AsyncCallback() { @Override public void onSuccess(RaceCourseDTO raceCourseDTO) { updateWaypointsAndControlPoints(raceCourseDTO, selectedRaceDTO); @@ -96,7 +96,7 @@ public class RaceCourseManagementPanel extends AbstractRaceManagementPanel { private void refreshORCPerformanceCurveLegs() { if (singleSelectedRace != null) { - sailingService.getORCPerformanceCurveLegInfo(singleSelectedRace, + sailingServiceWrite.getORCPerformanceCurveLegInfo(singleSelectedRace, new AsyncCallback>() { @Override public void onSuccess(Map result) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogCompetitorRegistrationDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogCompetitorRegistrationDialog.java index a54df6bbd85..f6b83929277 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogCompetitorRegistrationDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogCompetitorRegistrationDialog.java @@ -22,7 +22,7 @@ import com.sap.sailing.domain.common.dto.CompetitorAndBoatDTO; import com.sap.sailing.domain.common.dto.CompetitorDTO; import com.sap.sailing.domain.common.dto.CompetitorWithToolTipDTO; import com.sap.sailing.domain.common.dto.FleetDTO; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.async.ParallelExecutionCallback; @@ -37,7 +37,7 @@ public class RaceLogCompetitorRegistrationDialog extends AbstractCompetitorRegis private CheckBox competitorRegistrationInRaceLogCheckBox; private final Map> fleetNameWithCompetitors; private final ErrorReporter errorReporter; - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final StringMessages stringMessages; private static class Validator implements com.sap.sse.gwt.client.dialog.DataEntryDialog.Validator> { @@ -96,24 +96,24 @@ public class RaceLogCompetitorRegistrationDialog extends AbstractCompetitorRegis } } - public RaceLogCompetitorRegistrationDialog(String boatClass, SailingServiceAsync sailingService, final UserService userService, + public RaceLogCompetitorRegistrationDialog(String boatClass, SailingServiceWriteAsync sailingServiceWrite, final UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, boolean editable, String leaderboardName, boolean canBoatsOfCompetitorsChangePerRace, String raceColumnName, String fleetName, List fleets, com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback> callback) { - this(sailingService, userService, stringMessages, errorReporter, editable, callback, leaderboardName, canBoatsOfCompetitorsChangePerRace, boatClass, + this(sailingServiceWrite, userService, stringMessages, errorReporter, editable, callback, leaderboardName, canBoatsOfCompetitorsChangePerRace, boatClass, raceColumnName, fleetName, fleets, new Validator(stringMessages)); } - public RaceLogCompetitorRegistrationDialog(SailingServiceAsync sailingService, final UserService userService, StringMessages stringMessages, + public RaceLogCompetitorRegistrationDialog(SailingServiceWriteAsync sailingServiceWrite, final UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, boolean editable, com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback> callback, String leaderboardName, boolean canBoatsOfCompetitorsChangePerRace, String boatClass, String raceColumnName, String fleetName, List fleets, Validator validator) { - super(sailingService, userService, stringMessages, errorReporter, editable, callback, leaderboardName, + super(sailingServiceWrite, userService, stringMessages, errorReporter, editable, callback, leaderboardName, canBoatsOfCompetitorsChangePerRace, boatClass, canBoatsOfCompetitorsChangePerRace ? stringMessages.actionContinueToBoatAssignment() : stringMessages.save(), validator); this.errorReporter = errorReporter; this.stringMessages = stringMessages; - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.raceColumnName = raceColumnName; this.fleetName = fleetName; fleetNameWithCompetitors = findCompetitorsFromTheSameRaceColumn(fleets); @@ -177,7 +177,7 @@ public class RaceLogCompetitorRegistrationDialog extends AbstractCompetitorRegis }; for (final Entry>> fleetNameAndCallback : callbacksForFleetNames .entrySet()) { - sailingService.getCompetitorRegistrationsForRace(leaderboardName, raceColumnName, + sailingServiceWrite.getCompetitorRegistrationsForRace(leaderboardName, raceColumnName, fleetNameAndCallback.getKey(), fleetNameAndCallback.getValue()); } } @@ -203,9 +203,9 @@ public class RaceLogCompetitorRegistrationDialog extends AbstractCompetitorRegis private void getRegisteredCompetitors(AsyncCallback> callback) { if (competitorRegistrationsPanel.showOnlyCompetitorsOfLog()) { - sailingService.getCompetitorRegistrationsInRaceLog(leaderboardName, raceColumnName, fleetName, extractCompetitorDTOFromCompetitorAndBoatDTO(callback)); + sailingServiceWrite.getCompetitorRegistrationsInRaceLog(leaderboardName, raceColumnName, fleetName, extractCompetitorDTOFromCompetitorAndBoatDTO(callback)); } else { - sailingService.getCompetitorRegistrationsForRace(leaderboardName, raceColumnName, fleetName, extractCompetitorDTOFromCompetitorAndBoatDTO(callback)); + sailingServiceWrite.getCompetitorRegistrationsForRace(leaderboardName, raceColumnName, fleetName, extractCompetitorDTOFromCompetitorAndBoatDTO(callback)); } } @@ -224,7 +224,7 @@ public class RaceLogCompetitorRegistrationDialog extends AbstractCompetitorRegis } private void setupCompetitorRegistationsOnRaceCheckbox() { - sailingService.areCompetitorRegistrationsEnabledForRace(leaderboardName, raceColumnName, fleetName, + sailingServiceWrite.areCompetitorRegistrationsEnabledForRace(leaderboardName, raceColumnName, fleetName, new AsyncCallback() { @Override public void onSuccess(Boolean isEnabled) { @@ -259,7 +259,7 @@ public class RaceLogCompetitorRegistrationDialog extends AbstractCompetitorRegis @Override public void ok(Void editedObject) { if (getOrCreateCompetitorRegistrationInRaceLogCheckBox(stringMessages).getValue()) { - sailingService.enableCompetitorRegistrationsForRace(leaderboardName, + sailingServiceWrite.enableCompetitorRegistrationsForRace(leaderboardName, raceColumnName, fleetName, new AsyncCallback() { @Override public void onSuccess(Void isEnabled) { @@ -277,7 +277,7 @@ public class RaceLogCompetitorRegistrationDialog extends AbstractCompetitorRegis }); } else { - sailingService.disableCompetitorRegistrationsForRace(leaderboardName, + sailingServiceWrite.disableCompetitorRegistrationsForRace(leaderboardName, raceColumnName, fleetName, new AsyncCallback() { @Override public void onSuccess(Void isEnabled) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogCourseManagementWidget.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogCourseManagementWidget.java index bf85dae7b0a..a7958726e0a 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogCourseManagementWidget.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogCourseManagementWidget.java @@ -11,6 +11,7 @@ import com.google.gwt.user.client.ui.Button; import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveLegImpl; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.MarkDTO; import com.sap.sailing.gwt.ui.shared.RaceCourseDTO; @@ -27,10 +28,10 @@ public class RaceLogCourseManagementWidget extends CourseManagementWidget { private final String fleetName; private final Button removeMark; - public RaceLogCourseManagementWidget(final SailingServiceAsync sailingService, final ErrorReporter errorReporter, + public RaceLogCourseManagementWidget(final SailingServiceWriteAsync sailingServiceWrite, final ErrorReporter errorReporter, final StringMessages stringMessages, final String leaderboardName, final String raceColumnName, final String fleetName, final UserService userService) { - super(sailingService, errorReporter, stringMessages, userService, /* always show ORC OCS leg data actions */ ()->true); + super(sailingServiceWrite, errorReporter, stringMessages, userService, /* always show ORC OCS leg data actions */ ()->true); this.leaderboardName = leaderboardName; this.raceColumnName = raceColumnName; this.fleetName = fleetName; @@ -42,7 +43,7 @@ public class RaceLogCourseManagementWidget extends CourseManagementWidget { new DataEntryDialog.DialogCallback() { @Override public void ok(MarkDTO mark) { - sailingService.addMarkToRegattaLog(leaderboardName, mark, new AsyncCallback() { + sailingServiceWrite.addMarkToRegattaLog(leaderboardName, mark, new AsyncCallback() { @Override public void onSuccess(Void result) { refreshMarks(); @@ -68,7 +69,7 @@ public class RaceLogCourseManagementWidget extends CourseManagementWidget { public void onClick(ClickEvent event) { Set marksToRemove = marks.getSelectionModel().getSelectedSet(); for (final MarkDTO markToRemove : marksToRemove) { - sailingService.revokeMarkDefinitionEventInRegattaLog(leaderboardName, markToRemove, + sailingServiceWrite.revokeMarkDefinitionEventInRegattaLog(leaderboardName, markToRemove, new AsyncCallback() { @Override @@ -96,7 +97,7 @@ public class RaceLogCourseManagementWidget extends CourseManagementWidget { new DataEntryDialog.DialogCallback>() { @Override public void ok(Pair positionAndTimePoint) { - sailingService.pingMark(leaderboardName, markDTO, + sailingServiceWrite.pingMark(leaderboardName, markDTO, positionAndTimePoint.getB(), positionAndTimePoint.getA(), new AsyncCallback() { @Override public void onSuccess(Void result) { @@ -124,7 +125,7 @@ public class RaceLogCourseManagementWidget extends CourseManagementWidget { @Override protected void markSelectionChanged() { Set marksToRemove = marks.getSelectionModel().getSelectedSet(); - sailingService.checkIfMarksAreUsedInOtherRaceLogs(leaderboardName, raceColumnName, fleetName, marksToRemove, + sailingServiceWrite.checkIfMarksAreUsedInOtherRaceLogs(leaderboardName, raceColumnName, fleetName, marksToRemove, new AsyncCallback>() { @Override public void onSuccess(Pair result) { @@ -151,7 +152,7 @@ public class RaceLogCourseManagementWidget extends CourseManagementWidget { } private void refreshORCPerformanceCurveLegs() { - sailingService.getORCPerformanceCurveLegInfo(leaderboardName, raceColumnName, fleetName, + sailingServiceWrite.getORCPerformanceCurveLegInfo(leaderboardName, raceColumnName, fleetName, new AsyncCallback>() { @Override public void onSuccess(Map result) { @@ -166,7 +167,7 @@ public class RaceLogCourseManagementWidget extends CourseManagementWidget { } private void refreshCourse() { - sailingService.getLastCourseDefinitionInRaceLog(leaderboardName, raceColumnName, fleetName, + sailingServiceWrite.getLastCourseDefinitionInRaceLog(leaderboardName, raceColumnName, fleetName, new AsyncCallback() { @Override public void onSuccess(RaceCourseDTO result) { @@ -187,7 +188,7 @@ public class RaceLogCourseManagementWidget extends CourseManagementWidget { * the {@link #marks} table with the results. */ protected void refreshMarks() { - sailingService.getMarksInRegattaLog(leaderboardName, new AsyncCallback>() { + sailingServiceWrite.getMarksInRegattaLog(leaderboardName, new AsyncCallback>() { @Override public void onSuccess(Iterable result) { marks.refresh(result); @@ -203,6 +204,6 @@ public class RaceLogCourseManagementWidget extends CourseManagementWidget { @Override protected LegGeometrySupplier getLegGeometrySupplier() { return (zeroBasedLegIndices, legTypes, callback)-> - sailingService.getLegGeometry(leaderboardName, raceColumnName, fleetName, zeroBasedLegIndices, legTypes, callback); + sailingServiceWrite.getLegGeometry(leaderboardName, raceColumnName, fleetName, zeroBasedLegIndices, legTypes, callback); } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingCourseDefinitionDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingCourseDefinitionDialog.java index 0ce6cb559ba..be5692f0d54 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingCourseDefinitionDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceLogTrackingCourseDefinitionDialog.java @@ -12,7 +12,7 @@ import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.PassingInstruction; import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveLegImpl; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.ControlPointDTO; import com.sap.sse.common.Util.Pair; @@ -50,7 +50,7 @@ public class RaceLogTrackingCourseDefinitionDialog extends } } - public RaceLogTrackingCourseDefinitionDialog(final SailingServiceAsync sailingService, + public RaceLogTrackingCourseDefinitionDialog(final SailingServiceWriteAsync sailingServiceWrite, final StringMessages stringMessages, final ErrorReporter errorReporter, final String leaderboardName, final String raceColumnName, final String fleetName, DialogCallback callback, final UserService userService) { @@ -69,7 +69,7 @@ public class RaceLogTrackingCourseDefinitionDialog extends }, callback); this.stringMessages = stringMessages; - courseManagementWidget = new RaceLogCourseManagementWidget(sailingService, errorReporter, stringMessages, + courseManagementWidget = new RaceLogCourseManagementWidget(sailingServiceWrite, errorReporter, stringMessages, leaderboardName, raceColumnName, fleetName, userService); priorityBox = createIntegerBox(/* default priority: race officer */ 1, /* visibleLength */ 1); refreshButton = new Button(stringMessages.refresh()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceOrRegattaImportCompetitorCallback.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceOrRegattaImportCompetitorCallback.java index 75ddbdd25c7..cc463b2217d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceOrRegattaImportCompetitorCallback.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceOrRegattaImportCompetitorCallback.java @@ -3,16 +3,16 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.Set; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.ErrorReporter; public class RaceOrRegattaImportCompetitorCallback extends ImportCompetitorCallback { private final CompetitorRegistrationsPanel registrationsDialog; - public RaceOrRegattaImportCompetitorCallback(CompetitorRegistrationsPanel registrationsDialog, SailingServiceAsync sailingService, ErrorReporter errorReporter, + public RaceOrRegattaImportCompetitorCallback(CompetitorRegistrationsPanel registrationsDialog, SailingServiceWriteAsync sailingServiceWrite, ErrorReporter errorReporter, StringMessages stringMessages) { - super(sailingService, errorReporter, stringMessages); + super(sailingServiceWrite, errorReporter, stringMessages); this.registrationsDialog = registrationsDialog; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceSlotSelectionPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceSlotSelectionPanel.java index 92196eba19c..076cf2a26f2 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceSlotSelectionPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceSlotSelectionPanel.java @@ -18,7 +18,7 @@ import com.google.gwt.view.client.ListDataProvider; import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTO; import com.sap.sailing.gwt.ui.adminconsole.AbstractLeaderboardConfigPanel.RaceColumnDTOAndFleetDTOWithNameBasedEquality; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTOWithSecurity; import com.sap.sse.common.Util.Triple; @@ -58,7 +58,7 @@ public class RaceSlotSelectionPanel extends HorizontalPanel { private final RefreshableSingleSelectionModel leaderboardSelectionModel; - public RaceSlotSelectionPanel(final SailingServiceAsync sailingService, final UserService userService, + public RaceSlotSelectionPanel(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final StringMessages stringMessages, final ErrorReporter errorReporter, final boolean multiSelection, Iterable availableLeaderboards, RaceColumnDTOAndFleetDTOWithNameBasedEquality preselected) { final Resources tableRes = GWT.create(AdminConsoleTableResources.class); @@ -136,7 +136,7 @@ public class RaceSlotSelectionPanel extends HorizontalPanel { filteredLeaderboardList.addDataDisplay(leaderboardTable); leaderboardSelectionModel.addSelectionChangeHandler(e->updateRaceColumnTableAfterLeaderboardSelectionChange()); raceColumnTable = new RaceTableWrapper>( - sailingService, stringMessages, errorReporter, multiSelection); + sailingServiceWrite, stringMessages, errorReporter, multiSelection); raceColumnTable.asWidget().ensureDebugId("RaceColumnInRaceSlotSelectionPanelTable"); final Grid tableGrid = new Grid(2, 2); tableGrid.setWidget(0, 0, filterLeaderboardPanel); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceTableWrapper.java index 0b7ec5f5319..c76ad251363 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RaceTableWrapper.java @@ -16,7 +16,7 @@ import com.sap.sailing.gwt.settings.client.raceboard.RaceboardContextDefinition; import com.sap.sailing.gwt.ui.adminconsole.AbstractLeaderboardConfigPanel.RaceColumnDTOAndFleetDTOWithNameBasedEquality; import com.sap.sailing.gwt.ui.adminconsole.LeaderboardConfigPanel.AnchorCell; import com.sap.sailing.gwt.ui.adminconsole.LeaderboardConfigPanel.AnchorTemplates; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.util.NaturalComparator; import com.sap.sse.gwt.client.ErrorReporter; @@ -29,9 +29,9 @@ public class RaceTableWrapper() { @Override public boolean representSameEntity(RaceColumnDTOAndFleetDTOWithNameBasedEquality dto1, diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaBoatCertificatesPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaBoatCertificatesPanel.java index 8453a240b17..6d752fbdd2b 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaBoatCertificatesPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaBoatCertificatesPanel.java @@ -9,6 +9,7 @@ import com.sap.sailing.domain.common.RegattaIdentifier; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.orc.ORCCertificate; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sse.common.Util.Triple; @@ -28,19 +29,19 @@ import com.sap.sse.security.ui.client.UserService; public class RegattaBoatCertificatesPanel extends AbstractBoatCertificatesPanel { private final RegattaIdentifier regattaIdentifier; - public RegattaBoatCertificatesPanel(final SailingServiceAsync sailingService, final UserService userService, final RegattaDTO regatta, + public RegattaBoatCertificatesPanel(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final RegattaDTO regatta, final StringMessages stringMessages, final ErrorReporter errorReporter) { - super(sailingService, userService, /* objectToCheckUpdatePermissionFor */ regatta, stringMessages, errorReporter, + super(sailingServiceWrite, userService, /* objectToCheckUpdatePermissionFor */ regatta, stringMessages, errorReporter, /* context update permission check: */ ()->userService.hasPermission(regatta, DefaultActions.UPDATE), regatta.getName()); this.regattaIdentifier = regatta.getRegattaIdentifier(); refresh(); } @Override - protected void assignCertificates(SailingServiceAsync sailingService, + protected void assignCertificates(SailingServiceWriteAsync sailingServiceWrite, Map certificatesByBoatIdAsString, AsyncCallback> callback) { - sailingService.assignORCPerformanceCurveCertificates(regattaIdentifier, certificatesByBoatIdAsString, callback); + sailingServiceWrite.assignORCPerformanceCurveCertificates(regattaIdentifier, certificatesByBoatIdAsString, callback); } protected void getORCCertificateAssignemtnsByBoatIdAsString(SailingServiceAsync sailingService, diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaConfigImagesBarCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaConfigImagesBarCell.java index 6ee08a9a765..0e47610c156 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaConfigImagesBarCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaConfigImagesBarCell.java @@ -36,7 +36,7 @@ public class RegattaConfigImagesBarCell extends ImagesBarCell { GWT.log(getContext().getKey().getClass().getName()); if (getContext().getKey() instanceof RaceDTO) { final RaceDTO object = (RaceDTO) getContext().getKey(); - final TrackedRaceStatusEnum status = object.status.status; + final TrackedRaceStatusEnum status = object.status==null?null:object.status.status; if (status != TrackedRaceStatusEnum.ERROR && status != TrackedRaceStatusEnum.REMOVED && status != TrackedRaceStatusEnum.FINISHED) { result.add(new ImageSpec(ACTION_STOP_TRACKING, stringMessages.stopTracking(), diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaDetailsComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaDetailsComposite.java index f72b4a85d27..21fcf1d2fd5 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaDetailsComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaDetailsComposite.java @@ -36,7 +36,7 @@ import com.sap.sailing.domain.common.dto.FleetDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTO; import com.sap.sailing.domain.common.dto.RaceColumnInSeriesDTO; import com.sap.sailing.gwt.ui.client.RegattaRefresher; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.leaderboard.RankingMetricTypeFormatter; import com.sap.sailing.gwt.ui.leaderboard.ScoringSchemeTypeFormatter; @@ -59,7 +59,7 @@ public class RegattaDetailsComposite extends Composite { private final CaptionPanel mainPanel; - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final ErrorReporter errorReporter; private final StringMessages stringMessages; private final RegattaRefresher regattaRefresher; @@ -87,10 +87,10 @@ public class RegattaDetailsComposite extends Composite { private static AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class); - public RegattaDetailsComposite(final SailingServiceAsync sailingService, final UserService userService, + public RegattaDetailsComposite(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final RegattaRefresher regattaRefresher, final ErrorReporter errorReporter, final StringMessages stringMessages) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.regattaRefresher = regattaRefresher; this.errorReporter = errorReporter; this.stringMessages = stringMessages; @@ -148,7 +148,7 @@ public class RegattaDetailsComposite extends Composite { public void onClick(ClickEvent event) { RegistrationLinkWithQRCode registrationLinkWithQRCode = new RegistrationLinkWithQRCode(); registrationLinkWithQRCode.setSecret(regatta.registrationLinkSecret); - sailingService.getMailType(new AsyncCallback() { + sailingServiceWrite.getMailType(new AsyncCallback() { @Override public void onFailure(Throwable caught) { logger.log(Level.SEVERE, "Could not determine MailInvitationType", caught); @@ -156,7 +156,7 @@ public class RegattaDetailsComposite extends Composite { @Override public void onSuccess(MailInvitationType result) { - RegistrationLinkWithQRCodeDialog dialog = new RegistrationLinkWithQRCodeDialog(sailingService, + RegistrationLinkWithQRCodeDialog dialog = new RegistrationLinkWithQRCodeDialog(sailingServiceWrite, stringMessages, regatta.getName(), registrationLinkWithQRCode, new DialogCallback() { @Override @@ -292,7 +292,7 @@ public class RegattaDetailsComposite extends Composite { actionsColumn.addAction(SeriesConfigImagesBarCell.ACTION_REMOVE, UPDATE, series -> { RegattaIdentifier identifier = new RegattaName(regatta.getName()); if (Window.confirm(stringMessages.reallyRemoveSeries(series.getName()))) { - sailingService.removeSeries(identifier, series.getName(), + sailingServiceWrite.removeSeries(identifier, series.getName(), new MarkedAsyncCallback(new AsyncCallback() { @Override public void onFailure(Throwable cause) { @@ -389,7 +389,7 @@ public class RegattaDetailsComposite extends Composite { } if (raceColumnsToRemove.isEmpty() || Window.confirm(stringMessages.reallyRemoveRace(racesToRemove.toString()))) { // first remove: - sailingService.removeRaceColumnsFromSeries(regattaIdentifier, series.getName(), raceColumnsToRemove, + sailingServiceWrite.removeRaceColumnsFromSeries(regattaIdentifier, series.getName(), raceColumnsToRemove, new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -400,7 +400,7 @@ public class RegattaDetailsComposite extends Composite { @Override public void onSuccess(Void v) { // when successfully removed, insert: - sailingService.addRaceColumnsToSeries(regattaIdentifier, series.getName(), raceColumnNamesToAddWithInsertIndex, + sailingServiceWrite.addRaceColumnsToSeries(regattaIdentifier, series.getName(), raceColumnNamesToAddWithInsertIndex, new AsyncCallback>() { @Override public void onFailure(Throwable caught) { @@ -418,7 +418,7 @@ public class RegattaDetailsComposite extends Composite { if (isMedalChanged || isFleetsCanRunInParallelChanged || seriesResultDiscardingThresholdsChanged || isStartsWithZeroScoreChanged || isFirstColumnIsNonDiscardableCarryForwardChanged || hasSplitFleetContiguousScoringChanged || seriesNameChanged || maximumNumberOfDiscardsChanged) { - sailingService.updateSeries(regattaIdentifier, series.getName(), seriesDescriptor.getSeriesName(), + sailingServiceWrite.updateSeries(regattaIdentifier, series.getName(), seriesDescriptor.getSeriesName(), seriesDescriptor.isMedal(), seriesDescriptor.isFleetsCanRunInParallel(), seriesDescriptor.getResultDiscardingThresholds(), seriesDescriptor.isStartsWithZeroScore(), seriesDescriptor.isFirstColumnIsNonDiscardableCarryForward(), diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardCreateDialog.java index b49f7b7efe6..966d3c10c28 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardCreateDialog.java @@ -17,16 +17,9 @@ public class RegattaLeaderboardCreateDialog extends RegattaLeaderboardDialog { super(stringMessages.createRegattaLeaderboard(), new LeaderboardDescriptor(), existingRegattas, stringMessages, errorReporter, new RegattaLeaderboardDialog.LeaderboardParameterValidator(stringMessages, existingLeaderboards), callback); - nameTextBox = createTextBox(null); - nameTextBox.ensureDebugId("NameTextBox"); - nameTextBox.setVisibleLength(50); - // the name of the regatta leaderboard will be derived from the selected regatta - nameTextBox.setEnabled(false); - displayNameTextBox = createTextBox(null); displayNameTextBox.ensureDebugId("DisplayNameTextBox"); displayNameTextBox.setVisibleLength(50); - regattaListBox = createSortedRegattaListBox(existingRegattas, null); regattaListBox.ensureDebugId("RegattaListBox"); regattaListBox.addChangeHandler(new ChangeHandler() { @@ -34,11 +27,11 @@ public class RegattaLeaderboardCreateDialog extends RegattaLeaderboardDialog { int selectedIndex = regattaListBox.getSelectedIndex(); if (selectedIndex > 0) { nameTextBox.setText(regattaListBox.getValue(selectedIndex)); + validateAndUpdate(); } adjustVisibilityOfResultDiscardingRuleComponent(); } }); discardThresholdBoxes = new DiscardThresholdBoxes(this, stringMessages); } - } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardDialog.java index 9d17c260a69..8a162d77862 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardDialog.java @@ -81,14 +81,12 @@ public abstract class RegattaLeaderboardDialog extends AbstractLeaderboardDialog protected ListBox createSortedRegattaListBox(Collection regattas, String preSelectedRegattaName) { ListBox result = createListBox(false); - // sort the regatta names List sortedRegattaNames = new ArrayList(); for (RegattaDTO regatta : existingRegattas) { sortedRegattaNames.add(regatta.getName()); } Collections.sort(sortedRegattaNames); - result.addItem(stringMessages.pleaseSelectARegatta()); int i=1; for (String regattaName : sortedRegattaNames) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardEditDialog.java index 61f1b3cc481..18a9ed41f1f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardEditDialog.java @@ -13,10 +13,7 @@ public class RegattaLeaderboardEditDialog extends RegattaLeaderboardDialog { DialogCallback callback) { super(stringConstants.editRegattaLeaderboard(), leaderboardDescriptor, existingRegattas, stringConstants, errorReporter, new RegattaLeaderboardDialog.LeaderboardParameterValidator(stringConstants, otherExistingLeaderboards), callback); - nameTextBox = createTextBox(leaderboardDescriptor.getName()); displayNameTextBox = createTextBox(leaderboardDescriptor.getDisplayName()); - nameTextBox.setEnabled(false); - nameTextBox.setVisibleLength(50); displayNameTextBox.setVisibleLength(50); regattaListBox = createSortedRegattaListBox(existingRegattas, leaderboardDescriptor.getRegattaName()); regattaListBox.setEnabled(false); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardWithEliminationsCreateDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardWithEliminationsCreateDialog.java index 46a758ef442..11f87744291 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardWithEliminationsCreateDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardWithEliminationsCreateDialog.java @@ -7,7 +7,7 @@ import java.util.function.Consumer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; @@ -16,13 +16,14 @@ import com.sap.sse.security.ui.client.UserService; public class RegattaLeaderboardWithEliminationsCreateDialog extends RegattaLeaderboardWithEliminationsDialog { - public RegattaLeaderboardWithEliminationsCreateDialog(SailingServiceAsync sailingService, final UserService userService, + public RegattaLeaderboardWithEliminationsCreateDialog(SailingServiceWriteAsync sailingServiceWrite, final UserService userService, Collection existingLeaderboards, Collection existingRegattas, StringMessages stringMessages, ErrorReporter errorReporter, DialogCallback callback) { - super(sailingService, userService, stringMessages.createRegattaLeaderboard(), new LeaderboardDescriptorWithEliminations( + super(sailingServiceWrite, userService, stringMessages.createRegattaLeaderboard(), new LeaderboardDescriptorWithEliminations( new LeaderboardDescriptor(), Collections.emptySet()), existingRegattas, existingLeaderboards, stringMessages, errorReporter, new RegattaLeaderboardWithEliminationsDialog.LeaderboardParameterValidator(stringMessages, existingLeaderboards), callback); + nameTextBox.setEnabled(true); // a name can be selected during creation of a regatta leaderboard with eliminations } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardWithEliminationsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardWithEliminationsDialog.java index 53fbd4e6612..d92813b0219 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardWithEliminationsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardWithEliminationsDialog.java @@ -17,7 +17,7 @@ import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; @@ -29,7 +29,7 @@ public abstract class RegattaLeaderboardWithEliminationsDialog extends AbstractL protected final ListBox regattaLeaderboardsListBox; protected final Collection existingRegattas; protected final FlowPanel competitorEliminationPanelHolder; - protected final SailingServiceAsync sailingService; + protected final SailingServiceWriteAsync sailingServiceWrite; protected final UserService userService; private final Collection existingLeaderboards; protected final ErrorReporter errorReporter; @@ -80,21 +80,18 @@ public abstract class RegattaLeaderboardWithEliminationsDialog extends AbstractL } } - public RegattaLeaderboardWithEliminationsDialog(SailingServiceAsync sailingService, UserService userService, String title, + public RegattaLeaderboardWithEliminationsDialog(SailingServiceWriteAsync sailingServiceWrite, UserService userService, String title, LeaderboardDescriptorWithEliminations leaderboardDTO, Collection existingRegattas, final Collection existingLeaderboards, final StringMessages stringMessages, final ErrorReporter errorReporter, LeaderboardParameterValidator validator, DialogCallback callback) { super(title, leaderboardDTO, stringMessages, validator, callback); - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.userService = userService; this.stringMessages = stringMessages; this.errorReporter = errorReporter; this.existingRegattas = existingRegattas; this.existingLeaderboards = existingLeaderboards; - nameTextBox = createTextBox(null); - nameTextBox.ensureDebugId("NameTextBox"); - nameTextBox.setVisibleLength(50); displayNameTextBox = createTextBox(null); displayNameTextBox.ensureDebugId("DisplayNameTextBox"); displayNameTextBox.setVisibleLength(50); @@ -125,7 +122,7 @@ public abstract class RegattaLeaderboardWithEliminationsDialog extends AbstractL competitorEliminationPanelHolder.clear(); StrippedLeaderboardDTO selectedRegattaLeaderboard = getSelectedLeaderboard(); final CompetitorRegistrationsPanel[] competitorEliminationPanel = new CompetitorRegistrationsPanel[1]; - competitorEliminationPanel[0] = new CompetitorRegistrationsPanel(sailingService, userService, stringMessages, + competitorEliminationPanel[0] = new CompetitorRegistrationsPanel(sailingServiceWrite, userService, stringMessages, errorReporter, /* editable */ true, regattaLeaderboardsListBox.getValue(regattaLeaderboardsListBox.getSelectedIndex()), selectedRegattaLeaderboard.canBoatsOfCompetitorsChangePerRace, selectedRegattaLeaderboard.boatClassName, /* "validator" updates eliminatedCompetitors */ ()->eliminatedCompetitors = competitorEliminationPanel[0].getResult(), diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardWithEliminationsEditDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardWithEliminationsEditDialog.java index f8101ed215d..4674404f5b1 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardWithEliminationsEditDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLeaderboardWithEliminationsEditDialog.java @@ -6,7 +6,7 @@ import java.util.function.Consumer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; @@ -25,17 +25,15 @@ import com.sap.sse.security.ui.client.UserService; * */ public class RegattaLeaderboardWithEliminationsEditDialog extends RegattaLeaderboardWithEliminationsDialog { - public RegattaLeaderboardWithEliminationsEditDialog(SailingServiceAsync sailingService, final UserService userService, + public RegattaLeaderboardWithEliminationsEditDialog(SailingServiceWriteAsync sailingServiceWrite, final UserService userService, Collection otherExistingLeaderboards, Collection existingRegattas, LeaderboardDescriptorWithEliminations leaderboardDescriptor, StringMessages stringMessages, ErrorReporter errorReporter, DialogCallback callback) { - super(sailingService, userService, stringMessages.editRegattaLeaderboard(), leaderboardDescriptor, + super(sailingServiceWrite, userService, stringMessages.editRegattaLeaderboard(), leaderboardDescriptor, existingRegattas, otherExistingLeaderboards, stringMessages, errorReporter, new RegattaLeaderboardWithEliminationsDialog.LeaderboardParameterValidator(stringMessages, otherExistingLeaderboards), callback); - nameTextBox.setEnabled(false); - nameTextBox.setText(leaderboardDescriptor.getName()); for (int i=0; i>() { + sailingServiceWrite.getEliminatedCompetitors(nameTextBox.getValue(), new AsyncCallback>() { @Override public void onFailure(Throwable caught) { callback.onFailure(caught); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaListComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaListComposite.java index 000ef268338..e377252bfaf 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaListComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaListComposite.java @@ -35,7 +35,7 @@ import com.sap.sailing.domain.common.dto.CourseAreaDTO; import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.RegattasDisplayer; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; import com.sap.sailing.gwt.ui.leaderboard.RankingMetricTypeFormatter; @@ -73,7 +73,7 @@ public class RegattaListComposite extends Composite implements RegattasDisplayer private final CellTable regattaTable; private final Label noRegattasLabel; - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final RefreshableMultiSelectionModel refreshableRegattaMultiSelectionModel; private final ErrorReporter errorReporter; private final RegattaRefresher regattaRefresher; @@ -93,9 +93,9 @@ public class RegattaListComposite extends Composite implements RegattasDisplayer } @SuppressWarnings("unchecked") - public RegattaListComposite(final SailingServiceAsync sailingService, final UserService userService, + public RegattaListComposite(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, RegattaRefresher regattaRefresher, final ErrorReporter errorReporter, final StringMessages stringMessages) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.regattaRefresher = regattaRefresher; this.errorReporter = errorReporter; this.stringMessages = stringMessages; @@ -299,7 +299,7 @@ public class RegattaListComposite extends Composite implements RegattasDisplayer private void removeRegatta(final RegattaDTO regatta) { final RegattaIdentifier regattaIdentifier = new RegattaName(regatta.getName()); - sailingService.removeRegatta(regattaIdentifier, new MarkedAsyncCallback(new AsyncCallback() { + sailingServiceWrite.removeRegatta(regattaIdentifier, new MarkedAsyncCallback(new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Error trying to remove regatta " + regatta.getName() + ": " @@ -315,7 +315,7 @@ public class RegattaListComposite extends Composite implements RegattasDisplayer private void editRegatta(final RegattaDTO toBeEdited) { final Collection existingRegattas = getAllRegattas(); - sailingService.getEvents(new MarkedAsyncCallback>(new AsyncCallback>() { + sailingServiceWrite.getEvents(new MarkedAsyncCallback>(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { openEditRegattaDialog(toBeEdited, existingRegattas, Collections. emptyList()); @@ -331,7 +331,7 @@ public class RegattaListComposite extends Composite implements RegattasDisplayer private void openEditRegattaDialog(RegattaDTO regatta, Collection existingRegattas, List existingEvents) { RegattaWithSeriesAndFleetsDialog dialog = new RegattaWithSeriesAndFleetsEditDialog(regatta, existingRegattas, - existingEvents, /*correspondingEvent*/ null, sailingService, stringMessages, new DialogCallback() { + existingEvents, /*correspondingEvent*/ null, sailingServiceWrite, stringMessages, new DialogCallback() { @Override public void cancel() { } @@ -346,7 +346,7 @@ public class RegattaListComposite extends Composite implements RegattasDisplayer private void commitEditedRegatta(final RegattaDTO editedRegatta) { final RegattaIdentifier regattaName = new RegattaName(editedRegatta.getName()); - sailingService.updateRegatta(regattaName, editedRegatta.startDate, editedRegatta.endDate, + sailingServiceWrite.updateRegatta(regattaName, editedRegatta.startDate, editedRegatta.endDate, Util.mapToArrayList(editedRegatta.courseAreas, CourseAreaDTO::getId), editedRegatta.configuration, editedRegatta.buoyZoneRadiusInHullLengths, editedRegatta.useStartTimeInference, editedRegatta.controlTrackingFromStartAndFinishTimes, editedRegatta.autoRestartTrackingUponCompetitorSetChange, editedRegatta.registrationLinkSecret, @@ -369,7 +369,7 @@ public class RegattaListComposite extends Composite implements RegattasDisplayer public void run() { if (seriesIter.hasNext()) { final SeriesDTO series = seriesIter.next(); - sailingService.updateSeries(regattaName, series.getName(), series.getName(), series.isMedal(), + sailingServiceWrite.updateSeries(regattaName, series.getName(), series.getName(), series.isMedal(), series.isFleetsCanRunInParallel(), series.getDiscardThresholds(), series.isStartsWithZeroScore(), series.isFirstColumnIsNonDiscardableCarryForward(), series.hasSplitFleetContiguousScoring(), series.getMaximumNumberOfDiscards(), series.getFleets(), new MarkedAsyncCallback(new AsyncCallback() { @@ -411,8 +411,8 @@ public class RegattaListComposite extends Composite implements RegattasDisplayer } private void handleBoatCertificateAssignment(RegattaDTO regatta) { - BoatCertificateAssignmentDialog dialog = new BoatCertificateAssignmentDialog(sailingService, userService, - stringMessages, errorReporter, new RegattaBoatCertificatesPanel(sailingService, userService, regatta, stringMessages, errorReporter)); + BoatCertificateAssignmentDialog dialog = new BoatCertificateAssignmentDialog(sailingServiceWrite, userService, + stringMessages, errorReporter, new RegattaBoatCertificatesPanel(sailingServiceWrite, userService, regatta, stringMessages, errorReporter)); dialog.show(); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogAddDeviceMappingDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogAddDeviceMappingDialog.java index 6894ea5004b..ec5f730bac6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogAddDeviceMappingDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogAddDeviceMappingDialog.java @@ -26,6 +26,7 @@ import com.sap.sailing.gwt.ui.adminconsole.ItemToMapToDeviceSelectionPanel.Selec import com.sap.sailing.gwt.ui.client.DataEntryDialogWithDateTimeBox; import com.sap.sailing.gwt.ui.client.GwtUrlHelper; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.DeviceIdentifierDTO; import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO; @@ -55,7 +56,7 @@ public class RegattaLogAddDeviceMappingDialog extends DataEntryDialogWithDateTim protected Grid entryGrid; private String regattaRegisterSecret; - public RegattaLogAddDeviceMappingDialog(SailingServiceAsync sailingService, final UserService userService, final ErrorReporter errorReporter, + public RegattaLogAddDeviceMappingDialog(SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final ErrorReporter errorReporter, final StringMessages stringMessages, String leaderboardName, String regattaRegisterSecret, final MailInvitationType mailInvitationType, DialogCallback callback, final DeviceMappingDTO mapping) { @@ -88,7 +89,7 @@ public class RegattaLogAddDeviceMappingDialog extends DataEntryDialogWithDateTim } }, true, callback); this.stringMessages = stringMessages; - this.sailingService = sailingService; + this.sailingService = sailingServiceWrite; this.regattaRegisterSecret = regattaRegisterSecret; from = createDateTimeBox(new Date(), Accuracy.SECONDS); from.setValue(null); @@ -96,7 +97,7 @@ public class RegattaLogAddDeviceMappingDialog extends DataEntryDialogWithDateTim to.setValue(null); deviceType = createListBox(false); - sailingService.getDeserializableDeviceIdentifierTypes(new AsyncCallback>() { + sailingServiceWrite.getDeserializableDeviceIdentifierTypes(new AsyncCallback>() { @Override public void onSuccess(List result) { String typeToPreselect = mapping != null ? mapping.deviceIdentifier.deviceType : null; @@ -117,7 +118,7 @@ public class RegattaLogAddDeviceMappingDialog extends DataEntryDialogWithDateTim } }); deviceId = createTextBox(""); - itemSelectionPanel = new ItemToMapToDeviceSelectionPanel(sailingService, userService, stringMessages, errorReporter, + itemSelectionPanel = new ItemToMapToDeviceSelectionPanel(sailingServiceWrite, userService, stringMessages, errorReporter, new SelectionChangedHandler() { @Override public void onSelectionChange(MarkDTO mark) { @@ -163,7 +164,7 @@ public class RegattaLogAddDeviceMappingDialog extends DataEntryDialogWithDateTim qrWidget.generateQRCode(); } }); - sailingService.getEventsForLeaderboard(leaderboardName, new AsyncCallback>() { + sailingServiceWrite.getEventsForLeaderboard(leaderboardName, new AsyncCallback>() { @Override public void onSuccess(Collection result) { events.addItems(result); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogBoatRegistrationDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogBoatRegistrationDialog.java index b58379ab30d..57af8495e85 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogBoatRegistrationDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogBoatRegistrationDialog.java @@ -8,6 +8,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.dialog.DataEntryDialog; @@ -21,17 +22,17 @@ public class RegattaLogBoatRegistrationDialog extends DataEntryDialog> callback) { super(stringMessages.registerBoats(), /* messsage */null, stringMessages.save(), stringMessages.cancel(), /* validator */ null, callback); this.errorReporter = errorReporter; this.stringMessages = stringMessages; - this.sailingService = sailingService; + this.sailingService = sailingServiceWrite; this.leaderboardName = leaderboardName; this.canBoatsOfCompetitorsChangePerRace = canBoatsOfCompetitorsChangePerRace; - this.boatRegistrationsPanel = new BoatRegistrationsPanel(sailingService, userService, stringMessages, errorReporter, editable, leaderboardName, + this.boatRegistrationsPanel = new BoatRegistrationsPanel(sailingServiceWrite, userService, stringMessages, errorReporter, editable, leaderboardName, canBoatsOfCompetitorsChangePerRace, boatClass, ()->validateAndUpdate(), getRegisteredBoatsRetriever(), /* restrictPoolToLeaderboard */ false); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogCompetitorRegistrationDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogCompetitorRegistrationDialog.java index 2667b67410c..836adcced19 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogCompetitorRegistrationDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogCompetitorRegistrationDialog.java @@ -7,25 +7,25 @@ import java.util.function.Consumer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.dto.CompetitorDTO; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.security.ui.client.UserService; public class RegattaLogCompetitorRegistrationDialog extends AbstractCompetitorRegistrationDialog { - public RegattaLogCompetitorRegistrationDialog(String boatClass, SailingServiceAsync sailingService, final UserService userService, + public RegattaLogCompetitorRegistrationDialog(String boatClass, SailingServiceWriteAsync sailingServiceWrite, final UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, boolean editable, String leaderboardName, boolean canBoatsOfCompetitorsChangePerRace, com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback> callback) { - this(boatClass, sailingService, userService, stringMessages, errorReporter, editable, leaderboardName, + this(boatClass, sailingServiceWrite, userService, stringMessages, errorReporter, editable, leaderboardName, canBoatsOfCompetitorsChangePerRace, /* validator */ null, callback); } - public RegattaLogCompetitorRegistrationDialog(String boatClass, SailingServiceAsync sailingService, final UserService userService, + public RegattaLogCompetitorRegistrationDialog(String boatClass, SailingServiceWriteAsync sailingServiceWrite, final UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, boolean editable, String leaderboardName, boolean canBoatsOfCompetitorsChangePerRace, Validator> validator, com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback> callback) { - super(sailingService, userService, stringMessages, errorReporter, editable, callback, leaderboardName, + super(sailingServiceWrite, userService, stringMessages, errorReporter, editable, callback, leaderboardName, canBoatsOfCompetitorsChangePerRace, boatClass, stringMessages.save(), validator); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogFixesAddMappingsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogFixesAddMappingsDialog.java index d625ca2ab92..e032548379f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogFixesAddMappingsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogFixesAddMappingsDialog.java @@ -2,7 +2,7 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.Collection; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO; import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO; @@ -12,11 +12,11 @@ import com.sap.sse.security.ui.client.UserService; public class RegattaLogFixesAddMappingsDialog extends AbstractRegattaLogFixesAddMappingsDialog { TrackFileImportWidget importWidget; - public RegattaLogFixesAddMappingsDialog(SailingServiceAsync sailingService, final UserService userService, + public RegattaLogFixesAddMappingsDialog(SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final ErrorReporter errorReporter, final StringMessages stringMessages, String leaderboardName, Collection importedDeviceIds, DialogCallback> callback) { - super(sailingService, userService, errorReporter, stringMessages, leaderboardName, callback); + super(sailingServiceWrite, userService, errorReporter, stringMessages, leaderboardName, callback); deviceIdTable.getDataProvider().getList().addAll(importedDeviceIds); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogImportFixesAndAddMappingsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogImportFixesAndAddMappingsDialog.java index 7e44a438c81..e9741756190 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogImportFixesAndAddMappingsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogImportFixesAndAddMappingsDialog.java @@ -2,7 +2,7 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.Collection; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO; import com.sap.sse.gwt.client.ErrorReporter; @@ -11,11 +11,11 @@ import com.sap.sse.security.ui.client.UserService; public class RegattaLogImportFixesAndAddMappingsDialog extends AbstractRegattaLogFixesAddMappingsDialog { TrackFileImportWidget importWidget; - public RegattaLogImportFixesAndAddMappingsDialog(SailingServiceAsync sailingService, final UserService userService, + public RegattaLogImportFixesAndAddMappingsDialog(SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final ErrorReporter errorReporter, final StringMessages stringMessages, String leaderboardName, DialogCallback> callback) { - super(sailingService, userService, errorReporter, stringMessages, leaderboardName, callback); - importWidget = new TrackFileImportWidget(deviceIdTable, stringMessages, sailingService, errorReporter); + super(sailingServiceWrite, userService, errorReporter, stringMessages, leaderboardName, callback); + importWidget = new TrackFileImportWidget(deviceIdTable, stringMessages, sailingServiceWrite, errorReporter); setImportWidget(importWidget); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogImportSensorDataAndAddMappingsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogImportSensorDataAndAddMappingsDialog.java index 869ca9f5e87..24d0013e08e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogImportSensorDataAndAddMappingsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogImportSensorDataAndAddMappingsDialog.java @@ -2,7 +2,7 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.Collection; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.TypedDeviceMappingDTO; import com.sap.sse.gwt.client.ErrorReporter; @@ -12,11 +12,11 @@ public class RegattaLogImportSensorDataAndAddMappingsDialog extends AbstractRega private final SensorDataImportWidget importWidget; - public RegattaLogImportSensorDataAndAddMappingsDialog(SailingServiceAsync sailingService, final UserService userService, + public RegattaLogImportSensorDataAndAddMappingsDialog(SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final ErrorReporter errorReporter, final StringMessages stringMessages, String leaderboardName, DialogCallback> callback) { - super(sailingService, userService, errorReporter, stringMessages, leaderboardName, callback); - this.importWidget = new SensorDataImportWidget(deviceIdTable, stringMessages, sailingService, errorReporter); + super(sailingServiceWrite, userService, errorReporter, stringMessages, leaderboardName, callback); + this.importWidget = new SensorDataImportWidget(deviceIdTable, stringMessages, sailingServiceWrite, errorReporter); setImportWidget(importWidget); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogSensorDataAddMappingsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogSensorDataAddMappingsDialog.java index 25e48d6a11a..3a297d50496 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogSensorDataAddMappingsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogSensorDataAddMappingsDialog.java @@ -2,7 +2,7 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.Collection; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO; import com.sap.sailing.gwt.ui.shared.TypedDeviceMappingDTO; @@ -13,11 +13,11 @@ public class RegattaLogSensorDataAddMappingsDialog extends AbstractRegattaLogSen private final String importerType; - public RegattaLogSensorDataAddMappingsDialog(final SailingServiceAsync sailingService, final UserService userService, + public RegattaLogSensorDataAddMappingsDialog(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final ErrorReporter errorReporter, final StringMessages stringMessages, String leaderboardName, Collection importedDeviceIds, String importerType, DialogCallback> callback) { - super(sailingService, userService, errorReporter, stringMessages, leaderboardName, callback); + super(sailingServiceWrite, userService, errorReporter, stringMessages, leaderboardName, callback); this.importerType = importerType; deviceIdTable.getDataProvider().getList().addAll(importedDeviceIds); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogTrackingDeviceMappingsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogTrackingDeviceMappingsDialog.java index 5223b66f7c4..711844ec335 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogTrackingDeviceMappingsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaLogTrackingDeviceMappingsDialog.java @@ -38,7 +38,7 @@ import com.google.gwt.user.client.ui.Widget; import com.google.gwt.view.client.CellPreviewEvent; import com.sap.sailing.domain.common.MailInvitationType; import com.sap.sailing.gwt.ui.client.MappableToDeviceFormatter; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO; @@ -63,7 +63,7 @@ public class RegattaLogTrackingDeviceMappingsDialog extends DataEntryDialog mappings = new ArrayList<>(); @@ -80,12 +80,12 @@ public class RegattaLogTrackingDeviceMappingsDialog extends DataEntryDialog callback) { super(stringMessages.mapDevices(), /*message*/ null, stringMessages.ok(), stringMessages.cancel(), /*validator*/ null, callback); this.stringMessages = stringMessages; - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.userService = userService; this.errorReporter = errorReporter; this.regattaRegistrationSecret = regattaRegistrationSecret; @@ -123,7 +123,7 @@ public class RegattaLogTrackingDeviceMappingsDialog extends DataEntryDialog() { @Override public void onCellPreview(CellPreviewEvent event) { @@ -286,7 +286,7 @@ public class RegattaLogTrackingDeviceMappingsDialog extends DataEntryDialog>() { + sailingServiceWrite.getDeviceMappings(leaderboardName, new AsyncCallback>() { @Override public void onSuccess(List result) { busyIndicator.setBusy(false); @@ -304,7 +304,7 @@ public class RegattaLogTrackingDeviceMappingsDialog extends DataEntryDialog() { + sailingServiceWrite.getMailType(new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -313,12 +313,12 @@ public class RegattaLogTrackingDeviceMappingsDialog extends DataEntryDialog() { @Override public void ok(final DeviceMappingDTO mapping) { - sailingService.addDeviceMappingToRegattaLog(leaderboardName, mapping, + sailingServiceWrite.addDeviceMappingToRegattaLog(leaderboardName, mapping, new AsyncCallback() { @Override public void onSuccess(Void result) { @@ -344,12 +344,12 @@ public class RegattaLogTrackingDeviceMappingsDialog extends DataEntryDialog>() { @Override public void ok(Collection editedObject) { for (DeviceMappingDTO mapping : editedObject) { - sailingService.addDeviceMappingToRegattaLog(leaderboardName, mapping, + sailingServiceWrite.addDeviceMappingToRegattaLog(leaderboardName, mapping, new AsyncCallback() { @Override public void onSuccess(Void result) { @@ -371,12 +371,12 @@ public class RegattaLogTrackingDeviceMappingsDialog extends DataEntryDialog>() { @Override public void ok(Collection editedObject) { for (TypedDeviceMappingDTO mapping : editedObject) { - sailingService.addTypedDeviceMappingToRegattaLog(leaderboardName, mapping, new AsyncCallback() { + sailingServiceWrite.addTypedDeviceMappingToRegattaLog(leaderboardName, mapping, new AsyncCallback() { @Override public void onSuccess(Void result) { RegattaLogTrackingDeviceMappingsDialog.this.refresh(); @@ -405,7 +405,7 @@ public class RegattaLogTrackingDeviceMappingsDialog extends DataEntryDialog() { @Override public void ok(java.util.Date editedObject) { - sailingService.closeOpenEndedDeviceMapping(leaderboardName, dto, editedObject, + sailingServiceWrite.closeOpenEndedDeviceMapping(leaderboardName, dto, editedObject, new AsyncCallback() { @Override public void onSuccess(Void result) { @@ -425,7 +425,7 @@ public class RegattaLogTrackingDeviceMappingsDialog extends DataEntryDialog() { @Override public void onFailure(Throwable caught) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaManagementPanel.java index 7653ebe3d64..33db912c3b5 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/RegattaManagementPanel.java @@ -19,7 +19,7 @@ import com.sap.sailing.domain.common.RegattaIdentifier; import com.sap.sailing.gwt.ui.client.EventsRefresher; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.RegattasDisplayer; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.RegattaDTO; @@ -37,7 +37,7 @@ import com.sap.sse.security.ui.client.component.AccessControlledButtonPanel; */ public class RegattaManagementPanel extends SimplePanel implements RegattasDisplayer { - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final ErrorReporter errorReporter; private final StringMessages stringMessages; private final RegattaRefresher regattaRefresher; @@ -47,33 +47,29 @@ public class RegattaManagementPanel extends SimplePanel implements RegattasDispl private final RegattaDetailsComposite regattaDetailsComposite; private final UserService userService; - public RegattaManagementPanel(SailingServiceAsync sailingService, UserService userService, + public RegattaManagementPanel(SailingServiceWriteAsync sailingServiceWrite, UserService userService, ErrorReporter errorReporter, StringMessages stringMessages, RegattaRefresher regattaRefresher, EventsRefresher eventsRefresher) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.userService = userService; this.stringMessages = stringMessages; this.errorReporter = errorReporter; this.regattaRefresher = regattaRefresher; this.eventsRefresher = eventsRefresher; - final VerticalPanel mainPanel = new VerticalPanel(); setWidget(mainPanel); mainPanel.setWidth("100%"); - final CaptionPanel regattasPanel = new CaptionPanel(stringMessages.regattas()); mainPanel.add(regattasPanel); final VerticalPanel regattasContentPanel = new VerticalPanel(); regattasPanel.setContentWidget(regattasContentPanel); - - regattaListComposite = new RegattaListComposite(sailingService, userService, regattaRefresher, errorReporter, + regattaListComposite = new RegattaListComposite(sailingServiceWrite, userService, regattaRefresher, errorReporter, stringMessages); regattaListComposite.ensureDebugId("RegattaListComposite"); refreshableRegattaMultiSelectionModel = regattaListComposite.getRefreshableMultiSelectionModel(); final AccessControlledButtonPanel buttonPanel = new AccessControlledButtonPanel(userService, REGATTA); final Button create = buttonPanel.addCreateAction(stringMessages.addRegatta(), this::openCreateRegattaDialog); create.ensureDebugId("AddRegattaButton"); - final Button remove = buttonPanel.addRemoveAction(stringMessages.remove(), refreshableRegattaMultiSelectionModel, true, () -> { // unmodifiable collection can't be sent to the server. @@ -81,7 +77,6 @@ public class RegattaManagementPanel extends SimplePanel implements RegattasDispl removeRegattas(regattas); }); regattasContentPanel.add(buttonPanel); - refreshableRegattaMultiSelectionModel.addSelectionChangeHandler(new Handler() { @Override public void onSelectionChange(SelectionChangeEvent event) { @@ -113,8 +108,7 @@ public class RegattaManagementPanel extends SimplePanel implements RegattasDispl } }); regattasContentPanel.add(regattaListComposite); - - regattaDetailsComposite = new RegattaDetailsComposite(sailingService, userService, regattaRefresher, + regattaDetailsComposite = new RegattaDetailsComposite(sailingServiceWrite, userService, regattaRefresher, errorReporter, stringMessages); regattaDetailsComposite.ensureDebugId("RegattaDetailsComposite"); regattaDetailsComposite.setVisible(false); @@ -123,7 +117,7 @@ public class RegattaManagementPanel extends SimplePanel implements RegattasDispl protected void removeRegattas(Collection regattas) { if (!regattas.isEmpty()) { - sailingService.removeRegattas(regattas, new AsyncCallback() { + sailingServiceWrite.removeRegattas(regattas, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Error trying to remove the regattas:" + caught.getMessage()); @@ -139,7 +133,7 @@ public class RegattaManagementPanel extends SimplePanel implements RegattasDispl private void openCreateRegattaDialog() { final Collection existingRegattas = Collections.unmodifiableCollection(regattaListComposite.getAllRegattas()); - sailingService.getEvents(new AsyncCallback>() { + sailingServiceWrite.getEvents(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { openCreateRegattaDialog(existingRegattas, Collections.emptyList()); @@ -153,8 +147,8 @@ public class RegattaManagementPanel extends SimplePanel implements RegattasDispl } private void openCreateRegattaDialog(Collection existingRegattas, final List existingEvents) { - RegattaWithSeriesAndFleetsCreateDialog dialog = new RegattaWithSeriesAndFleetsCreateDialog(existingRegattas, existingEvents, /*eventToSelect*/ null, sailingService, stringMessages, - new CreateRegattaCallback(userService, sailingService, stringMessages, errorReporter, regattaRefresher, + RegattaWithSeriesAndFleetsCreateDialog dialog = new RegattaWithSeriesAndFleetsCreateDialog(existingRegattas, existingEvents, /*eventToSelect*/ null, sailingServiceWrite, stringMessages, + new CreateRegattaCallback(userService, sailingServiceWrite, stringMessages, errorReporter, regattaRefresher, eventsRefresher, existingEvents)); dialog.ensureDebugId("RegattaCreateDialog"); dialog.show(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ResultImportUrlsListComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ResultImportUrlsListComposite.java index 29567f242c0..5fdcb5de97c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ResultImportUrlsListComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ResultImportUrlsListComposite.java @@ -2,6 +2,7 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.List; import java.util.Set; + import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.user.client.rpc.AsyncCallback; @@ -13,7 +14,7 @@ import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.VerticalPanel; import com.sap.sailing.domain.common.security.SecuredDomainType; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.UrlDTO; import com.sap.sse.common.Util.Pair; @@ -31,7 +32,7 @@ import com.sap.sse.security.ui.client.component.AccessControlledButtonPanel; * @author Tim Hessenmüller (D062243) */ public class ResultImportUrlsListComposite extends Composite { - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final ErrorReporter errorReporter; private final StringMessages stringMessages; @@ -39,9 +40,9 @@ public class ResultImportUrlsListComposite extends Composite { private final ResultImportUrlsTableWrapper> table; - public ResultImportUrlsListComposite(SailingServiceAsync sailingServiceAsync, UserService userService, + public ResultImportUrlsListComposite(SailingServiceWriteAsync sailingServiceWriteAsync, UserService userService, ErrorReporter errorReporter, StringMessages stringMessages) { - this.sailingService = sailingServiceAsync; + this.sailingServiceWrite = sailingServiceWriteAsync; this.errorReporter = errorReporter; this.stringMessages = stringMessages; @@ -50,7 +51,7 @@ public class ResultImportUrlsListComposite extends Composite { final AccessControlledButtonPanel buttonPanel = new AccessControlledButtonPanel(userService, SecuredDomainType.RESULT_IMPORT_URL); - table = new ResultImportUrlsTableWrapper<>(sailingServiceAsync, userService, stringMessages, errorReporter); + table = new ResultImportUrlsTableWrapper<>(sailingServiceWriteAsync, userService, stringMessages, errorReporter); final Button add = buttonPanel.addCreateAction(stringMessages.add(), this::addUrl); add.setEnabled(false); @@ -80,7 +81,7 @@ public class ResultImportUrlsListComposite extends Composite { urlSampleLabel.setText(provider == null || provider.equals("null") ? "" : provider); } }); - sailingService.getUrlResultProviderNamesAndOptionalSampleURL(new AsyncCallback>>() { + sailingServiceWrite.getUrlResultProviderNamesAndOptionalSampleURL(new AsyncCallback>>() { @Override public void onSuccess(List> urlProviderNamesAndOptionalSampleURL) { urlProviderListBox.clear(); @@ -108,11 +109,11 @@ public class ResultImportUrlsListComposite extends Composite { } private void addUrl() { - new ResultImportUrlAddDialog(getSelectedProviderName(), sailingService, stringMessages, + new ResultImportUrlAddDialog(getSelectedProviderName(), sailingServiceWrite, stringMessages, new DataEntryDialog.DialogCallback() { @Override public void ok(UrlDTO url) { - sailingService.addResultImportUrl(getSelectedProviderName(), url, new AsyncCallback() { + sailingServiceWrite.addResultImportUrl(getSelectedProviderName(), url, new AsyncCallback() { @Override public void onSuccess(Void result) { Notification.notify(stringMessages.successfullyUpdatedResultImportUrls(), @@ -136,7 +137,7 @@ public class ResultImportUrlsListComposite extends Composite { private void removeUrls(Set set) { if (set != null && set.size() > 0) { String providerName = getSelectedProviderName(); - sailingService.removeResultImportURLs(providerName, set, new AsyncCallback() { + sailingServiceWrite.removeResultImportURLs(providerName, set, new AsyncCallback() { @Override public void onSuccess(Void result) { Notification.notify(stringMessages.successfullyUpdatedResultImportUrls(), NotificationType.INFO); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ResultImportUrlsTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ResultImportUrlsTableWrapper.java index cd8e5d18e2c..97be84010d6 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ResultImportUrlsTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ResultImportUrlsTableWrapper.java @@ -9,7 +9,7 @@ import com.google.gwt.user.cellview.client.TextColumn; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.sap.sailing.domain.common.security.SecuredDomainType; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.UrlDTO; import com.sap.sse.gwt.client.ErrorReporter; @@ -21,8 +21,8 @@ import com.sap.sse.security.ui.client.UserService; import com.sap.sse.security.ui.client.component.AccessControlledActionsColumn; import com.sap.sse.security.ui.client.component.DefaultActionsImagesBarCell; import com.sap.sse.security.ui.client.component.EditOwnershipDialog; -import com.sap.sse.security.ui.client.component.SecuredDTOOwnerColumn; import com.sap.sse.security.ui.client.component.EditOwnershipDialog.DialogConfig; +import com.sap.sse.security.ui.client.component.SecuredDTOOwnerColumn; import com.sap.sse.security.ui.client.component.editacl.EditACLDialog; public class ResultImportUrlsTableWrapper> extends TableWrapper { @@ -41,9 +41,9 @@ public class ResultImportUrlsTableWrapper listHandler = super.getColumnSortHandler(); TextColumn urlColumn = new AbstractSortableTextColumn(url -> url.getUrl()); @@ -76,7 +76,7 @@ public class ResultImportUrlsTableWrapper>() { + sailingServiceWrite.getResultImportUrls(providerName, new AsyncCallback>() { @Override public void onSuccess(List result) { ResultImportUrlsTableWrapper.super.refresh(result); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ShowCompetitorToBoatMappingsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ShowCompetitorToBoatMappingsDialog.java index cbdd1d94c17..5d203096592 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ShowCompetitorToBoatMappingsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/ShowCompetitorToBoatMappingsDialog.java @@ -6,13 +6,13 @@ import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.DialogBox; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.VerticalPanel; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.security.ui.client.UserService; public class ShowCompetitorToBoatMappingsDialog extends DialogBox { - public ShowCompetitorToBoatMappingsDialog(final SailingServiceAsync sailingService, final StringMessages stringMessages, + public ShowCompetitorToBoatMappingsDialog(final SailingServiceWriteAsync sailingServiceWrite, final StringMessages stringMessages, final ErrorReporter errorReporter, String leaderboardName, final String raceColumnName, final String fleetName, String raceName, UserService userService) { super(); @@ -26,7 +26,7 @@ public class ShowCompetitorToBoatMappingsDialog extends DialogBox { } }); VerticalPanel vPanel = new VerticalPanel(); - CompetitorToBoatMappingsViewPanel competitorPanel = new CompetitorToBoatMappingsViewPanel(sailingService, + CompetitorToBoatMappingsViewPanel competitorPanel = new CompetitorToBoatMappingsViewPanel(sailingServiceWrite, stringMessages, errorReporter, leaderboardName, raceColumnName, fleetName, userService); vPanel.add(new Label(stringMessages.race() + ": " + raceName)); vPanel.add(competitorPanel); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SmartphoneTrackingEventManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SmartphoneTrackingEventManagementPanel.java index 4da4b3411f0..5fc1eef19f7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SmartphoneTrackingEventManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SmartphoneTrackingEventManagementPanel.java @@ -52,7 +52,7 @@ import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.ui.client.LeaderboardsDisplayer; import com.sap.sailing.gwt.ui.client.LeaderboardsRefresher; import com.sap.sailing.gwt.ui.client.RegattaRefresher; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.racemap.RaceMapSettings; import com.sap.sailing.gwt.ui.shared.DeviceConfigurationDTO; @@ -102,20 +102,20 @@ public class SmartphoneTrackingEventManagementPanel private Map, Pair> raceWithStartAndEndOfTrackingTime = new HashMap<>(); private CaptionPanel importPanel; - public SmartphoneTrackingEventManagementPanel(SailingServiceAsync sailingService, UserService userService, + public SmartphoneTrackingEventManagementPanel(SailingServiceWriteAsync sailingServiceWrite, UserService userService, RegattaRefresher regattaRefresher, LeaderboardsRefresher leaderboardsRefresher, ErrorReporter errorReporter, StringMessages stringMessages) { - super(sailingService, userService, regattaRefresher, leaderboardsRefresher, errorReporter, + super(sailingServiceWrite, userService, regattaRefresher, leaderboardsRefresher, errorReporter, stringMessages, /* multiSelection */ true); // add upload panel importPanel = new CaptionPanel(stringMessages.importFixes()); importPanel.setVisible(false); VerticalPanel importContent = new VerticalPanel(); mainPanel.add(importPanel); - deviceIdentifierTable = new TrackFileImportDeviceIdentifierTableWrapper(sailingService, stringMessages, errorReporter); + deviceIdentifierTable = new TrackFileImportDeviceIdentifierTableWrapper(sailingServiceWrite, stringMessages, errorReporter); TrackFileImportWidget importWidget = new TrackFileImportWidget(deviceIdentifierTable, stringMessages, - sailingService, errorReporter); + sailingServiceWrite, errorReporter); importPanel.add(importContent); importContent.add(importWidget); importContent.add(deviceIdentifierTable); @@ -195,8 +195,7 @@ public class SmartphoneTrackingEventManagementPanel Boolean.valueOf(l1.canBoatsOfCompetitorsChangePerRace).compareTo(Boolean.valueOf(l2.canBoatsOfCompetitorsChangePerRace))); final HasPermissions type = SecuredDomainType.EVENT; final EditOwnershipDialog.DialogConfig configOwnership = EditOwnershipDialog - .create(userService.getUserManagementService(), type, leaderboard -> { - }, stringMessages); + .create(userService.getUserManagementService(), type, leaderboard -> listDataProvider.refresh(), stringMessages); final EditACLDialog.DialogConfig configACL = EditACLDialog.create( userService.getUserManagementService(), type, leaderboard -> leaderboard.getAccessControlList(), stringMessages); @@ -344,7 +343,7 @@ public class SmartphoneTrackingEventManagementPanel races.remove(t); Distance buoyZoneRadius = getSelectedRegatta() == null ? RaceMapSettings.DEFAULT_BUOY_ZONE_RADIUS : getSelectedRegatta().getCalculatedBuoyZoneRadius(); - new CopyCourseAndCompetitorsDialog(sailingService, errorReporter, stringMessages, races, leaderboardName, + new CopyCourseAndCompetitorsDialog(sailingServiceWrite, errorReporter, stringMessages, races, leaderboardName, buoyZoneRadius, new DialogCallback() { @Override public void ok(CourseAndCompetitorCopyOperation operation) { @@ -366,7 +365,7 @@ public class SmartphoneTrackingEventManagementPanel final String leaderboardName = t.getC().getName(); final String raceColumnName = t.getA().getName(); final String fleetName = t.getB().getName(); - new RaceLogTrackingCourseDefinitionDialog(sailingService, stringMessages, errorReporter, leaderboardName, + new RaceLogTrackingCourseDefinitionDialog(sailingServiceWrite, stringMessages, errorReporter, leaderboardName, raceColumnName, fleetName, new DialogCallback() { @Override public void cancel() { @@ -374,11 +373,11 @@ public class SmartphoneTrackingEventManagementPanel @Override public void ok(RaceLogTrackingCourseDefinitionDialog.Result waypointPairs) { - sailingService.addCourseDefinitionToRaceLog(leaderboardName, raceColumnName, fleetName, + sailingServiceWrite.addCourseDefinitionToRaceLog(leaderboardName, raceColumnName, fleetName, waypointPairs.getWaypoints(), waypointPairs.getPriority(), new AsyncCallback() { @Override public void onSuccess(Void result) { - sailingService.setORCPerformanceCurveLegInfo(leaderboardName, raceColumnName, fleetName, + sailingServiceWrite.setORCPerformanceCurveLegInfo(leaderboardName, raceColumnName, fleetName, waypointPairs.getORCLegData(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -416,13 +415,13 @@ public class SmartphoneTrackingEventManagementPanel RaceColumnDTOAndFleetDTOWithNameBasedEquality raceColumnDTOAndFleetDTO) { RegattaDTO regatta = getSelectedRegatta(); String boatClassName = regatta.boatClass.getName(); - RaceLogCompetitorRegistrationDialog dialog = new RaceLogCompetitorRegistrationDialog(boatClassName, sailingService, userService, stringMessages, + RaceLogCompetitorRegistrationDialog dialog = new RaceLogCompetitorRegistrationDialog(boatClassName, sailingServiceWrite, userService, stringMessages, errorReporter, editable, leaderboardName, canBoatsOfCompetitorsChangePerRace, raceColumnName, fleetName, raceColumnDTOAndFleetDTO.getA().getFleets(), new DialogCallback>() { @Override public void ok(final Set registeredCompetitors) { if (canBoatsOfCompetitorsChangePerRace) { - sailingService.getCompetitorAndBoatRegistrationsInRaceLog(leaderboardName, raceColumnName, fleetName, new AsyncCallback>() { + sailingServiceWrite.getCompetitorAndBoatRegistrationsInRaceLog(leaderboardName, raceColumnName, fleetName, new AsyncCallback>() { @Override public void onSuccess(Map existingCompetitorToBoatMappings) { // remove the competitors which has been removed in the first dialog (competitor selection) @@ -435,11 +434,11 @@ public class SmartphoneTrackingEventManagementPanel newCompetitorToBoatMappings.put(competitorDTO, null); } } - new CompetitorToBoatMappingsDialog(sailingService, stringMessages, + new CompetitorToBoatMappingsDialog(sailingServiceWrite, stringMessages, errorReporter, leaderboardName, newCompetitorToBoatMappings, new DialogCallback>() { @Override public void ok(final Map competitorToBoatMappings) { - sailingService.setCompetitorRegistrationsInRaceLog(leaderboardName, raceColumnName, + sailingServiceWrite.setCompetitorRegistrationsInRaceLog(leaderboardName, raceColumnName, fleetName, competitorToBoatMappings, new AsyncCallback() { @Override public void onSuccess(Void result) { @@ -467,7 +466,7 @@ public class SmartphoneTrackingEventManagementPanel for (final CompetitorDTO competitor : registeredCompetitors) { registeredCompetitorsWithBoat.add((CompetitorWithBoatDTO) competitor); } - sailingService.setCompetitorRegistrationsInRaceLog(leaderboardName, raceColumnName, + sailingServiceWrite.setCompetitorRegistrationsInRaceLog(leaderboardName, raceColumnName, fleetName, registeredCompetitorsWithBoat, new AsyncCallback() { @Override public void onSuccess(Void result) { @@ -533,7 +532,7 @@ public class SmartphoneTrackingEventManagementPanel racesToStopTracking.add(race.getRaceIdentifier()); } } - sailingService.stopTrackingRaces(racesToStopTracking, new MarkedAsyncCallback( + sailingServiceWrite.stopTrackingRaces(racesToStopTracking, new MarkedAsyncCallback( new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -611,7 +610,7 @@ public class SmartphoneTrackingEventManagementPanel raceColumnsAndFleets.add(new Triple(selectedLeaderboard.getName(), raceColumn.getName(), fleet.getName())); } } - sailingService.getTrackingTimes(raceColumnsAndFleets, + sailingServiceWrite.getTrackingTimes(raceColumnsAndFleets, new AsyncCallback, Pair>>() { @Override public void onFailure(Throwable caught) { @@ -636,7 +635,7 @@ public class SmartphoneTrackingEventManagementPanel trackedRacesListComposite.setRegattaFilterValue(selectedLeaderboard.regattaName); trackedRacesCaptionPanel.setVisible(true); } - sailingService.doesRegattaLogContainCompetitors(((StrippedLeaderboardDTO) leaderboardSelectionModel.getSelectedSet().toArray()[0]).getName(), new RegattaLogCallBack()); + sailingServiceWrite.doesRegattaLogContainCompetitors(((StrippedLeaderboardDTO) leaderboardSelectionModel.getSelectedSet().toArray()[0]).getName(), new RegattaLogCallBack()); } else { selectedLeaderBoardPanel.setVisible(false); trackedRacesCaptionPanel.setVisible(false); @@ -666,7 +665,7 @@ public class SmartphoneTrackingEventManagementPanel @Override public void ok(String prefix) { - sailingService.denoteForRaceLogTracking(leaderboard.getName(), prefix, new AsyncCallback() { + sailingServiceWrite.denoteForRaceLogTracking(leaderboard.getName(), prefix, new AsyncCallback() { @Override public void onSuccess(Void result) { loadAndRefreshLeaderboard(leaderboard.getName()); @@ -747,7 +746,7 @@ public class SmartphoneTrackingEventManagementPanel private void updateRegattaConfiguration(final RegattaDTO regatta, DeviceConfigurationDTO.RegattaConfigurationDTO configuration) { final RegattaIdentifier regattaIdentifier = new RegattaName(regatta.getName()); - sailingService.updateRegatta(regattaIdentifier, regatta.startDate, regatta.endDate, + sailingServiceWrite.updateRegatta(regattaIdentifier, regatta.startDate, regatta.endDate, Util.mapToArrayList(regatta.courseAreas, CourseAreaDTO::getId), configuration, regatta.buoyZoneRadiusInHullLengths, regatta.useStartTimeInference, regatta.controlTrackingFromStartAndFinishTimes, regatta.autoRestartTrackingUponCompetitorSetChange, regatta.registrationLinkSecret, @@ -767,7 +766,7 @@ public class SmartphoneTrackingEventManagementPanel } private void denoteForRaceLogTracking(final RaceColumnDTOAndFleetDTOWithNameBasedEquality t) { - sailingService.denoteForRaceLogTracking(t.getC().getName(), t.getA().getName(), t.getB().getName(), + sailingServiceWrite.denoteForRaceLogTracking(t.getC().getName(), t.getA().getName(), t.getB().getName(), new AsyncCallback() { @Override public void onSuccess(Boolean result) { @@ -784,7 +783,7 @@ public class SmartphoneTrackingEventManagementPanel } private void removeDenotation(final RaceColumnDTOAndFleetDTOWithNameBasedEquality t) { - sailingService.removeDenotationForRaceLogTracking(t.getC().getName(), t.getA().getName(), t.getB().getName(), + sailingServiceWrite.removeDenotationForRaceLogTracking(t.getC().getName(), t.getA().getName(), t.getB().getName(), new AsyncCallback() { @Override public void onSuccess(Void result) { @@ -824,7 +823,7 @@ public class SmartphoneTrackingEventManagementPanel leaderboardRaceColumnFleetNames .add(new Triple<>(leaderboard.getName(), raceColumn.getName(), fleet.getName())); } - sailingService.startRaceLogTracking(leaderboardRaceColumnFleetNames, trackWind, correctWindByDeclination, + sailingServiceWrite.startRaceLogTracking(leaderboardRaceColumnFleetNames, trackWind, correctWindByDeclination, new AsyncCallback() { @Override public void onSuccess(Void result) { @@ -841,12 +840,12 @@ public class SmartphoneTrackingEventManagementPanel } private void setStartTime(RaceColumnDTOAndFleetDTOWithNameBasedEquality t) { - new SetStartTimeDialog(sailingService, errorReporter, t.getC().getName(), t.getA().getName(), + new SetStartTimeDialog(sailingServiceWrite, errorReporter, t.getC().getName(), t.getA().getName(), t.getB().getName(), stringMessages, new DataEntryDialog.DialogCallback() { @Override public void ok(RaceLogSetStartTimeAndProcedureDTO editedObject) { - sailingService.setStartTimeAndProcedure(editedObject, new AsyncCallback() { + sailingServiceWrite.setStartTimeAndProcedure(editedObject, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(caught.getMessage()); @@ -871,11 +870,11 @@ public class SmartphoneTrackingEventManagementPanel } private void setEndTime(RaceColumnDTOAndFleetDTOWithNameBasedEquality t) { - new SetFinishingAndFinishedTimeDialog(sailingService, errorReporter, t.getC().getName(), t.getA().getName(), + new SetFinishingAndFinishedTimeDialog(sailingServiceWrite, errorReporter, t.getC().getName(), t.getA().getName(), t.getB().getName(), stringMessages, new DialogCallback() { @Override public void ok(RaceLogSetFinishingAndFinishTimeDTO editedObject) { - sailingService.setFinishingAndEndTime(editedObject, + sailingServiceWrite.setFinishingAndEndTime(editedObject, new AsyncCallback>() { @Override public void onFailure(Throwable caught) { @@ -905,11 +904,11 @@ public class SmartphoneTrackingEventManagementPanel } private void showSetTrackingTimesDialog(RaceColumnDTOAndFleetDTOWithNameBasedEquality t) { - new SetTrackingTimesDialog(sailingService, errorReporter, t.getC().getName(), t.getA().getName(), + new SetTrackingTimesDialog(sailingServiceWrite, errorReporter, t.getC().getName(), t.getA().getName(), t.getB().getName(), stringMessages, new DataEntryDialog.DialogCallback() { @Override public void ok(RaceLogSetTrackingTimesDTO editedObject) { - sailingService.setTrackingTimes(editedObject, new AsyncCallback(){ + sailingServiceWrite.setTrackingTimes(editedObject, new AsyncCallback(){ @Override public void onFailure(Throwable caught) { errorReporter.reportError("Error while setting tracking times: " + caught.getMessage()); @@ -936,7 +935,7 @@ public class SmartphoneTrackingEventManagementPanel final String raceColumnName = t.getA().getName(); final String fleetName = t.getB().getName(); final String raceName = LeaderboardNameConstants.DEFAULT_FLEET_NAME.equals(fleetName) ? raceColumnName : raceColumnName + ", " + fleetName; - ShowCompetitorToBoatMappingsDialog dialog = new ShowCompetitorToBoatMappingsDialog(sailingService, + ShowCompetitorToBoatMappingsDialog dialog = new ShowCompetitorToBoatMappingsDialog(sailingServiceWrite, stringMessages, errorReporter, selectedLeaderboardName, raceColumnName, fleetName, raceName, userService); dialog.center(); @@ -947,10 +946,10 @@ public class SmartphoneTrackingEventManagementPanel } private void openChooseEventDialogAndSendMails(final String leaderboardName) { - new InviteBuoyTenderDialog(stringMessages, sailingService, leaderboardName, errorReporter, new DialogCallback>() { + new InviteBuoyTenderDialog(stringMessages, sailingServiceWrite, leaderboardName, errorReporter, new DialogCallback>() { @Override public void ok(Triple result) { - sailingService.inviteBuoyTenderViaEmail(result.getB(), result.getA(), leaderboardName, result.getC(), + sailingServiceWrite.inviteBuoyTenderViaEmail(result.getB(), result.getA(), leaderboardName, result.getC(), null, stringMessages.playStoreBuoyPingerApp(), getLocaleInfo(), new AsyncCallback() { @@ -977,12 +976,12 @@ public class SmartphoneTrackingEventManagementPanel RegattaDTO regatta = getSelectedRegatta(); String boatClassName = regatta.boatClass.getName(); - new RegattaLogCompetitorRegistrationDialog(boatClassName, sailingService, userService, stringMessages, + new RegattaLogCompetitorRegistrationDialog(boatClassName, sailingServiceWrite, userService, stringMessages, errorReporter, /* editable */true, t.getName(), t.canBoatsOfCompetitorsChangePerRace, new DialogCallback>() { @Override public void ok(Set registeredCompetitors) { - sailingService.setCompetitorRegistrationsInRegattaLog(t.getName(), registeredCompetitors, + sailingServiceWrite.setCompetitorRegistrationsInRegattaLog(t.getName(), registeredCompetitors, new AsyncCallback() { @Override public void onSuccess(Void result) { @@ -1008,12 +1007,12 @@ public class SmartphoneTrackingEventManagementPanel RegattaDTO regatta = getSelectedRegatta(); String boatClassName = regatta.boatClass.getName(); - new RegattaLogBoatRegistrationDialog(boatClassName, sailingService, userService, stringMessages, + new RegattaLogBoatRegistrationDialog(boatClassName, sailingServiceWrite, userService, stringMessages, errorReporter, /* editable */true, t.getName(), t.canBoatsOfCompetitorsChangePerRace, new DialogCallback>() { @Override public void ok(Set registeredBoats) { - sailingService.setBoatRegistrationsInRegattaLog(t.getName(), registeredBoats, + sailingServiceWrite.setBoatRegistrationsInRegattaLog(t.getName(), registeredBoats, new AsyncCallback() { @Override public void onSuccess(Void result) { @@ -1038,7 +1037,7 @@ public class SmartphoneTrackingEventManagementPanel } private void handleDeviceMappings(StrippedLeaderboardDTOWithSecurity t) { - sailingService.getSecretForRegattaByName(t.getName(), new AsyncCallback() { + sailingServiceWrite.getSecretForRegattaByName(t.getName(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -1048,7 +1047,7 @@ public class SmartphoneTrackingEventManagementPanel @Override public void onSuccess(String secret) { - new RegattaLogTrackingDeviceMappingsDialog(sailingService, userService, stringMessages, errorReporter, + new RegattaLogTrackingDeviceMappingsDialog(sailingServiceWrite, userService, stringMessages, errorReporter, t.getName(), secret, new DialogCallback() { @Override public void ok(Void editedObject) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/StructureImportListComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/StructureImportListComposite.java index 3cb186c9feb..7f84c9fc969 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/StructureImportListComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/StructureImportListComposite.java @@ -7,7 +7,7 @@ import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; import com.google.gwt.user.cellview.client.TextColumn; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.RegattasDisplayer; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sse.common.util.NaturalComparator; @@ -26,10 +26,10 @@ public class StructureImportListComposite extends RegattaListComposite implement RegattaStructure getRegattaStructure(RegattaDTO regatta); } - public StructureImportListComposite(final SailingServiceAsync sailingService, final UserService userService, + public StructureImportListComposite(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, RegattaRefresher regattaRefresher, RegattaStructureProvider regattaStructureProvider, final ErrorReporter errorReporter, final StringMessages stringMessages) { - super(sailingService, userService, regattaRefresher, errorReporter, stringMessages); + super(sailingServiceWrite, userService, regattaRefresher, errorReporter, stringMessages); this.regattaStructureProvider = regattaStructureProvider; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/StructureImportManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/StructureImportManagementPanel.java index 707b2e832d6..3f936e5c3c0 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/StructureImportManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/StructureImportManagementPanel.java @@ -38,7 +38,7 @@ import com.sap.sailing.domain.common.dto.CourseAreaDTO; import com.sap.sailing.domain.common.impl.MeterDistance; import com.sap.sailing.gwt.ui.adminconsole.StructureImportListComposite.RegattaStructureProvider; import com.sap.sailing.gwt.ui.client.RegattaRefresher; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.EventAndRegattaDTO; import com.sap.sailing.gwt.ui.shared.EventDTO; @@ -55,7 +55,7 @@ import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; import com.sap.sse.security.ui.client.UserService; public class StructureImportManagementPanel extends SimplePanel implements RegattaStructureProvider { - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final ErrorReporter errorReporter; private final StringMessages stringMessages; private final RegattaRefresher regattaRefresher; @@ -97,19 +97,19 @@ public class StructureImportManagementPanel extends SimplePanel implements Regat */ private final Map regattaStructures; - public StructureImportManagementPanel(SailingServiceAsync sailingService, UserService userService, + public StructureImportManagementPanel(SailingServiceWriteAsync sailingServiceWrite, UserService userService, ErrorReporter errorReporter, StringMessages stringMessages, RegattaRefresher regattaRefresher, EventManagementPanel eventManagementPanel) { this.regattaDefaultsPerStructure = new HashMap<>(); this.regattaStructures = new HashMap<>(); this.eventManagementPanel = eventManagementPanel; this.busyIndicator = new SimpleBusyIndicator(); - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.errorReporter = errorReporter; this.stringMessages = stringMessages; this.regattaRefresher = regattaRefresher; - this.regattaListComposite = new StructureImportListComposite(this.sailingService, userService, - this.regattaRefresher, this, this.errorReporter, this.stringMessages); + this.regattaListComposite = new StructureImportListComposite(sailingServiceWrite, userService, regattaRefresher, + this, errorReporter, stringMessages); regattaListComposite.ensureDebugId("RegattaListComposite"); VerticalPanel mainPanel = new VerticalPanel(); @@ -223,7 +223,7 @@ public class StructureImportManagementPanel extends SimplePanel implements Regat }); grid.setWidget(0, 1, newEventBtn); editSeriesPanel.add(grid); - sailingService.getEvents(new AsyncCallback>() { + sailingServiceWrite.getEvents(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(stringMessages.errorTryingToGetEvents(caught.getMessage())); @@ -249,7 +249,7 @@ public class StructureImportManagementPanel extends SimplePanel implements Regat } private void openEventCreateDialog() { - EventCreateDialog dialog = new EventCreateDialog(existingEvents, Collections.emptyList(), sailingService, stringMessages, + EventCreateDialog dialog = new EventCreateDialog(existingEvents, Collections.emptyList(), sailingServiceWrite, stringMessages, new DialogCallback() { @Override public void cancel() { @@ -268,7 +268,7 @@ public class StructureImportManagementPanel extends SimplePanel implements Regat for (CourseAreaDTO courseAreaDTO : newEvent.venue.getCourseAreas()) { courseAreaNames.add(courseAreaDTO.getName()); } - sailingService.createEvent(newEvent.getName(), newEvent.getDescription(), newEvent.startDate, newEvent.endDate, + sailingServiceWrite.createEvent(newEvent.getName(), newEvent.getDescription(), newEvent.startDate, newEvent.endDate, newEvent.venue.getName(), newEvent.isPublic, courseAreaNames, newEvent.getOfficialWebsiteURL(), newEvent.getBaseURL(), newEvent.getSailorsInfoWebsiteURLs(), newEvent.getImages(), newEvent.getVideos(), newEvent.getLeaderboardGroupIds(), new AsyncCallback() { @@ -298,7 +298,7 @@ public class StructureImportManagementPanel extends SimplePanel implements Regat errorReporter.reportError(stringMessages.pleaseEnterNonEmptyUrl()); } else { busyIndicator.setBusy(true); - sailingService.getRegattas(jsonURL, new AsyncCallback>() { + sailingServiceWrite.getRegattas(jsonURL, new AsyncCallback>() { @Override public void onFailure(Throwable caught) { busyIndicator.setBusy(false); @@ -398,7 +398,7 @@ public class StructureImportManagementPanel extends SimplePanel implements Regat existingEvents.add(getSelectedEvent()); } DefaultRegattaCreateDialog dialog = new DefaultRegattaCreateDialog(existingEvents, regattaDefaultsPerStructure.get(regattaStructure), - sailingService, errorReporter, stringMessages, new DialogCallback() { + sailingServiceWrite, errorReporter, stringMessages, new DialogCallback() { @Override public void cancel() { } @@ -454,7 +454,7 @@ public class StructureImportManagementPanel extends SimplePanel implements Regat private void createRegattas(final Iterable selectedOriginalRegattasFromXRR, EventDTO newEvent) { eventManagementPanel.fillEvents(); - final Set regattaConfigurationsToCreate = new HashSet<>(); + final List regattaConfigurationsToCreate = new ArrayList<>(); for (RegattaDTO originalRegattaFromXRR : selectedOriginalRegattasFromXRR) { RegattaDTO cloneFromDefaults = new RegattaDTO(regattaDefaultsPerStructure.get(regattaStructures.get(originalRegattaFromXRR))); cloneFromDefaults.setName(originalRegattaFromXRR.getName()); @@ -469,7 +469,7 @@ public class StructureImportManagementPanel extends SimplePanel implements Regat } regattaConfigurationsToCreate.add(cloneFromDefaults); } - sailingService.createRegattaStructure(regattaConfigurationsToCreate, newEvent, + sailingServiceWrite.createRegattaStructure(regattaConfigurationsToCreate, newEvent, new AsyncCallback() { @Override public void onFailure(Throwable caught) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SwissTimingEventManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SwissTimingEventManagementPanel.java index 5d284e49768..ed461d3e009 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SwissTimingEventManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SwissTimingEventManagementPanel.java @@ -27,7 +27,7 @@ import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.ui.adminconsole.swisstiming.SwissTimingConnectionDialog; import com.sap.sailing.gwt.ui.adminconsole.swisstiming.SwissTimingConnectionTableWrapper; import com.sap.sailing.gwt.ui.client.RegattaRefresher; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationWithSecurityDTO; @@ -63,10 +63,10 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane private final List availableSwissTimingRaces = new ArrayList(); private final SwissTimingConnectionTableWrapper connectionsTable; - public SwissTimingEventManagementPanel(final SailingServiceAsync sailingService, UserService userService, + public SwissTimingEventManagementPanel(final SailingServiceWriteAsync sailingServiceWrite, UserService userService, ErrorReporter errorReporter, RegattaRefresher regattaRefresher, StringMessages stringConstants, final CellTableWithCheckboxResources tableResources) { - super(sailingService, userService, regattaRefresher, errorReporter, true, stringConstants); + super(sailingServiceWrite, userService, regattaRefresher, errorReporter, true, stringConstants); this.errorReporter = errorReporter; VerticalPanel mainPanel = new VerticalPanel(); this.setWidget(mainPanel); @@ -76,7 +76,7 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane VerticalPanel verticalPanel = new VerticalPanel(); captionPanelConnections.setContentWidget(verticalPanel); captionPanelConnections.setStyleName("bold"); - connectionsTable = new SwissTimingConnectionTableWrapper(userService, sailingService, stringConstants, + connectionsTable = new SwissTimingConnectionTableWrapper(userService, sailingServiceWrite, stringConstants, errorReporter, true, tableResources, () -> {}); connectionsTable.refreshSwissTimingConnectionList(); // Add button panel @@ -92,7 +92,7 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane new DialogCallback() { @Override public void ok(SwissTimingConfigurationWithSecurityDTO editedConnection) { - sailingService.createSwissTimingConfiguration(editedConnection.getName(), + sailingServiceWrite.createSwissTimingConfiguration(editedConnection.getName(), editedConnection.getJsonUrl(), editedConnection.getHostname(), editedConnection.getPort(), editedConnection.getUpdateURL(), editedConnection.getUpdateUsername(), editedConnection.getUpdatePassword(), @@ -118,7 +118,7 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane }, userService, errorReporter).show()); // Remove SwissTiming Connection buttonPanel.addRemoveAction(stringMessages.remove(), connectionsTable.getSelectionModel(), false, () -> { - sailingService.deleteSwissTimingConfigurations(connectionsTable.getSelectionModel().getSelectedSet(), + sailingServiceWrite.deleteSwissTimingConfigurations(connectionsTable.getSelectionModel().getSelectedSet(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -134,7 +134,7 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane }); // List Races in SwissTiming Connection final Button listRacesButton = buttonPanel.addUnsecuredAction(stringMessages.listRaces(), () -> { - fillRaces(sailingService); + fillRaces(sailingServiceWrite); }); listRacesButton.setEnabled(false); connectionsTable.getSelectionModel().addSelectionChangeHandler(e -> { @@ -377,10 +377,10 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane } - private void fillRaces(final SailingServiceAsync sailingService) { + private void fillRaces(final SailingServiceWriteAsync sailingServiceWrite) { final SwissTimingConfigurationWithSecurityDTO selectedObject = connectionsTable.getSelectionModel() .getSelectedSet().iterator().next(); - sailingService.getRacesOfSwissTimingEvent(selectedObject.getJsonUrl(), + sailingServiceWrite.getRacesOfSwissTimingEvent(selectedObject.getJsonUrl(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -402,7 +402,7 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane final SwissTimingConfigurationWithSecurityDTO updatedDTO = new SwissTimingConfigurationWithSecurityDTO( selectedObject, result.trackingDataHost, result.trackingDataPort, result.eventName); - sailingService.updateSwissTimingConfiguration(updatedDTO, new AsyncCallback() { + sailingServiceWrite.updateSwissTimingConfiguration(updatedDTO, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError( @@ -440,7 +440,7 @@ public class SwissTimingEventManagementPanel extends AbstractEventManagementPane // Check if the assigned regatta makes sense if (checkBoatClassOK(selectedRegatta, selectedRaces)) { - sailingService.trackWithSwissTiming(/* regattaToAddTo */ regattaIdentifier, selectedRaces, hostname, port, + sailingServiceWrite.trackWithSwissTiming(/* regattaToAddTo */ regattaIdentifier, selectedRaces, hostname, port, trackWind, correctWindByDeclination, useInternalMarkPassingAlgorithm, updateURL, updateUsername, updatePassword, selectedObject.getName(), selectedObject.getJsonUrl(), new AsyncCallback() { @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SwissTimingReplayConnectorPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SwissTimingReplayConnectorPanel.java index 0cebc51a6e7..9de66653eea 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SwissTimingReplayConnectorPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/SwissTimingReplayConnectorPanel.java @@ -31,6 +31,7 @@ import com.sap.sailing.gwt.ui.adminconsole.swisstiming.SwissTimingArchivedConnec import com.sap.sailing.gwt.ui.adminconsole.swisstiming.SwissTimingArchivedConnectionTableWrapper; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationWithSecurityDTO; @@ -64,9 +65,9 @@ public class SwissTimingReplayConnectorPanel extends AbstractEventManagementPane private final SwissTimingArchivedConnectionTableWrapper connectionsTable; - public SwissTimingReplayConnectorPanel(final SailingServiceAsync sailingService, UserService userService, + public SwissTimingReplayConnectorPanel(final SailingServiceWriteAsync sailingServiceWrite, UserService userService, ErrorReporter errorReporter, RegattaRefresher regattaRefresher, StringMessages stringMessages, CellTableWithCheckboxResources tableResources) { - super(sailingService, userService, regattaRefresher, errorReporter, true, stringMessages); + super(sailingServiceWrite, userService, regattaRefresher, errorReporter, true, stringMessages); this.errorReporter = errorReporter; availableSwissTimingRaces = new ArrayList(); @@ -84,13 +85,13 @@ public class SwissTimingReplayConnectorPanel extends AbstractEventManagementPane captionPanelConnections.setStyleName("bold"); // add connections table - connectionsTable = new SwissTimingArchivedConnectionTableWrapper(userService, sailingService, stringMessages, + connectionsTable = new SwissTimingArchivedConnectionTableWrapper(userService, sailingServiceWrite, stringMessages, errorReporter, true, tableResources, () -> { }); connectionsTable.refreshConnectionList(); // create button UI - final AccessControlledButtonPanel buttonPanel = createButtonPanel(sailingService, userService, errorReporter, + final AccessControlledButtonPanel buttonPanel = createButtonPanel(sailingServiceWrite, userService, errorReporter, stringMessages); verticalPanel.add(buttonPanel); verticalPanel.add(connectionsTable); @@ -250,7 +251,7 @@ public class SwissTimingReplayConnectorPanel extends AbstractEventManagementPane e -> btnTrack.setEnabled(connectionsTable.getSelectionModel().getSelectedSet().size() == 1)); } - private AccessControlledButtonPanel createButtonPanel(final SailingServiceAsync sailingService, + private AccessControlledButtonPanel createButtonPanel(final SailingServiceWriteAsync sailingServiceWrite, UserService userService, ErrorReporter errorReporter, StringMessages stringMessages) { final AccessControlledButtonPanel buttonPanel = new AccessControlledButtonPanel(userService, SecuredDomainType.SWISS_TIMING_ARCHIVE_ACCOUNT); @@ -262,7 +263,7 @@ public class SwissTimingReplayConnectorPanel extends AbstractEventManagementPane new DialogCallback() { @Override public void ok(SwissTimingArchiveConfigurationWithSecurityDTO editedConnection) { - sailingService.createSwissTimingArchiveConfiguration(editedConnection.getJsonUrl(), + sailingServiceWrite.createSwissTimingArchiveConfiguration(editedConnection.getJsonUrl(), new MarkedAsyncCallback(new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -285,7 +286,7 @@ public class SwissTimingReplayConnectorPanel extends AbstractEventManagementPane }, userService, errorReporter).show()); // Remove action buttonPanel.addRemoveAction(stringMessages.remove(), connectionsTable.getSelectionModel(), false, () -> { - sailingService.deleteSwissTimingArchiveConfigurations(connectionsTable.getSelectionModel().getSelectedSet(), + sailingServiceWrite.deleteSwissTimingArchiveConfigurations(connectionsTable.getSelectionModel().getSelectedSet(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -301,7 +302,7 @@ public class SwissTimingReplayConnectorPanel extends AbstractEventManagementPane }); // List Race action final Button listRacesButton = buttonPanel.addUnsecuredAction(stringMessages.listRaces(), () -> { - fillRaces(sailingService); + fillRaces(sailingServiceWrite); }); listRacesButton.setEnabled(false); // add change handlers to enable and disable List Races and Remove @@ -383,7 +384,7 @@ public class SwissTimingReplayConnectorPanel extends AbstractEventManagementPane } } if (checkBoatClassOK(selectedRegatta, selectedRaces)) { - sailingService.replaySwissTimingRace(regattaIdentifier, selectedRaces, trackWind, correctWindByDeclination, + sailingServiceWrite.replaySwissTimingRace(regattaIdentifier, selectedRaces, trackWind, correctWindByDeclination, useInternalMarkPassingAlgorithm, new AsyncCallback() { @Override public void onFailure(Throwable caught) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TableWrapper.java index eb107276e5c..3962a0e0205 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TableWrapper.java @@ -3,6 +3,7 @@ package com.sap.sailing.gwt.ui.adminconsole; import com.google.gwt.core.client.GWT; import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.adminconsole.AdminConsoleTableResources; import com.sap.sse.gwt.client.ErrorReporter; @@ -18,7 +19,7 @@ import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel; public abstract class TableWrapper> extends com.sap.sse.gwt.client.celltable.TableWrapper { protected static final int DEFAULT_PAGING_SIZE = 100; - protected final SailingServiceAsync sailingService; + protected final SailingServiceWriteAsync sailingServiceWrite; /** * @param enablePager if {@code true}, a paging control will be shown; this constructor, other than @@ -26,10 +27,10 @@ extends com.sap.sse.gwt.client.celltable.TableWrapper entityIdentityComparator) { - this(sailingService, stringMessages, errorReporter, multiSelection, enablePager, + this(sailingServiceWrite, stringMessages, errorReporter, multiSelection, enablePager, enablePager ? DEFAULT_PAGING_SIZE : Integer.MAX_VALUE /* if no pager, show all */, entityIdentityComparator); } @@ -38,11 +39,11 @@ extends com.sap.sse.gwt.client.celltable.TableWrapper entityIdentityComparator) { super(stringMessages, errorReporter, multiSelection, enablePager, entityIdentityComparator, GWT.create(AdminConsoleTableResources.class)); - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; table.setPageSize(pagingSize); } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TracTracEventManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TracTracEventManagementPanel.java index 151206e1139..2ca5f657e1c 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TracTracEventManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TracTracEventManagementPanel.java @@ -2,7 +2,6 @@ package com.sap.sailing.gwt.ui.adminconsole; import java.util.ArrayList; import java.util.Comparator; -import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -34,6 +33,7 @@ import com.sap.sailing.gwt.ui.adminconsole.tractrac.TracTracConnectionDialog; import com.sap.sailing.gwt.ui.adminconsole.tractrac.TracTracConnectionTableWrapper; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sailing.gwt.ui.shared.TracTracConfigurationWithSecurityDTO; @@ -81,11 +81,13 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel { private final UserService userService; private final CellTableWithCheckboxResources tableResources; + private final SailingServiceWriteAsync sailingServiceWrite; - public TracTracEventManagementPanel(final SailingServiceAsync sailingService, UserService userService, + public TracTracEventManagementPanel(final SailingServiceWriteAsync sailingService, UserService userService, ErrorReporter errorReporter, RegattaRefresher regattaRefresher, StringMessages stringMessages, final CellTableWithCheckboxResources tableResources) { super(sailingService, userService, regattaRefresher, errorReporter, true, stringMessages); + this.sailingServiceWrite = sailingService; this.userService = userService; this.errorReporter = errorReporter; this.tableResources = tableResources; @@ -110,7 +112,7 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel { connectionsPanel.ensureDebugId("ConnectionsSection"); connectionsPanel.setStyleName("bold"); VerticalPanel tableAndConfigurationPanel = new VerticalPanel(); - connectionsTable = new TracTracConnectionTableWrapper(userService, sailingService, stringMessages, + connectionsTable = new TracTracConnectionTableWrapper(userService, sailingServiceWrite, stringMessages, errorReporter, true, tableResources, () -> {}); connectionsTable.refreshTracTracConnectionList(); @@ -127,7 +129,7 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel { new DialogCallback() { @Override public void ok(TracTracConfigurationWithSecurityDTO editedConnection) { - sailingService.createTracTracConfiguration(editedConnection.getName(), + sailingServiceWrite.createTracTracConfiguration(editedConnection.getName(), editedConnection.getJsonUrl(), editedConnection.getLiveDataURI(), editedConnection.getStoredDataURI(), editedConnection.getCourseDesignUpdateURI(), @@ -152,7 +154,7 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel { }, userService, errorReporter).show()); addCreateAction.ensureDebugId("AddConnectionButton"); buttonPanel.addRemoveAction(stringMessages.remove(), connectionsTable.getSelectionModel(), false, () -> { - sailingService.deleteTracTracConfigurations(connectionsTable.getSelectionModel().getSelectedSet(), + sailingServiceWrite.deleteTracTracConfigurations(connectionsTable.getSelectionModel().getSelectedSet(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -169,7 +171,7 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel { loadingMessageLabel = new Label(); final Button listRacesButton = buttonPanel.addUnsecuredAction(stringMessages.listRaces(), () -> { loadingMessageLabel.setText(stringMessages.loading()); - fillRaces(sailingService, showHiddenRacesCheckbox.getValue()); + fillRaces(sailingServiceWrite, showHiddenRacesCheckbox.getValue()); }); listRacesButton.ensureDebugId("ListRacesButton"); listRacesButton.setEnabled(false); @@ -480,7 +482,7 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel { TracTracEventManagementPanel.this.racesTable.setPageSize(races.size()); loadingMessageLabel.setText(""); // store a successful configuration in the database for later retrieval - sailingService.updateTracTracConfiguration(updatedConnection, + sailingServiceWrite.updateTracTracConfiguration(updatedConnection, new MarkedAsyncCallback( new AsyncCallback() { @Override @@ -520,14 +522,14 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel { // because it may be an accidental omission to select that regatta for loading List allRaces = raceList.getList(); SelectionModel selectionModel = racesTable.getSelectionModel(); - final Set selectedRaces = new LinkedHashSet<>(); + final List selectedRaces = new ArrayList<>(); for (TracTracRaceRecordDTO race : allRaces) { if (selectionModel.isSelected(race)) { selectedRaces.add(race); } } if (checkBoatClassOK(selectedRegatta, selectedRaces)) { - sailingService.trackWithTracTrac(regattaIdentifier, selectedRaces, liveURI, storedURI, + sailingServiceWrite.trackWithTracTrac(regattaIdentifier, selectedRaces, liveURI, storedURI, courseDesignUpdateURI, trackWind, correctWind, offsetToStartTimeOfSimulatedRace, ignoreTracTracMarkPassings, useOfficialResultsToUpdateRaceLogs, tractracUsername, tractracPassword, new MarkedAsyncCallback(new AsyncCallback() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackFileImportDeviceIdentifierTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackFileImportDeviceIdentifierTableWrapper.java index 8cbeacc0776..d0503bdbf50 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackFileImportDeviceIdentifierTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackFileImportDeviceIdentifierTableWrapper.java @@ -15,7 +15,7 @@ import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTO; import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice; import com.sap.sailing.gwt.ui.client.MappableToDeviceFormatter; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; import com.sap.sailing.gwt.ui.shared.MarkDTO; @@ -29,9 +29,9 @@ public class TrackFileImportDeviceIdentifierTableWrapper extends private TextColumn trackNameColumn; private final Map mappings = new HashMap<>(); - public TrackFileImportDeviceIdentifierTableWrapper(SailingServiceAsync sailingService, + public TrackFileImportDeviceIdentifierTableWrapper(SailingServiceWriteAsync sailingServiceWrite, StringMessages stringMessages, ErrorReporter errorReporter) { - super(sailingService, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true, + super(sailingServiceWrite, stringMessages, errorReporter, /* multiSelection */ false, /* enablePager */ true, new EntityIdentityComparator() { @Override public boolean representSameEntity(TrackFileImportDeviceIdentifierDTO dto1, diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesListComposite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesListComposite.java index 10a4b5829f6..260d999ea88 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesListComposite.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesListComposite.java @@ -16,7 +16,7 @@ import com.sap.sailing.domain.common.dto.RaceDTO; import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.RegattasDisplayer; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sse.common.Util; @@ -43,10 +43,10 @@ public class TrackedRacesListComposite extends AbstractTrackedRacesListComposite private boolean actionButtonsEnabled; public TrackedRacesListComposite(Component parent, ComponentContext context, - final SailingServiceAsync sailingService, UserService userService, + final SailingServiceWriteAsync sailingServiceWrite, UserService userService, final ErrorReporter errorReporter, final RegattaRefresher regattaRefresher, final StringMessages stringMessages, boolean hasMultiSelection, boolean actionButtonsEnabled) { - super(parent, context, sailingService, errorReporter, regattaRefresher, stringMessages, hasMultiSelection, userService); + super(parent, context, sailingServiceWrite, errorReporter, regattaRefresher, stringMessages, hasMultiSelection, userService); this.raceIsTrackedRaceChangeListener = new HashSet(); this.actionButtonsEnabled = actionButtonsEnabled; createUI(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesManagementPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesManagementPanel.java index 008dd6cc4a4..04cbe298e61 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesManagementPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesManagementPanel.java @@ -15,7 +15,7 @@ import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.Grid; import com.sap.sailing.domain.common.dto.RaceDTO; import com.sap.sailing.gwt.ui.client.RegattaRefresher; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback; @@ -33,9 +33,9 @@ public class TrackedRacesManagementPanel extends AbstractRaceManagementPanel { private final Grid raceDataGrid; private final Button setStartTimeButton; - public TrackedRacesManagementPanel(final SailingServiceAsync sailingService, UserService userService, + public TrackedRacesManagementPanel(final SailingServiceWriteAsync sailingServiceWrite, UserService userService, ErrorReporter errorReporter, RegattaRefresher regattaRefresher, final StringMessages stringMessages) { - super(sailingService, userService, errorReporter, regattaRefresher, /* actionButtonsEnabled */ true, + super(sailingServiceWrite, userService, errorReporter, regattaRefresher, /* actionButtonsEnabled */ true, stringMessages); this.userService = userService; this.setStartTimeButton = new Button(stringMessages.setStartTimeReceived(), new ClickHandler() { @@ -44,7 +44,7 @@ public class TrackedRacesManagementPanel extends AbstractRaceManagementPanel { new SetStartTimeReceivedDialog(stringMessages, new DialogCallback() { @Override public void ok(Date newStartTimeReceived) { - sailingService.setStartTimeReceivedForRace(selectedRaceDTO.getRaceIdentifier(), newStartTimeReceived, new AsyncCallback() { + sailingServiceWrite.setStartTimeReceivedForRace(selectedRaceDTO.getRaceIdentifier(), newStartTimeReceived, new AsyncCallback() { @Override public void onFailure(Throwable caught) { TrackedRacesManagementPanel.this.errorReporter.reportError(stringMessages.errorSettingStartTime(caught.getMessage())); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesTableWrapper.java index 915c95b3076..5582f0fe098 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TrackedRacesTableWrapper.java @@ -1,16 +1,16 @@ package com.sap.sailing.gwt.ui.adminconsole; import com.sap.sailing.domain.common.dto.RaceDTO; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.celltable.EntityIdentityComparator; import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel; public class TrackedRacesTableWrapper extends TableWrapper> { - public TrackedRacesTableWrapper(SailingServiceAsync sailingService, StringMessages stringMessages, + public TrackedRacesTableWrapper(SailingServiceWriteAsync sailingServiceWrite, StringMessages stringMessages, ErrorReporter errorReporter, boolean multiSelection, boolean enablePager) { - super(sailingService, stringMessages, errorReporter, multiSelection, enablePager, new EntityIdentityComparator() { + super(sailingServiceWrite, stringMessages, errorReporter, multiSelection, enablePager, new EntityIdentityComparator() { @Override public boolean representSameEntity(RaceDTO dto1, RaceDTO dto2) { return dto1.getRaceIdentifier().equals(dto2.getRaceIdentifier()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WaypointCreationDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WaypointCreationDialog.java index 0575c8faa40..0ee54012945 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WaypointCreationDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WaypointCreationDialog.java @@ -10,7 +10,7 @@ import com.google.gwt.user.client.ui.Widget; import com.google.gwt.view.client.SelectionChangeEvent; import com.google.gwt.view.client.SelectionChangeEvent.Handler; import com.sap.sailing.domain.common.PassingInstruction; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.ControlPointDTO; import com.sap.sailing.gwt.ui.shared.WaypointDTO; @@ -29,7 +29,7 @@ public class WaypointCreationDialog extends DataEntryDialog { PassingInstruction getDefaultPassingInstruction(int numberOfMarksInControlPoint, String controlPointIdAsString); } - public WaypointCreationDialog(SailingServiceAsync sailingService, ErrorReporter errorReporter, + public WaypointCreationDialog(SailingServiceWriteAsync sailingServiceWrite, ErrorReporter errorReporter, final StringMessages stringMessages, AdminConsoleTableResources tableRes, List controlPoints, final DefaultPassingInstructionProvider defaultPassingInstructionProvider, DialogCallback callback) { @@ -45,7 +45,7 @@ public class WaypointCreationDialog extends DataEntryDialog { }, /* animationEnabled */ false, callback); this.stringMessages = stringMessages; controlPointsWrapper = new ControlPointTableWrapper>( - /* multiSelection */ false, sailingService, stringMessages, errorReporter); + /* multiSelection */ false, sailingServiceWrite, stringMessages, errorReporter); controlPointsWrapper.getDataProvider().getList().addAll(controlPoints); passingInstructions = createListBox(false); updatePassingInstructions(defaultPassingInstructionProvider); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WaypointTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WaypointTableWrapper.java index 4efa03c10e4..fa40c9e1a28 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WaypointTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WaypointTableWrapper.java @@ -1,7 +1,7 @@ package com.sap.sailing.gwt.ui.adminconsole; import com.google.gwt.user.cellview.client.TextColumn; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.ControlPointDTO; import com.sap.sailing.gwt.ui.shared.GateDTO; @@ -11,7 +11,7 @@ import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel; public class WaypointTableWrapper> extends TableWrapper { - public WaypointTableWrapper(boolean multiSelection, SailingServiceAsync sailingService, final StringMessages stringMessages, + public WaypointTableWrapper(boolean multiSelection, SailingServiceWriteAsync sailingService, final StringMessages stringMessages, ErrorReporter errorReporter) { super(sailingService, stringMessages, errorReporter, multiSelection, true, /* use equals/hashCode of WaypointDTO which maps to identity */ null); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java index 37e9a261840..b696334a0d4 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindPanel.java @@ -59,7 +59,7 @@ import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.ui.adminconsole.WindImportResult.RaceEntry; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.RegattasDisplayer; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil; import com.sap.sailing.gwt.ui.shared.CoursePositionsDTO; @@ -95,7 +95,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer { private static final String URL_SAILINGSERVER_NMEA_IMPORT = "/../../sailingserver/nmea-wind-import"; private static final String URL_SAILINGSERVER_BRAVO_IMPORT = "/../../sailingserver/bravo-wind-import"; - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final UserService userService; private final ErrorReporter errorReporter; private final StringMessages stringMessages; @@ -128,22 +128,22 @@ public class WindPanel extends FormPanel implements RegattasDisplayer { private CaptionPanel igtimiImportPanel; private CaptionPanel expeditionAllInOneImporterPanel; - public WindPanel(final SailingServiceAsync sailingService, final UserService userService, + public WindPanel(final SailingServiceWriteAsync sailingServiceWrite, final UserService userService, final AsyncActionsExecutor asyncActionsExecutor, final ErrorReporter errorReporter, final RegattaRefresher regattaRefresher, final StringMessages stringMessages) { this.ensureDebugId("WindPanel"); this.userPermission = race -> userService.hasPermission(race, UPDATE); - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.userService = userService; this.containedRegattaDisplayers = new HashSet<>(); this.errorReporter = errorReporter; this.stringMessages = stringMessages; - this.windSourcesToExcludeSelectorPanel = new WindSourcesToExcludeSelectorPanel(sailingService, stringMessages, + this.windSourcesToExcludeSelectorPanel = new WindSourcesToExcludeSelectorPanel(sailingServiceWrite, stringMessages, errorReporter); VerticalPanel mainPanel = new VerticalPanel(); mainPanel.setSize("100%", "100%"); this.setWidget(mainPanel); - trackedRacesListComposite = new TrackedRacesListComposite(null, null, sailingService, userService, + trackedRacesListComposite = new TrackedRacesListComposite(null, null, sailingServiceWrite, userService, errorReporter, regattaRefresher, stringMessages, /* multiselection */true, /* actionButtonsEnabled */ false); containedRegattaDisplayers.add(trackedRacesListComposite); @@ -172,7 +172,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer { RegattaAndRaceIdentifier selectedRace = getSelectedRace(); if (selectedRace != null) { final RaceDTO race = trackedRacesListComposite.getRaceByIdentifier(selectedRace); - sailingService.getCoursePositions(selectedRace, race.trackedRace.startOfTracking, new AsyncCallback() { + sailingServiceWrite.getCoursePositions(selectedRace, race.trackedRace.startOfTracking, new AsyncCallback() { @Override public void onFailure(Throwable caught) { showWindSettingDialog(race, null); @@ -208,7 +208,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer { List selectedRaces = new ArrayList<>(refreshableRaceSelectionModel.getSelectedSet()); final RegattaAndRaceIdentifier raceIdentifier = selectedRaces.get(selectedRaces.size() - 1) .getRaceIdentifier(); - sailingService.removeWind(raceIdentifier, wind, new AsyncCallback() { + sailingServiceWrite.removeWind(raceIdentifier, wind, new AsyncCallback() { @Override public void onSuccess(Void result) { // remove row from underlying list: @@ -353,7 +353,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer { } if (Window.confirm(warningMessage)) { resultReport.setText(stringMessages.loading()); - sailingService.importWindFromIgtimi(new ArrayList<>(refreshableRaceSelectionModel.getSelectedSet()), + sailingServiceWrite.importWindFromIgtimi(new ArrayList<>(refreshableRaceSelectionModel.getSelectedSet()), correctByDeclination.getValue(), new AsyncCallback>() { @Override public void onFailure(Throwable caught) { @@ -506,7 +506,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer { private Pair createExpeditionAllInOneImportPanel(RegattaRefresher regattaRefresher) { final CaptionPanel rootPanel = new CaptionPanel(stringMessages.importFullExpeditionData()); - final ExpeditionAllInOneImportPanel expeditionAllInOneImportPanel = new ExpeditionAllInOneImportPanel(stringMessages, sailingService, userService, errorReporter, regattaRefresher); + final ExpeditionAllInOneImportPanel expeditionAllInOneImportPanel = new ExpeditionAllInOneImportPanel(stringMessages, sailingServiceWrite, userService, errorReporter, regattaRefresher); rootPanel.add(expeditionAllInOneImportPanel); return new Pair<>(rootPanel, expeditionAllInOneImportPanel); } @@ -611,7 +611,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer { private void addWindFix(final WindDTO wind, final RaceDTO race) { final RegattaAndRaceIdentifier raceIdentifier = getSelectedRace(); - sailingService.setWind(raceIdentifier, wind, new AsyncCallback() { + sailingServiceWrite.setWind(raceIdentifier, wind, new AsyncCallback() { @Override public void onSuccess(Void result) { showWind(raceIdentifier, race); @@ -632,7 +632,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer { } public void showWind(final RegattaAndRaceIdentifier raceIdentifier, final RaceDTO race) { - sailingService.getWindSourcesInfo(raceIdentifier, new AsyncCallback() { + sailingServiceWrite.getWindSourcesInfo(raceIdentifier, new AsyncCallback() { @Override public void onSuccess(final WindInfoForRaceDTO result) { if (result != null) { @@ -644,7 +644,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer { windSourcesToExcludeSelectorPanel.setEnabled(userHasPermission); // load the raw wind fixes - sailingService.getRawWindFixes(raceIdentifier, null, new AsyncCallback() { + sailingServiceWrite.getRawWindFixes(raceIdentifier, null, new AsyncCallback() { @Override public void onSuccess(WindInfoForRaceDTO result) { if (result != null) { @@ -719,7 +719,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer { private void setRaceIsKnownToStartUpwind() { final RegattaAndRaceIdentifier selectedRace = getSelectedRace(); - sailingService.setRaceIsKnownToStartUpwind(selectedRace, raceIsKnownToStartUpwindBox.getValue(), new AsyncCallback() { + sailingServiceWrite.setRaceIsKnownToStartUpwind(selectedRace, raceIsKnownToStartUpwindBox.getValue(), new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(WindPanel.this.stringMessages.errorWhileTryingToSetWindSourceForRace() + " " + selectedRace + ": " + caught.getMessage()); @@ -753,7 +753,7 @@ public class WindPanel extends FormPanel implements RegattasDisplayer { windSourceTypeNames.add(WindSourceType.COMBINED.name()); addWindFixButton.setVisible(userPermission.test(race)); if (race.startOfRace != null) { - sailingService.getAveragedWindInfo(raceIdentifier, race.startOfRace, 30000L, 100, windSourceTypeNames, + sailingServiceWrite.getAveragedWindInfo(raceIdentifier, race.startOfRace, 30000L, 100, windSourceTypeNames, /* onlyUpToNewestEvent==true means to only use data "based on facts" */ true, /* includeCombinedWindForAllLegMiddles */ false, new AsyncCallback() { @Override public void onFailure(Throwable caught) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindSourcesToExcludeSelectorPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindSourcesToExcludeSelectorPanel.java index 7ac70b90025..425081a0e7b 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindSourcesToExcludeSelectorPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/WindSourcesToExcludeSelectorPanel.java @@ -1,7 +1,9 @@ package com.sap.sailing.gwt.ui.adminconsole; +import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Set; @@ -14,7 +16,7 @@ import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.VerticalPanel; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.WindSource; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.WindSourceTypeFormatter; import com.sap.sse.gwt.client.ErrorReporter; @@ -30,11 +32,11 @@ import com.sap.sse.gwt.client.ErrorReporter; public class WindSourcesToExcludeSelectorPanel extends VerticalPanel implements HasEnabled { private final LinkedHashMap checkboxesByWindSource; private final StringMessages stringMessages; - private final SailingServiceAsync service; + private final SailingServiceWriteAsync service; private final ErrorReporter errorReporter; private RegattaAndRaceIdentifier raceIdentifier; - public WindSourcesToExcludeSelectorPanel(SailingServiceAsync service, + public WindSourcesToExcludeSelectorPanel(SailingServiceWriteAsync service, StringMessages stringMessages, ErrorReporter errorReporter) { this.stringMessages = stringMessages; this.errorReporter = errorReporter; @@ -87,8 +89,8 @@ public class WindSourcesToExcludeSelectorPanel extends VerticalPanel implements }); } - private Iterable getWindSourcesToExclude() { - Set result = new HashSet(); + private List getWindSourcesToExclude() { + List result = new ArrayList(); for (Map.Entry e : checkboxesByWindSource.entrySet()) { if (!e.getValue().getValue()) { result.add(e.getKey()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/CourseTemplatePanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/CourseTemplatePanel.java index 6bea48c22cd..148f8a15a34 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/CourseTemplatePanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/CourseTemplatePanel.java @@ -35,7 +35,7 @@ import com.google.gwt.view.client.DefaultSelectionEventManager; import com.google.gwt.view.client.DefaultSelectionEventManager.SelectAction; import com.google.gwt.view.client.ListDataProvider; import com.sap.sailing.domain.common.security.SecuredDomainType; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.courseCreation.CourseTemplateDTO; import com.sap.sailing.gwt.ui.shared.courseCreation.MarkRoleDTO; @@ -61,7 +61,7 @@ import com.sap.sse.security.ui.client.component.editacl.EditACLDialog; public class CourseTemplatePanel extends FlowPanel { private static AdminConsoleTableResources tableResources = GWT.create(AdminConsoleTableResources.class); - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingService; private final LabeledAbstractFilterablePanel filterableCourseTemplatePanel; private List allCourseTemplates; private final ErrorReporter errorReporter; @@ -72,9 +72,9 @@ public class CourseTemplatePanel extends FlowPanel { private List allMarkRoles; private List allMarkTemplates; - public CourseTemplatePanel(SailingServiceAsync sailingService, ErrorReporter errorReporter, + public CourseTemplatePanel(SailingServiceWriteAsync sailingServiceWrite, ErrorReporter errorReporter, StringMessages stringMessages, final UserService userService) { - this.sailingService = sailingService; + this.sailingService = sailingServiceWrite; this.stringMessages = stringMessages; this.errorReporter = errorReporter; AccessControlledButtonPanel buttonAndFilterPanel = new AccessControlledButtonPanel(userService, @@ -293,29 +293,22 @@ public class CourseTemplatePanel extends FlowPanel { return Integer.toString(courseTemplate.getWaypointTemplates().size()); } }; - nameColumn.setSortable(true); sortHandler.setComparator(nameColumn, new Comparator() { public int compare(CourseTemplateDTO courseTemplate1, CourseTemplateDTO courseTemplate2) { return courseTemplate1.getName().compareTo(courseTemplate2.getName()); } }); - courseTemplateTable.addColumn(nameColumn, stringMessages.name()); courseTemplateTable.addColumn(urlColumn, stringMessages.url()); courseTemplateTable.addColumn(tagsColumn, stringMessages.tags()); courseTemplateTable.addColumn(waypointTemplateCountColumn, stringMessages.waypoints()); - SecuredDTOOwnerColumn.configureOwnerColumns(courseTemplateTable, sortHandler, stringMessages); - final HasPermissions type = SecuredDomainType.COURSE_TEMPLATE; - final AccessControlledActionsColumn actionsColumn = create( new DefaultActionsImagesBarCell(stringMessages), userService); final EditOwnershipDialog.DialogConfig configOwnership = EditOwnershipDialog - .create(userService.getUserManagementService(), type, courseTemplate -> { - /* no refresh action */}, stringMessages); - + .create(userService.getUserManagementService(), type, courseTemplateDTO -> courseTemplateListDataProvider.refresh(), stringMessages); final EditACLDialog.DialogConfig configACL = EditACLDialog.create( userService.getUserManagementService(), type, courseTemplate -> courseTemplate.getAccessControlList(), stringMessages); @@ -342,7 +335,7 @@ public class CourseTemplatePanel extends FlowPanel { courseTemplateTable.addColumn(idColumn, stringMessages.id()); courseTemplateTable.addColumn(actionsColumn, stringMessages.actions()); } - + public void refreshCourseTemplates() { loadCourseTemplates(); loadMarkRoles(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/MarkPropertiesPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/MarkPropertiesPanel.java index 47b1790cd90..f350fba78c5 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/MarkPropertiesPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/MarkPropertiesPanel.java @@ -41,7 +41,7 @@ import com.google.gwt.view.client.ListDataProvider; import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.ui.adminconsole.AdminConsoleResources; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.DeviceIdentifierDTO; import com.sap.sailing.gwt.ui.shared.courseCreation.MarkPropertiesDTO; @@ -72,7 +72,7 @@ public class MarkPropertiesPanel extends FlowPanel { private static final AbstractImagePrototype setDeviceIdentifierImagePrototype = AbstractImagePrototype .create(resources.mapDevices()); - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final LabeledAbstractFilterablePanel filterableMarkProperties; private List allMarkProperties; private final ErrorReporter errorReporter; @@ -81,9 +81,9 @@ public class MarkPropertiesPanel extends FlowPanel { private ListDataProvider markPropertiesListDataProvider = new ListDataProvider<>(); private RefreshableMultiSelectionModel refreshableSelectionModel; - public MarkPropertiesPanel(SailingServiceAsync sailingService, ErrorReporter errorReporter, + public MarkPropertiesPanel(SailingServiceWriteAsync sailingServiceWrite, ErrorReporter errorReporter, StringMessages stringMessages, final UserService userService) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.stringMessages = stringMessages; this.errorReporter = errorReporter; AccessControlledButtonPanel buttonAndFilterPanel = new AccessControlledButtonPanel(userService, @@ -125,7 +125,7 @@ public class MarkPropertiesPanel extends FlowPanel { private void removeMarkProperties(Collection markPropertiesUuids) { if (!markPropertiesUuids.isEmpty()) { - sailingService.removeMarkProperties(markPropertiesUuids, new AsyncCallback() { + sailingServiceWrite.removeMarkProperties(markPropertiesUuids, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Error trying to remove mark properties:" + caught.getMessage()); @@ -141,7 +141,7 @@ public class MarkPropertiesPanel extends FlowPanel { public void loadMarkProperties() { markPropertiesListDataProvider.getList().clear(); - sailingService.getMarkProperties(new AsyncCallback>() { + sailingServiceWrite.getMarkProperties(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(caught.toString()); @@ -294,7 +294,6 @@ public class MarkPropertiesPanel extends FlowPanel { return String.join(", ", markProperties.getTags()); } }; - Column positioningColumn = new Column( new AbstractCell() { @@ -315,14 +314,12 @@ public class MarkPropertiesPanel extends FlowPanel { } } }; - nameColumn.setSortable(true); sortHandler.setComparator(nameColumn, new Comparator() { public int compare(MarkPropertiesDTO markProperties1, MarkPropertiesDTO markProperties2) { return markProperties1.getName().compareTo(markProperties2.getName()); } }); - markPropertiesTable.addColumn(nameColumn, stringMessages.name()); markPropertiesTable.addColumn(shortNameColumn, stringMessages.shortName()); markPropertiesTable.addColumn(colorColumn, stringMessages.color()); @@ -331,23 +328,19 @@ public class MarkPropertiesPanel extends FlowPanel { markPropertiesTable.addColumn(typeColumn, stringMessages.type()); markPropertiesTable.addColumn(positioningColumn, stringMessages.position()); markPropertiesTable.addColumn(tagsColumn, stringMessages.tags()); - SecuredDTOOwnerColumn.configureOwnerColumns(markPropertiesTable, sortHandler, stringMessages); - final HasPermissions type = SecuredDomainType.MARK_PROPERTIES; - final AccessControlledActionsColumn actionsColumn = create( new MarkPropertiesImagesbarCell(stringMessages), userService); final EditOwnershipDialog.DialogConfig configOwnership = EditOwnershipDialog - .create(userService.getUserManagementService(), type, markProperties -> { - /* no refresh action */}, stringMessages); - + .create(userService.getUserManagementService(), type, markProperties -> + markPropertiesListDataProvider.refresh(), stringMessages); final EditACLDialog.DialogConfig configACL = EditACLDialog.create( userService.getUserManagementService(), type, markProperties -> markProperties.getAccessControlList(), stringMessages); actionsColumn.addAction(ACTION_DELETE, DELETE, e -> { if (Window.confirm(stringMessages.doYouReallyWantToRemoveMarkProperties(e.getName()))) { - sailingService.removeMarkProperties(Collections.singletonList(e.getUuid()), new AsyncCallback() { + sailingServiceWrite.removeMarkProperties(Collections.singletonList(e.getUuid()), new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(stringMessages.couldNotRemoveMarkProperties(caught.getMessage())); @@ -383,7 +376,7 @@ public class MarkPropertiesPanel extends FlowPanel { new DialogCallback() { @Override public void ok(MarkPropertiesDTO markProperties) { - sailingService.addOrUpdateMarkProperties(markProperties, + sailingServiceWrite.addOrUpdateMarkProperties(markProperties, new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -420,7 +413,7 @@ public class MarkPropertiesPanel extends FlowPanel { stringMessages, null, new DialogCallback() { @Override public void ok(DeviceIdentifierDTO deviceIdentifier) { - sailingService.updateMarkPropertiesPositioning(originalMarkProperties.getUuid(), + sailingServiceWrite.updateMarkPropertiesPositioning(originalMarkProperties.getUuid(), deviceIdentifier, null, new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -453,7 +446,7 @@ public class MarkPropertiesPanel extends FlowPanel { private void unsetPosition(final MarkPropertiesDTO originalMarkProperties) { if (Window.confirm(stringMessages.confirmUnsettingPositionForMarkProperties(originalMarkProperties.getName()))) { - sailingService.updateMarkPropertiesPositioning(originalMarkProperties.getUuid(), /* no tracking device */ null, + sailingServiceWrite.updateMarkPropertiesPositioning(originalMarkProperties.getUuid(), /* no tracking device */ null, /* and no fixed position either */ null, new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -482,7 +475,7 @@ public class MarkPropertiesPanel extends FlowPanel { new DialogCallback() { @Override public void ok(Position fixedPosition) { - sailingService.updateMarkPropertiesPositioning(originalMarkProperties.getUuid(), null, + sailingServiceWrite.updateMarkPropertiesPositioning(originalMarkProperties.getUuid(), null, fixedPosition, new AsyncCallback() { @Override public void onFailure(Throwable caught) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/MarkRolePanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/MarkRolePanel.java index faa15fb4643..7e4c2479cfb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/MarkRolePanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/MarkRolePanel.java @@ -27,7 +27,7 @@ import com.google.gwt.view.client.DefaultSelectionEventManager; import com.google.gwt.view.client.DefaultSelectionEventManager.SelectAction; import com.google.gwt.view.client.ListDataProvider; import com.sap.sailing.domain.common.security.SecuredDomainType; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.courseCreation.MarkRoleDTO; import com.sap.sse.common.Util; @@ -51,7 +51,7 @@ import com.sap.sse.security.ui.client.component.editacl.EditACLDialog; public class MarkRolePanel extends FlowPanel { private static AdminConsoleTableResources tableResources = GWT.create(AdminConsoleTableResources.class); - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final ErrorReporter errorReporter; private final StringMessages stringMessages; private final ListDataProvider markRoleListDataProvider = new ListDataProvider<>(); @@ -60,9 +60,9 @@ public class MarkRolePanel extends FlowPanel { private CellTable markRolesTable; private RefreshableMultiSelectionModel refreshableSelectionModel; - public MarkRolePanel(SailingServiceAsync sailingService, ErrorReporter errorReporter, StringMessages stringMessages, + public MarkRolePanel(SailingServiceWriteAsync sailingServiceWrite, ErrorReporter errorReporter, StringMessages stringMessages, final UserService userService) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.errorReporter = errorReporter; this.stringMessages = stringMessages; AccessControlledButtonPanel buttonAndFilterPanel = new AccessControlledButtonPanel(userService, @@ -109,7 +109,7 @@ public class MarkRolePanel extends FlowPanel { public void loadMarkRoles() { markRoleListDataProvider.getList().clear(); - sailingService.getMarkRoles(new AsyncCallback>() { + sailingServiceWrite.getMarkRoles(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { @@ -238,8 +238,7 @@ public class MarkRolePanel extends FlowPanel { final AccessControlledActionsColumn actionsColumn = create( new DefaultActionsImagesBarCell(stringMessages), userService); final EditOwnershipDialog.DialogConfig configOwnership = EditOwnershipDialog - .create(userService.getUserManagementService(), SecuredDomainType.MARK_ROLE, markRole -> { - /* no refresh action */}, stringMessages); + .create(userService.getUserManagementService(), SecuredDomainType.MARK_ROLE, markRole -> markRoleListDataProvider.refresh(), stringMessages); final EditACLDialog.DialogConfig configACL = EditACLDialog.create( userService.getUserManagementService(), SecuredDomainType.MARK_ROLE, markRole -> markRole.getAccessControlList(), stringMessages); @@ -255,7 +254,7 @@ public class MarkRolePanel extends FlowPanel { new DialogCallback() { @Override public void ok(MarkRoleDTO markRole) { - sailingService.createMarkRole(markRole, new AsyncCallback() { + sailingServiceWrite.createMarkRole(markRole, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/MarkTemplatePanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/MarkTemplatePanel.java index c322b4fa47f..4a6b982c07d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/MarkTemplatePanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/coursecreation/MarkTemplatePanel.java @@ -27,7 +27,7 @@ import com.google.gwt.view.client.DefaultSelectionEventManager; import com.google.gwt.view.client.DefaultSelectionEventManager.SelectAction; import com.google.gwt.view.client.ListDataProvider; import com.sap.sailing.domain.common.security.SecuredDomainType; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.courseCreation.MarkTemplateDTO; import com.sap.sse.common.Util; @@ -52,7 +52,7 @@ import com.sap.sse.security.ui.client.component.editacl.EditACLDialog; public class MarkTemplatePanel extends FlowPanel { private static AdminConsoleTableResources tableResources = GWT.create(AdminConsoleTableResources.class); - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final LabeledAbstractFilterablePanel filterableMarkTemplates; private List allMarkTemplates; private final ErrorReporter errorReporter; @@ -61,9 +61,9 @@ public class MarkTemplatePanel extends FlowPanel { private ListDataProvider markTemplateListDataProvider = new ListDataProvider<>(); private RefreshableMultiSelectionModel refreshableSelectionModel; - public MarkTemplatePanel(SailingServiceAsync sailingService, ErrorReporter errorReporter, + public MarkTemplatePanel(SailingServiceWriteAsync sailingServiceWrite, ErrorReporter errorReporter, StringMessages stringMessages, final UserService userService) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.stringMessages = stringMessages; this.errorReporter = errorReporter; AccessControlledButtonPanel buttonAndFilterPanel = new AccessControlledButtonPanel(userService, @@ -71,7 +71,6 @@ public class MarkTemplatePanel extends FlowPanel { add(buttonAndFilterPanel); allMarkTemplates = new ArrayList<>(); buttonAndFilterPanel.addUnsecuredAction(stringMessages.refresh(), new Command() { - @Override public void execute() { loadMarkTemplates(); @@ -81,14 +80,11 @@ public class MarkTemplatePanel extends FlowPanel { @Override public void execute() { openEditMarkTemplateDialog(new MarkTemplateDTO()); - // TODO add action } }); - Label lblFilterRaces = new Label(stringMessages.filterMarkTemplateByName() + ":"); lblFilterRaces.setWordWrap(false); buttonAndFilterPanel.addUnsecuredWidget(lblFilterRaces); - this.filterableMarkTemplates = new LabeledAbstractFilterablePanel(lblFilterRaces, allMarkTemplates, markTemplateListDataProvider, stringMessages) { @Override @@ -114,7 +110,7 @@ public class MarkTemplatePanel extends FlowPanel { public void loadMarkTemplates() { markTemplateListDataProvider.getList().clear(); - sailingService.getMarkTemplates(new AsyncCallback>() { + sailingServiceWrite.getMarkTemplates(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { errorReporter.reportError(caught.toString()); @@ -132,17 +128,14 @@ public class MarkTemplatePanel extends FlowPanel { private void createMarkTemplatesTable(final UserService userService) { // Create a CellTable. - // Set a key provider that provides a unique key for each contact. If key is // used to identify contacts when fields (such as the name and address) // change. markTemplateTable = new BaseCelltable<>(1000, tableResources); markTemplateTable.setWidth("100%"); - // Attach a column sort handler to the ListDataProvider to sort the list. ListHandler sortHandler = new ListHandler<>(markTemplateListDataProvider.getList()); markTemplateTable.addColumnSortHandler(sortHandler); - // Add a selection model so we can select cells. refreshableSelectionModel = new RefreshableMultiSelectionModel<>( new EntityIdentityComparator() { @@ -188,7 +181,6 @@ public class MarkTemplatePanel extends FlowPanel { // Initialize the columns. initTableColumns(sortHandler, userService); - markTemplateListDataProvider.addDataDisplay(markTemplateTable); add(markTemplateTable); allMarkTemplates.clear(); @@ -210,7 +202,6 @@ public class MarkTemplatePanel extends FlowPanel { }; markTemplateTable.addColumn(checkColumn, SafeHtmlUtils.fromSafeConstant("
    ")); markTemplateTable.setColumnWidth(checkColumn, 40, Unit.PX); - // id Column idColumn = new Column(new TextCell()) { @Override @@ -264,31 +255,24 @@ public class MarkTemplatePanel extends FlowPanel { : ""; } }; - nameColumn.setSortable(true); sortHandler.setComparator(nameColumn, new Comparator() { public int compare(MarkTemplateDTO markTemplate1, MarkTemplateDTO markTemplate2) { return markTemplate1.getName().compareTo(markTemplate2.getName()); } }); - markTemplateTable.addColumn(nameColumn, stringMessages.name()); markTemplateTable.addColumn(shortNameColumn, stringMessages.shortName()); markTemplateTable.addColumn(colorColumn, stringMessages.color()); markTemplateTable.addColumn(shapeColumn, stringMessages.shape()); markTemplateTable.addColumn(patternColumn, stringMessages.pattern()); markTemplateTable.addColumn(typeColumn, stringMessages.type()); - SecuredDTOOwnerColumn.configureOwnerColumns(markTemplateTable, sortHandler, stringMessages); - final HasPermissions type = SecuredDomainType.MARK_TEMPLATE; - final AccessControlledActionsColumn actionsColumn = create( new DefaultActionsImagesBarCell(stringMessages), userService); final EditOwnershipDialog.DialogConfig configOwnership = EditOwnershipDialog - .create(userService.getUserManagementService(), type, markTemplate -> { - /* no refresh action */}, stringMessages); - + .create(userService.getUserManagementService(), type, markTemplate -> markTemplateListDataProvider.refresh(), stringMessages); final EditACLDialog.DialogConfig configACL = EditACLDialog.create( userService.getUserManagementService(), type, markTemplate -> markTemplate.getAccessControlList(), stringMessages); @@ -297,7 +281,6 @@ public class MarkTemplatePanel extends FlowPanel { markTemplate -> configACL.openACLDialog(markTemplate)); markTemplateTable.addColumn(idColumn, stringMessages.id()); markTemplateTable.addColumn(actionsColumn, stringMessages.actions()); - } public void refreshMarkTemplates() { @@ -309,7 +292,7 @@ public class MarkTemplatePanel extends FlowPanel { new DialogCallback() { @Override public void ok(MarkTemplateDTO markTemplate) { - sailingService.addOrUpdateMarkTemplate(markTemplate, new AsyncCallback() { + sailingServiceWrite.addOrUpdateMarkTemplate(markTemplate, new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter @@ -337,5 +320,4 @@ public class MarkTemplatePanel extends FlowPanel { dialog.ensureDebugId("MarkTemplateEditDialog"); dialog.show(); } - } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/swisstiming/SwissTimingArchivedConnectionTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/swisstiming/SwissTimingArchivedConnectionTableWrapper.java index 451d59907fb..b89973911a7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/swisstiming/SwissTimingArchivedConnectionTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/swisstiming/SwissTimingArchivedConnectionTableWrapper.java @@ -13,6 +13,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Label; import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationWithSecurityDTO; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.async.MarkedAsyncCallback; @@ -44,7 +45,7 @@ public class SwissTimingArchivedConnectionTableWrapper extends private final SailingServiceAsync sailingServiceAsync; private final com.sap.sailing.gwt.ui.client.StringMessages stringMessagesClient; - public SwissTimingArchivedConnectionTableWrapper(final UserService userService, final SailingServiceAsync sailingServiceAsync, + public SwissTimingArchivedConnectionTableWrapper(final UserService userService, final SailingServiceWriteAsync sailingServiceAsyncWrite, final com.sap.sailing.gwt.ui.client.StringMessages stringMessages, final ErrorReporter errorReporter, final boolean enablePager, final CellTableWithCheckboxResources tableResources, final Runnable refresher) { super(stringMessages, errorReporter, true, enablePager, @@ -61,7 +62,7 @@ public class SwissTimingArchivedConnectionTableWrapper extends } }, tableResources); this.stringMessagesClient = stringMessages; - this.sailingServiceAsync = sailingServiceAsync; + this.sailingServiceAsync = sailingServiceAsyncWrite; final ListHandler swissTimingAccountColumnListHandler = getColumnSortHandler(); // table @@ -78,7 +79,7 @@ public class SwissTimingArchivedConnectionTableWrapper extends new DialogCallback() { @Override public void ok(final SwissTimingArchiveConfigurationWithSecurityDTO editedObject) { - sailingServiceAsync.updateSwissTimingArchiveConfiguration(editedObject, + sailingServiceAsyncWrite.updateSwissTimingArchiveConfiguration(editedObject, new MarkedAsyncCallback(new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -99,7 +100,7 @@ public class SwissTimingArchivedConnectionTableWrapper extends }, userService, errorReporter).show(); }); actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_DELETE, DefaultActions.DELETE, dto -> { - sailingServiceAsync.deleteSwissTimingArchiveConfigurations(Collections.singletonList(dto), new AsyncCallback() { + sailingServiceAsyncWrite.deleteSwissTimingArchiveConfigurations(Collections.singletonList(dto), new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Exception trying to delete configuration in DB: " + caught.getMessage()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/swisstiming/SwissTimingConnectionTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/swisstiming/SwissTimingConnectionTableWrapper.java index 9bcc5a2c66a..785d1012548 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/swisstiming/SwissTimingConnectionTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/swisstiming/SwissTimingConnectionTableWrapper.java @@ -13,6 +13,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Label; import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationWithSecurityDTO; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.async.MarkedAsyncCallback; @@ -46,7 +47,7 @@ public class SwissTimingConnectionTableWrapper extends private final SailingServiceAsync sailingServiceAsync; private final com.sap.sailing.gwt.ui.client.StringMessages stringMessagesClient; - public SwissTimingConnectionTableWrapper(final UserService userService, final SailingServiceAsync sailingServiceAsync, + public SwissTimingConnectionTableWrapper(final UserService userService, final SailingServiceWriteAsync sailingServiceWriteAsync, final com.sap.sailing.gwt.ui.client.StringMessages stringMessages, final ErrorReporter errorReporter, final boolean enablePager, final CellTableWithCheckboxResources tableResources, final Runnable refresher) { super(stringMessages, errorReporter, true, enablePager, @@ -63,7 +64,7 @@ public class SwissTimingConnectionTableWrapper extends } }, tableResources); this.stringMessagesClient = stringMessages; - this.sailingServiceAsync = sailingServiceAsync; + this.sailingServiceAsync = sailingServiceWriteAsync; final ListHandler swissTimingConectionColumnListHandler = getColumnSortHandler(); // table @@ -92,7 +93,7 @@ public class SwissTimingConnectionTableWrapper extends new SwissTimingConnectionEditDialog(dto, new DialogCallback() { @Override public void ok(final SwissTimingConfigurationWithSecurityDTO editedObject) { - sailingServiceAsync.updateSwissTimingConfiguration(editedObject, + sailingServiceWriteAsync.updateSwissTimingConfiguration(editedObject, new MarkedAsyncCallback(new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -114,7 +115,7 @@ public class SwissTimingConnectionTableWrapper extends }); actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_DELETE, DefaultActions.DELETE, dto -> { - sailingServiceAsync.deleteSwissTimingConfigurations(Collections.singletonList(dto), new AsyncCallback() { + sailingServiceWriteAsync.deleteSwissTimingConfigurations(Collections.singletonList(dto), new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Exception trying to delete configuration in DB: " + caught.getMessage()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/tractrac/TracTracConnectionTableWrapper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/tractrac/TracTracConnectionTableWrapper.java index 35942bfd2f2..7701445f353 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/tractrac/TracTracConnectionTableWrapper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/tractrac/TracTracConnectionTableWrapper.java @@ -14,6 +14,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Label; import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.shared.TracTracConfigurationWithSecurityDTO; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.async.MarkedAsyncCallback; @@ -44,10 +45,10 @@ import com.sap.sse.security.ui.client.i18n.StringMessages; public class TracTracConnectionTableWrapper extends TableWrapper, StringMessages, CellTableWithCheckboxResources> { private final LabeledAbstractFilterablePanel filterField; - private final SailingServiceAsync sailingServiceAsync; + private final SailingServiceAsync sailingServiceWriteAsync; private final com.sap.sailing.gwt.ui.client.StringMessages stringMessagesClient; - public TracTracConnectionTableWrapper(final UserService userService, final SailingServiceAsync sailingServiceAsync, + public TracTracConnectionTableWrapper(final UserService userService, final SailingServiceWriteAsync sailingServiceWriteAsync, final com.sap.sailing.gwt.ui.client.StringMessages stringMessages, final ErrorReporter errorReporter, final boolean enablePager, final CellTableWithCheckboxResources tableResources, final Runnable refresher) { super(stringMessages, errorReporter, true, enablePager, @@ -64,7 +65,7 @@ public class TracTracConnectionTableWrapper extends } }, tableResources); this.stringMessagesClient = stringMessages; - this.sailingServiceAsync = sailingServiceAsync; + this.sailingServiceWriteAsync = sailingServiceWriteAsync; final ListHandler tracTracAccountColumnListHandler = getColumnSortHandler(); // table @@ -89,7 +90,7 @@ public class TracTracConnectionTableWrapper extends new TracTracConnectionEditDialog(dto, new DialogCallback() { @Override public void ok(final TracTracConfigurationWithSecurityDTO editedObject) { - sailingServiceAsync.updateTracTracConfiguration(editedObject, + sailingServiceWriteAsync.updateTracTracConfiguration(editedObject, new MarkedAsyncCallback(new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -111,7 +112,7 @@ public class TracTracConnectionTableWrapper extends }); actionColumn.addAction(DefaultActionsImagesBarCell.ACTION_DELETE, DefaultActions.DELETE, dto -> { - sailingServiceAsync.deleteTracTracConfigurations(Collections.singletonList(dto), new AsyncCallback() { + sailingServiceWriteAsync.deleteTracTracConfigurations(Collections.singletonList(dto), new AsyncCallback() { @Override public void onFailure(Throwable caught) { errorReporter.reportError("Exception trying to delete configuration in DB: " + caught.getMessage()); @@ -180,7 +181,7 @@ public class TracTracConnectionTableWrapper extends * the same entity if present */ public void refreshTracTracConnectionList(final TracTracConfigurationWithSecurityDTO selectEntityWhenDone) { - sailingServiceAsync + sailingServiceWriteAsync .getPreviousTracTracConfigurations(new AsyncCallback>() { @Override public void onFailure(Throwable caught) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AbstractRegattaPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AbstractRegattaPanel.java index 0de9d5d48db..10cc5edc1cf 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AbstractRegattaPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AbstractRegattaPanel.java @@ -9,17 +9,17 @@ import com.sap.sse.gwt.client.ErrorReporter; //TODO: Do not inherit from FormPanel since the provided functionality is never used! public abstract class AbstractRegattaPanel extends FormPanel implements RegattasDisplayer { - protected final SailingServiceAsync sailingService; + protected final SailingServiceWriteAsync sailingServiceWrite; protected DateTimeFormatRenderer dateFormatter = new DateTimeFormatRenderer(DateTimeFormat.getFormat(PredefinedFormat.DATE_SHORT)); protected DateTimeFormatRenderer timeFormatter = new DateTimeFormatRenderer(DateTimeFormat.getFormat(PredefinedFormat.TIME_LONG)); protected final RegattaRefresher regattaRefresher; protected ErrorReporter errorReporter; protected StringMessages stringMessages; - public AbstractRegattaPanel(SailingServiceAsync sailingService, + public AbstractRegattaPanel(SailingServiceWriteAsync sailingServiceWrite, RegattaRefresher regattaRefresher, ErrorReporter errorReporter, StringMessages stringMessages) { super(); - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.regattaRefresher = regattaRefresher; this.errorReporter = errorReporter; this.stringMessages = stringMessages; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AbstractSailingEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AbstractSailingEntryPoint.java index d82c75e6d80..b54730adca4 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AbstractSailingEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AbstractSailingEntryPoint.java @@ -2,34 +2,24 @@ package com.sap.sailing.gwt.ui.client; import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.common.communication.routing.ProvidesLeaderboardRouting; -import com.sap.sse.gwt.client.ServiceRoutingProvider; import com.sap.sse.security.ui.client.AbstractSecureEntryPoint; -public abstract class AbstractSailingEntryPoint extends AbstractSecureEntryPoint { - private SailingServiceAsync sailingService; +public abstract class AbstractSailingEntryPoint extends AbstractSecureEntryPoint { + protected T sailingService; @Override protected void doOnModuleLoad() { super.doOnModuleLoad(); getUserService().addKnownHasPermissions(SecuredDomainType.getAllInstances()); } - + /** * Lazily initialize sailing service. Concrete entry point subclasses may influence sailing service creation by * implementing a given routing information providing interface {@link ProvidesLeaderboardRouting}. The routing * information provided via {@link ProvidesLeaderboardRouting#getLeaderboardName()} needs to be available when this * method is called for the first time. Repetitive calls will not cause a new leaderboard name to take effect. */ - protected SailingServiceAsync getSailingService() { - if (sailingService == null) { - if (this instanceof ServiceRoutingProvider) { - sailingService = SailingServiceHelper.createSailingServiceInstance((ServiceRoutingProvider)this); - } else { - sailingService = SailingServiceHelper.createSailingServiceInstance(); - } - } - return sailingService; - } + abstract protected T getSailingService(); @Override protected StringMessages createStringMessages() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AbstractSailingReadEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AbstractSailingReadEntryPoint.java new file mode 100644 index 00000000000..aad1ccccd08 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AbstractSailingReadEntryPoint.java @@ -0,0 +1,18 @@ +package com.sap.sailing.gwt.ui.client; + +import com.sap.sse.gwt.client.ServiceRoutingProvider; + +public class AbstractSailingReadEntryPoint extends AbstractSailingEntryPoint { + + @Override + protected SailingServiceAsync getSailingService() { + if (sailingService == null) { + if (this instanceof ServiceRoutingProvider) { + sailingService = SailingServiceHelper.createSailingServiceInstance((ServiceRoutingProvider)this); + } else { + sailingService = SailingServiceHelper.createSailingServiceInstance(); + } + } + return sailingService; + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AbstractSailingWriteEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AbstractSailingWriteEntryPoint.java new file mode 100644 index 00000000000..d8a00a730dd --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/AbstractSailingWriteEntryPoint.java @@ -0,0 +1,25 @@ +package com.sap.sailing.gwt.ui.client; + +import com.sap.sailing.gwt.common.communication.routing.ProvidesLeaderboardRouting; +import com.sap.sse.gwt.client.ServiceRoutingProvider; + +public class AbstractSailingWriteEntryPoint extends AbstractSailingEntryPoint { + + /** + * Lazily initialize sailing service. Concrete entry point subclasses may influence sailing service creation by + * implementing a given routing information providing interface {@link ProvidesLeaderboardRouting}. The routing + * information provided via {@link ProvidesLeaderboardRouting#getLeaderboardName()} needs to be available when this + * method is called for the first time. Repetitive calls will not cause a new leaderboard name to take effect. + */ + @Override + protected SailingServiceWriteAsync getSailingService() { + if (sailingService == null) { + if (this instanceof ServiceRoutingProvider) { + sailingService = SailingServiceHelper.createSailingServiceWriteInstance((ServiceRoutingProvider)this); + } else { + sailingService = SailingServiceHelper.createSailingServiceWriteInstance(); + } + } + return sailingService; + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimesInfoProvider.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimesInfoProvider.java index 392594e2662..e831042bc28 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimesInfoProvider.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RaceTimesInfoProvider.java @@ -140,7 +140,6 @@ public class RaceTimesInfoProvider { } else { getRaceTimesInfoAction = new GetRaceTimesInfoAction(sailingService, raceIdentifiers); } - asyncActionsExecutor.execute(getRaceTimesInfoAction, new AsyncCallback>() { @Override public void onFailure(Throwable caught) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RemoteServiceMappingConstants.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RemoteServiceMappingConstants.java index 8a8caed7121..edf27d78f68 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RemoteServiceMappingConstants.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/RemoteServiceMappingConstants.java @@ -19,6 +19,8 @@ public interface RemoteServiceMappingConstants { public static final String mediaServiceRemotePath = "service/media"; public static final String sailingServiceRemotePath = "service/sailing"; + + public static final String sailingServiceWriteRemotePath = "service/sailingmaster"; public static final String serverConfigurationServiceRemotePath = "service/serverconfiguration"; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java index 53445d2e06c..9d2e6a21979 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java @@ -12,36 +12,18 @@ import java.util.UUID; import org.apache.shiro.authz.UnauthorizedException; import com.google.gwt.user.client.rpc.RemoteService; -import com.sap.sailing.domain.abstractlog.Revokable; -import com.sap.sailing.domain.abstractlog.orc.RaceLogORCLegDataEvent; import com.sap.sailing.domain.abstractlog.race.RaceLog; import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.common.CompetitorDescriptor; -import com.sap.sailing.domain.common.CompetitorRegistrationType; -import com.sap.sailing.domain.common.DataImportProgress; import com.sap.sailing.domain.common.DetailType; -import com.sap.sailing.domain.common.LeaderboardType; import com.sap.sailing.domain.common.LegIdentifier; import com.sap.sailing.domain.common.MailInvitationType; -import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.common.NotFoundException; -import com.sap.sailing.domain.common.PassingInstruction; -import com.sap.sailing.domain.common.PolarSheetsXYDiagramData; -import com.sap.sailing.domain.common.Position; -import com.sap.sailing.domain.common.RaceIdentifier; -import com.sap.sailing.domain.common.RankingMetrics; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.RegattaIdentifier; -import com.sap.sailing.domain.common.RegattaName; -import com.sap.sailing.domain.common.ScoringSchemeType; -import com.sap.sailing.domain.common.ServiceException; -import com.sap.sailing.domain.common.UnableToCloseDeviceMappingException; import com.sap.sailing.domain.common.WindSource; -import com.sap.sailing.domain.common.abstractlog.NotRevokableException; import com.sap.sailing.domain.common.abstractlog.TimePointSpecificationFoundInLog; import com.sap.sailing.domain.common.dto.BoatDTO; import com.sap.sailing.domain.common.dto.CompetitorAndBoatDTO; @@ -54,9 +36,6 @@ import com.sap.sailing.domain.common.dto.PairingListDTO; import com.sap.sailing.domain.common.dto.PairingListTemplateDTO; import com.sap.sailing.domain.common.dto.PersonDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTO; -import com.sap.sailing.domain.common.dto.RaceColumnInSeriesDTO; -import com.sap.sailing.domain.common.dto.RaceDTO; -import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO; import com.sap.sailing.domain.common.dto.TagDTO; import com.sap.sailing.domain.common.impl.KilometersPerHourSpeedImpl; import com.sap.sailing.domain.common.impl.KnotSpeedImpl; @@ -65,32 +44,20 @@ import com.sap.sailing.domain.common.orc.ORCCertificate; import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLegTypes; import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveLegImpl; import com.sap.sailing.domain.common.racelog.RacingProcedureType; -import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException; import com.sap.sailing.domain.common.racelog.tracking.DoesNotHaveRegattaLogException; -import com.sap.sailing.domain.common.racelog.tracking.NotDenotedForRaceLogTrackingException; import com.sap.sailing.domain.common.racelog.tracking.TransformationException; import com.sap.sailing.domain.common.tracking.impl.PreciseCompactGPSFixMovingImpl.PreciseCompactPosition; import com.sap.sailing.domain.common.windfinder.SpotDTO; -import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; -import com.sap.sailing.domain.racelog.tracking.SensorFixStore; -import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapter; -import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.expeditionconnector.ExpeditionDeviceConfiguration; -import com.sap.sailing.gwt.ui.adminconsole.RaceLogSetTrackingTimesDTO; import com.sap.sailing.gwt.ui.client.shared.charts.MarkPositionService.MarkTrackDTO; -import com.sap.sailing.gwt.ui.client.shared.charts.MarkPositionService.MarkTracksDTO; import com.sap.sailing.gwt.ui.shared.AccountWithSecurityDTO; -import com.sap.sailing.gwt.ui.shared.BulkScoreCorrectionDTO; import com.sap.sailing.gwt.ui.shared.CompactBoatPositionsDTO; import com.sap.sailing.gwt.ui.shared.CompactRaceMapDataDTO; import com.sap.sailing.gwt.ui.shared.CompetitorProviderDTO; import com.sap.sailing.gwt.ui.shared.CompetitorsRaceDataDTO; -import com.sap.sailing.gwt.ui.shared.ControlPointDTO; import com.sap.sailing.gwt.ui.shared.CoursePositionsDTO; import com.sap.sailing.gwt.ui.shared.DeviceConfigurationDTO; -import com.sap.sailing.gwt.ui.shared.DeviceConfigurationDTO.RegattaConfigurationDTO; import com.sap.sailing.gwt.ui.shared.DeviceConfigurationWithSecurityDTO; -import com.sap.sailing.gwt.ui.shared.DeviceIdentifierDTO; import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.GPSFixDTO; @@ -98,7 +65,6 @@ import com.sap.sailing.gwt.ui.shared.GPSFixDTOWithSpeedWindTackAndLegType; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; import com.sap.sailing.gwt.ui.shared.ManeuverDTO; import com.sap.sailing.gwt.ui.shared.MarkDTO; -import com.sap.sailing.gwt.ui.shared.MigrateGroupOwnerForHierarchyDTO; import com.sap.sailing.gwt.ui.shared.QRCodeEvent; import com.sap.sailing.gwt.ui.shared.RaceCourseDTO; import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; @@ -122,15 +88,11 @@ import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTOWithSecurity; import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationWithSecurityDTO; import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationWithSecurityDTO; import com.sap.sailing.gwt.ui.shared.SwissTimingEventRecordDTO; -import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDTO; import com.sap.sailing.gwt.ui.shared.SwissTimingReplayRaceDTO; import com.sap.sailing.gwt.ui.shared.TracTracConfigurationWithSecurityDTO; import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDTO; import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO; -import com.sap.sailing.gwt.ui.shared.TypedDeviceMappingDTO; import com.sap.sailing.gwt.ui.shared.UrlDTO; -import com.sap.sailing.gwt.ui.shared.VenueDTO; -import com.sap.sailing.gwt.ui.shared.WindDTO; import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO; import com.sap.sailing.gwt.ui.shared.courseCreation.CourseTemplateDTO; import com.sap.sailing.gwt.ui.shared.courseCreation.MarkPropertiesDTO; @@ -146,37 +108,20 @@ import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.Util.Triple; import com.sap.sse.common.impl.SecondsDurationImpl; -import com.sap.sse.common.mail.MailException; -import com.sap.sse.common.media.MediaTagConstants; -import com.sap.sse.filestorage.FileStorageService; -import com.sap.sse.gwt.client.filestorage.FileStorageManagementGwtService; -import com.sap.sse.gwt.client.media.ImageDTO; -import com.sap.sse.gwt.client.media.ImageResizingTaskDTO; -import com.sap.sse.gwt.client.media.VideoDTO; import com.sap.sse.gwt.client.replication.RemoteReplicationService; -import com.sap.sse.security.interfaces.UserStore; import com.sap.sse.security.shared.TypeRelativeObjectIdentifier; -import com.sap.sse.security.ui.shared.SuccessInfo; /** * The client side stub for the RPC service. Usually, when a null date is passed to the time-dependent * service methods, an empty (non-null) result is returned. */ -public interface SailingService extends RemoteService, FileStorageManagementGwtService, RemoteReplicationService { +public interface SailingService extends RemoteService, RemoteReplicationService { List getPreviousTracTracConfigurations() throws UnauthorizedException, Exception; - void updateTracTracConfiguration(TracTracConfigurationWithSecurityDTO tracTracConfiguration) - throws UnauthorizedException, Exception; - - void deleteTracTracConfigurations(Collection tracTracConfigurations) - throws UnauthorizedException, Exception; - List getRegattas() throws UnauthorizedException; - List getRegattasWithUpdatePermission() throws UnauthorizedException; - RegattaDTO getRegattaByName(String regattaName) throws UnauthorizedException; List getEvents() throws Exception; @@ -184,34 +129,13 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS Util.Pair> listTracTracRacesInEvent(String eventJsonURL, boolean listHiddenRaces) throws UnauthorizedException, Exception; - void trackWithTracTrac(RegattaIdentifier regattaToAddTo, Iterable rrs, String liveURI, - String storedURI, String courseDesignUpdateURI, boolean trackWind, boolean correctWindByDeclination, - Duration offsetToStartTimeOfSimulatedRace, boolean useInternalMarkPassingAlgorithm, boolean useOfficialEventsToUpdateRaceLog, - String tracTracUsername, String tracTracPassword) throws UnauthorizedException, Exception; - - void trackWithSwissTiming(RegattaIdentifier regattaToAddTo, Iterable rrs, String hostname, - int port, boolean trackWind, boolean correctWindByDeclination, boolean useInternalMarkPassingAlgorithm, - String updateURL, String updateUsername, String updatePassword, String eventName, String manage2SailEventUrl) throws UnauthorizedException, Exception; - void replaySwissTimingRace(RegattaIdentifier regattaIdentifier, Iterable replayRaces, boolean trackWind, boolean correctWindByDeclination, boolean useInternalMarkPassingAlgorithm) throws UnauthorizedException; - void createTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI, - String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword) - throws UnauthorizedException, Exception; - - void stopTrackingRaces(Iterable racesToStopTracking) - throws UnauthorizedException, Exception; - - void removeAndUntrackRaces(Iterable regattaNamesAndRaceNames) - throws UnauthorizedException; - WindInfoForRaceDTO getRawWindFixes(RegattaAndRaceIdentifier raceIdentifier, Collection windSources) throws UnauthorizedException; - void setWind(RegattaAndRaceIdentifier raceIdentifier, WindDTO wind) throws UnauthorizedException; - WindInfoForRaceDTO getAveragedWindInfo(RegattaAndRaceIdentifier raceIdentifier, Date from, long millisecondsStepWidth, int numberOfFixes, Collection windSourceTypeNames, boolean onlyUpToNewestEvent, boolean includeCombinedWindForAllLegMiddles) @@ -221,10 +145,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS long resolutionInMilliseconds, Collection windSourceTypeNames, boolean onlyUpToNewestEvent) throws UnauthorizedException; - WindInfoForRaceDTO getAveragedWindInfo(RegattaAndRaceIdentifier raceIdentifier, Date from, - long millisecondsStepWidth, int numberOfFixes, double latDeg, double lngDeg, Collection windSources) - throws NoWindException, UnauthorizedException; - boolean getPolarResults(RegattaAndRaceIdentifier raceIdentifier) throws UnauthorizedException; SimulatorResultsDTO getSimulatorResults(LegIdentifier legIdentifier) throws UnauthorizedException; @@ -274,8 +194,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS RaceCourseDTO getRaceCourse(RegattaAndRaceIdentifier raceIdentifier, Date date) throws UnauthorizedException; - void removeWind(RegattaAndRaceIdentifier raceIdentifier, WindDTO windDTO) throws UnauthorizedException; - public List getLeaderboardNames() throws UnauthorizedException; IncrementalOrFullLeaderboardDTO getLeaderboardByName(String leaderboardName, Date date, @@ -291,118 +209,13 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS List getLeaderboardsWithSecurity() throws UnauthorizedException; - StrippedLeaderboardDTOWithSecurity updateLeaderboard(String leaderboardName, String newLeaderboardName, - String newLeaderboardDisplayName, int[] newDiscardingThreasholds, Iterable newCourseAreaIds) - throws UnauthorizedException; - - StrippedLeaderboardDTOWithSecurity createFlexibleLeaderboard(String leaderboardName, String leaderboardDisplayName, - int[] discardThresholds, ScoringSchemeType scoringSchemeType, Iterable courseAreaIds) - throws UnauthorizedException; - - StrippedLeaderboardDTOWithSecurity createRegattaLeaderboard(RegattaName regattaIdentifier, - String leaderboardDisplayName, int[] discardThresholds) throws UnauthorizedException; - - StrippedLeaderboardDTOWithSecurity createRegattaLeaderboardWithEliminations(String name, String displayName, - String regattaName) throws UnauthorizedException; - - void removeLeaderboard(String leaderboardName) throws UnauthorizedException; - - void removeLeaderboards(Collection leaderboardNames) throws UnauthorizedException; - - void renameLeaderboard(String leaderboardName, String newLeaderboardName) throws UnauthorizedException; - - void renameLeaderboardColumn(String leaderboardName, String oldColumnName, String newColumnName) - throws UnauthorizedException; - - void removeLeaderboardColumn(String leaderboardName, String columnName) throws UnauthorizedException; - - void addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace) - throws UnauthorizedException; - - void moveLeaderboardColumnUp(String leaderboardName, String columnName) throws UnauthorizedException; - - void moveLeaderboardColumnDown(String leaderboardName, String columnName) throws UnauthorizedException; - - RegattaDTO createRegatta(String regattaName, String boatClassName, boolean canBoatsOfCompetitorsChangePerRace, - CompetitorRegistrationType competitorRegistrationType, String registrationLinkSecret, Date startDate, - Date endDate, RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal, - boolean persistent, ScoringSchemeType scoringSchemeType, Iterable courseAreaIds, - Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, - boolean controlTrackingFromStartAndFinishTimes, boolean autoRestartTrackingUponCompetitorSetChange, RankingMetrics rankingMetricType) - throws UnauthorizedException; - - void removeRegatta(RegattaIdentifier regattaIdentifier) throws UnauthorizedException; - - void removeSeries(RegattaIdentifier regattaIdentifier, String seriesName) throws UnauthorizedException; - - void removeRegattas(Collection regattas) throws UnauthorizedException; - - void updateRegatta(RegattaIdentifier regattaIdentifier, Date startDate, Date endDate, Iterable courseAreaUuids, - RegattaConfigurationDTO regattaConfiguration, Double buoyZoneRadiusInHullLengths, - boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes, - boolean autoRestartTrackingUponCompetitorSetChange, String registrationLinkSecret, CompetitorRegistrationType registrationType) throws UnauthorizedException; - - List addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, - List> columnNames) throws UnauthorizedException; - - void updateSeries(RegattaIdentifier regattaIdentifier, String seriesName, String newSeriesName, boolean isMedal, - boolean isFleetsCanRunInParallel, int[] resultDiscardingThresholds, boolean startsWithZeroScore, - boolean firstRaceIsNonDiscardableCarryForward, boolean hasSplitFleetScore, Integer maximumNumberOfDiscards, - List fleets) throws UnauthorizedException; - - void removeRaceColumnsFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, List columnNames) - throws UnauthorizedException; - - void moveRaceColumnInSeriesUp(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) - throws UnauthorizedException; - - void moveRaceColumnInSeriesDown(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) - throws UnauthorizedException; - - boolean connectTrackedRaceToLeaderboardColumn(String leaderboardName, String raceColumnName, String fleetName, - RegattaAndRaceIdentifier raceIdentifier) throws UnauthorizedException; - - void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName, String fleetName) - throws UnauthorizedException; - Map getRegattaAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn( String leaderboardName, String raceColumnName) throws UnauthorizedException; - void updateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Double carriedPoints) - throws UnauthorizedException; - - /** - * @return the new net points in {@link Pair#getA()} and the new total points in {@link Pair#getB()} for time point - * date after the max points reason has been updated to maxPointsReasonAsString. - */ - Util.Triple updateLeaderboardMaxPointsReason(String leaderboardName, - String competitorIdAsString, String raceColumnName, MaxPointsReason maxPointsReason, Date date) - throws NoWindException, UnauthorizedException; - - Util.Triple updateLeaderboardScoreCorrection(String leaderboardName, - String competitorIdAsString, String columnName, Double correctedScore, Date date) - throws NoWindException, UnauthorizedException; - - void updateCompetitorDisplayNameInLeaderboard(String leaderboardName, String competitorIdAsString, - String displayName) throws UnauthorizedException; - - void updateIsMedalRace(String leaderboardName, String columnName, boolean isMedalRace) throws UnauthorizedException; - List getPreviousSwissTimingConfigurations() throws UnauthorizedException; SwissTimingEventRecordDTO getRacesOfSwissTimingEvent(String eventJsonURL) throws UnauthorizedException, Exception; - void createSwissTimingConfiguration(String configName, String jsonURL, String hostname, Integer port, - String updateURL, String updateUsername, String updatePassword) throws UnauthorizedException, Exception; - - void deleteSwissTimingConfigurations(Collection configurations) - throws UnauthorizedException, Exception; - - void updateSwissTimingConfiguration(SwissTimingConfigurationWithSecurityDTO configuration) - throws UnauthorizedException, Exception; - - String[] getCountryCodes() throws UnauthorizedException; - Map> getDouglasPoints( RegattaAndRaceIdentifier raceIdentifier, Map competitorTimeRanges, double meters) throws NoWindException, UnauthorizedException; @@ -410,63 +223,17 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS Map> getManeuvers(RegattaAndRaceIdentifier raceIdentifier, Map competitorTimeRanges) throws NoWindException, UnauthorizedException; - List getLeaderboardsByRaceAndRegatta(String raceName, RegattaIdentifier regattaIdentifier) - throws UnauthorizedException; - List getLeaderboardGroups(boolean withGeoLocationData) throws UnauthorizedException; LeaderboardGroupDTO getLeaderboardGroupByName(String groupName, boolean withGeoLocationData) throws UnauthorizedException; - void renameLeaderboardGroup(String oldName, String newName) throws UnauthorizedException; - - void removeLeaderboardGroups(Set groupNames) throws UnauthorizedException; - - LeaderboardGroupDTO createLeaderboardGroup(String groupName, String description, String displayName, - boolean displayGroupsInReverseOrder, int[] overallLeaderboardDiscardThresholds, - ScoringSchemeType overallLeaderboardScoringSchemeType) throws UnauthorizedException; - - void updateLeaderboardGroup(UUID leaderboardGroupId, String oldName, String newName, String description, - String newDisplayName, List leaderboardNames, int[] overallLeaderboardDiscardThresholds, - ScoringSchemeType overallLeaderboardScoringSchemeType) throws UnauthorizedException; - CompetitorsRaceDataDTO getCompetitorsRaceData(RegattaAndRaceIdentifier race, List competitors, Date from, Date to, long stepSizeInMs, DetailType detailType, String leaderboardGroupName, String leaderboardName) throws NoWindException, UnauthorizedException; - void setRaceIsKnownToStartUpwind(RegattaAndRaceIdentifier raceIdentifier, boolean raceIsKnownToStartUpwind) - throws UnauthorizedException; - - void setWindSourcesToExclude(RegattaAndRaceIdentifier raceIdentifier, Iterable windSourcesToExclude) - throws UnauthorizedException; - - void updateRaceDelayToLive(RegattaAndRaceIdentifier regattaAndRaceIdentifier, long delayToLiveInMs) - throws UnauthorizedException; - - void updateRacesDelayToLive(List regattaAndRaceIdentifiers, long delayToLiveInMs) - throws UnauthorizedException; - Pair resolveImageDimensions(String imageUrlAsString) throws UnauthorizedException, Exception; - EventDTO updateEvent(UUID eventId, String eventName, String eventDescription, Date startDate, Date endDate, - VenueDTO venue, boolean isPublic, Iterable leaderboardGroupIds, String officialWebsiteURL, - String baseURL, Map sailorsInfoWebsiteURLsByLocaleName, Iterable images, - Iterable videos, Iterable windFinderReviewedSpotCollectionIds) - throws UnauthorizedException, Exception; - - EventDTO createEvent(String eventName, String eventDescription, Date startDate, Date endDate, String venue, - boolean isPublic, List courseAreaNames, String officialWebsiteURL, String baseURLAsString, - Map sailorsInfoWebsiteURLsByLocaleName, Iterable images, - Iterable videos, Iterable leaderboardGroupIds) throws UnauthorizedException, Exception; - - void removeEvent(UUID eventId) throws UnauthorizedException; - - void removeEvents(Collection eventIds) throws UnauthorizedException; - - void renameEvent(UUID eventId, String newName) throws UnauthorizedException; - - EventDTO getEventById(UUID id, boolean withStatisticalData) throws UnauthorizedException, Exception; - Iterable getScoreCorrectionProviderNames() throws UnauthorizedException; ScoreCorrectionProviderDTO getScoreCorrectionsOfProvider(String providerName) @@ -475,9 +242,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS RegattaScoreCorrectionDTO getScoreCorrections(String scoreCorrectionProviderName, String eventName, String boatClassName, Date timePointWhenResultPublished) throws UnauthorizedException, Exception; - void updateLeaderboardScoreCorrectionsAndMaxPointsReasons(BulkScoreCorrectionDTO updates) - throws UnauthorizedException, NoWindException; - Iterable getCompetitorProviderNames() throws UnauthorizedException; CompetitorProviderDTO getCompetitorProviderDTOByName(String providerName) throws UnauthorizedException, Exception; @@ -500,36 +264,14 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS List getResultImportUrls(String resultProviderName) throws UnauthorizedException; - void removeResultImportURLs(String resultProviderName, Set toRemove) - throws UnauthorizedException, Exception; - - void addResultImportUrl(String resultProviderName, UrlDTO url) throws UnauthorizedException, Exception; - String validateResultImportUrl(String resultProviderName, UrlDTO urlDTO); - void updateLeaderboardScoreCorrectionMetadata(String leaderboardName, Date timePointOfLastCorrectionValidity, - String comment) throws UnauthorizedException; - List> getUrlResultProviderNamesAndOptionalSampleURL() throws UnauthorizedException; - void updateRaceCourse(RegattaAndRaceIdentifier raceIdentifier, - List> controlPoints) throws UnauthorizedException; - - void addColumnsToLeaderboard(String leaderboardName, List> columnsToAdd) - throws UnauthorizedException; - - void removeLeaderboardColumns(String leaderboardName, List columnsToRemove) throws UnauthorizedException; - StrippedLeaderboardDTO getLeaderboard(String leaderboardName) throws UnauthorizedException; StrippedLeaderboardDTOWithSecurity getLeaderboardWithSecurity(String leaderboardName) throws UnauthorizedException; - void suppressCompetitorInLeaderboard(String leaderboardName, String competitorIdAsString, boolean suppressed) - throws UnauthorizedException; - - void updateLeaderboardColumnFactor(String leaderboardName, String columnName, Double newFactor) - throws UnauthorizedException; - List listSwissTiminigReplayRaces(String swissTimingUrl) throws UnauthorizedException; List, List>> getLeaderboardDataEntriesForAllRaceColumns( @@ -539,24 +281,9 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS List getPreviousSwissTimingArchiveConfigurations() throws UnauthorizedException; - void createSwissTimingArchiveConfiguration(String jsonUrl) - throws UnauthorizedException, Exception; - - void updateSwissTimingArchiveConfiguration(SwissTimingArchiveConfigurationWithSecurityDTO dto) - throws UnauthorizedException, Exception; - - void deleteSwissTimingArchiveConfigurations(Collection dtos) - throws UnauthorizedException, Exception; - - void createCourseAreas(UUID eventId, String[] courseAreaNames) throws UnauthorizedException; - - void removeCourseAreas(UUID eventId, UUID[] courseAreaIds) throws UnauthorizedException; - List> getLeaderboardsNamesOfMetaLeaderboard(String metaLeaderboardName) throws UnauthorizedException; - LeaderboardType getLeaderboardType(String leaderboardName) throws UnauthorizedException; - /** for backward compatibility with the regatta overview */ List getRegattaStructureForEvent(UUID eventId) throws UnauthorizedException; @@ -564,10 +291,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS List visibleRegattas, boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay, Duration clientTimeZoneOffset) throws UnauthorizedException, Exception; - List getRaceStateEntriesForLeaderboard(String leaderboardName, - boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay, Duration clientTimeZoneOffset, - List visibleRegattas) throws UnauthorizedException, Exception; - void reloadRaceLog(String leaderboardName, RaceColumnDTO raceColumnDTO, FleetDTO fleet) throws UnauthorizedException, NotFoundException; @@ -579,12 +302,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS List getLeaderboardGroupNamesFromRemoteServer(String url, String username, String password) throws UnauthorizedException; - UUID importMasterData(String host, String[] groupNames, boolean override, boolean compress, boolean exportWind, - boolean exportDeviceConfigurations, String targetServerUsername, String targetServerPassword, - boolean exportTrackedRacesAndStartTracking) throws UnauthorizedException; - - DataImportProgress getImportOperationProgress(UUID id) throws UnauthorizedException; - Iterable getCompetitors(boolean filterCompetitorsWithBoat, boolean filterCompetitorsWithoutBoat) throws UnauthorizedException; @@ -593,43 +310,17 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS Map getCompetitorsAndBoatsOfRace(String leaderboardName, String raceColumnName, String fleetName) throws UnauthorizedException, NotFoundException; - List addOrUpdateCompetitors(List competitors) throws UnauthorizedException, Exception; - - CompetitorWithBoatDTO addOrUpdateCompetitorWithBoat(CompetitorWithBoatDTO competitor) - throws UnauthorizedException, Exception; - - CompetitorDTO addOrUpdateCompetitorWithoutBoat(CompetitorDTO competitor) throws UnauthorizedException, Exception; - - List addCompetitors(List competitorsForSaving, String searchTag) - throws UnauthorizedException, Exception; - - void allowCompetitorResetToDefaults(Iterable competitors) throws UnauthorizedException; - Iterable getAllBoats() throws UnauthorizedException; Iterable getStandaloneBoats() throws UnauthorizedException; - BoatDTO addOrUpdateBoat(BoatDTO boat) throws UnauthorizedException, Exception; - - void allowBoatResetToDefaults(Iterable boats) throws UnauthorizedException; - - boolean linkBoatToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, - String competitorIdAsString, String boatIdAsString) throws UnauthorizedException, NotFoundException; - - boolean unlinkBoatFromCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, - String competitorIdAsString) throws UnauthorizedException, NotFoundException; - BoatDTO getBoatLinkedToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString) throws UnauthorizedException, NotFoundException; List getDeviceConfigurations() throws UnauthorizedException; - DeviceConfigurationDTO getDeviceConfiguration(UUID id) throws UnauthorizedException; - void createOrUpdateDeviceConfiguration(DeviceConfigurationDTO configurationDTO) throws UnauthorizedException; - boolean removeDeviceConfiguration(UUID deviceConfigurationId) throws UnauthorizedException; - boolean setStartTimeAndProcedure(RaceLogSetStartTimeAndProcedureDTO dto) throws UnauthorizedException, NotFoundException; @@ -642,174 +333,9 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS Util.Triple getFinishingAndFinishTime(String leaderboardName, String raceColumnName, String fleetName) throws UnauthorizedException, NotFoundException; - Iterable getAllIgtimiAccountEmailAddresses() throws UnauthorizedException; - String getIgtimiAuthorizationUrl(String redirectProtocol, String redirectHostname, String redirectPort) throws UnauthorizedException, Exception; - boolean authorizeAccessToIgtimiUser(String eMailAddress, String password) throws UnauthorizedException, Exception; - - void removeIgtimiAccount(String eMailOfAccountToRemove) throws UnauthorizedException; - - Map importWindFromIgtimi(List selectedRaces, - boolean correctByDeclination) throws UnauthorizedException, Exception; - - Boolean denoteForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName) - throws UnauthorizedException, Exception; - - /** - * Revoke the {@link RaceLogDenoteForTrackingEvent}. This does not affect an existing {@code RaceLogRaceTracker} or - * {@link TrackedRace} for this {@code RaceLog}. - * - * @throws UnauthorizedException, - * NotFoundException - * - * @see RaceLogTrackingAdapter#removeDenotationForRaceLogTracking - */ - void removeDenotationForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName) - throws UnauthorizedException, NotFoundException; - - void denoteForRaceLogTracking(String leaderboardName) throws UnauthorizedException, Exception; - - void denoteForRaceLogTracking(String leaderboardName, String prefix) throws UnauthorizedException, Exception; - - /** - * Performs all the necessary steps to start tracking the race. The {@code RaceLog} needs to be denoted for - * racelog-tracking beforehand. - * - * @see RaceLogTrackingAdapter#startTracking - */ - void startRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName, boolean trackWind, - boolean correctWindByDeclination) - throws UnauthorizedException, NotDenotedForRaceLogTrackingException, Exception; - - void startRaceLogTracking(List> leaderboardRaceColumnFleetNames, boolean trackWind, - boolean correctWindByDeclination) - throws UnauthorizedException, NotDenotedForRaceLogTrackingException, Exception; - - void setCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName, - Set competitors) - throws UnauthorizedException, CompetitorRegistrationOnRaceLogDisabledException, NotFoundException; - - void setCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName, - Map competitorsAndBoats) - throws UnauthorizedException, CompetitorRegistrationOnRaceLogDisabledException, NotFoundException; - - /** - * Adds the course definition to the racelog, while trying to reuse existing marks, controlpoints and waypoints from - * the previous course definition in the racelog. - * - * @param priority - * TODO - * @throws UnauthorizedException, - * NotFoundException - */ - void addCourseDefinitionToRaceLog(String leaderboardName, String raceColumnName, String fleetName, - List> course, int priority) - throws UnauthorizedException, NotFoundException; - - /** - * Adds public tag as {@link RaceLogTagEvent} to {@link RaceLog} and private tag to - * {@link com.sap.sse.security.interfaces.UserStore UserStore}. - * - * @param leaderboardName - * required to identify {@link RaceLog}, must NOT be null - * @param raceColumnName - * required to identify {@link RaceLog}, must NOT be null - * @param fleetName - * required to identify {@link RaceLog}, must NOT be null - * @param tag - * title of tag, must NOT be null - * @param comment - * optional comment of tag - * @param imageURLs - * optional image URLs of tag - * @param visibleForPublic - * when set to true tag will be saved as public tag (visible for every user), when set to - * false tag will be saved as private tag (visible only for creator) - * @param raceTimepoint - * timepoint in race where user created tag, must NOT be null - * @return successful {@link SuccessInfo} if tag was added successfully, otherwise - * non-successful {@link SuccessInfo} - */ - SuccessInfo addTag(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment, - String imageURL, String resizedImageURL, boolean visibleForPublic, TimePoint raceTimepoint) - throws UnauthorizedException; - - /** - * Removes public {@link TagDTO tag} from {@link RaceLog} and private {@link TagDTO tag} from {@link UserStore}. - * - * @param leaderboardName - * required to identify {@link RaceLog}, must NOT be null - * @param raceColumnName - * required to identify {@link RaceLog}, must NOT be null - * @param fleetName - * required to identify {@link RaceLog}, must NOT be null - * @param tag - * tag to remove - * @return successful {@link SuccessInfo} if tag was removed successfully, otherwise - * non-successful {@link SuccessInfo} - */ - SuccessInfo removeTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag) - throws UnauthorizedException; - - /** - * Updates given tagToUpdate with the given attributes tag, comment, - * imageURL and visibleForPublic. Tags are not really updated, instead public tags are - * revoked/private tags removed first and then the new tags gets saved depending on the new value - * visibleForPublic. - * - * @param leaderboardName - * required to identify {@link RaceLog}, must NOT be null - * @param raceColumnName - * required to identify {@link RaceLog}, must NOT be null - * @param fleetName - * required to identify {@link RaceLog}, must NOT be null - * @param tagToUpdate - * tag to be updated - * @param tag - * new tag title - * @param comment - * new comment - * @param imageURL - * new image url - * @param visibleForPublic - * new visibility status - * @return successful {@link SuccessInfo} if tag was updated successfully, otherwise - * non-successful {@link SuccessInfo} - */ - SuccessInfo updateTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tagToUpdate, - String tag, String comment, String imageURL, String resizedImageURL, boolean visibleForPublic) - throws UnauthorizedException; - - /** - * Returns all public and private tags of specified race and current user. - * - * @param leaderboardName - * required to identify {@link RaceLog}, must NOT be null - * @param raceColumnName - * required to identify {@link RaceLog}, must NOT be null - * @param fleetName - * required to identify {@link RaceLog}, must NOT be null - * @return list of {@link TagDTO tags} - */ - List getAllTags(String leaderboardName, String raceColumnName, String fleetName) - throws UnauthorizedException; - - /** - * Returns all public {@link TagDTO tags} of specified race. - * - * @param leaderboardName - * required to identify {@link RaceLog}, must NOT be null - * @param raceColumnName - * required to identify {@link RaceLog}, must NOT be null - * @param fleetName - * required to identify {@link RaceLog}, must NOT be null - * @return list of public {@link TagDTO tags} - */ - List getPublicTags(String leaderboardName, String raceColumnName, String fleetName) - throws UnauthorizedException; - /** * Returns all private {@link TagDTO tags} of specified race and current user. * @@ -827,30 +353,8 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS RaceCourseDTO getLastCourseDefinitionInRaceLog(String leaderboardName, String raceColumnName, String fleetName) throws UnauthorizedException, NotFoundException; - /** - * Adds a fix to the {@link SensorFixStore}, and creates a mapping with a virtual device for exactly the current - * timepoint. - * - * @param timePoint - * the time point for the fix; if {@code null}, the current time is used - * - * @throws DoesNotHaveRegattaLogException - * @throws NotFoundException - */ - void pingMark(String leaderboardName, MarkDTO mark, TimePoint timePoint, Position position) - throws UnauthorizedException, DoesNotHaveRegattaLogException, NotFoundException; - List getDeserializableDeviceIdentifierTypes() throws UnauthorizedException; - /** - * Revoke the events in the {@code RaceLog} that are identified by the {@code eventIds}. This only affects such - * events that implement {@link Revokable}. - * - * @throws NotFoundException - */ - void revokeRaceAndRegattaLogEvents(String leaderboardName, String raceColumnName, String fleetName, - List eventIds) throws UnauthorizedException, NotRevokableException, NotFoundException; - Collection getGPSFixImporterTypes() throws UnauthorizedException; Collection getSensorDataImporterTypes() throws UnauthorizedException; @@ -858,14 +362,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS List getTrackFileImportDeviceIds(List uuids) throws NoCorrespondingServiceRegisteredException, TransformationException; - /** - * @return The RaceDTO of the modified race or null, if the given newStartTimeReceived was null. - */ - RaceDTO setStartTimeReceivedForRace(RaceIdentifier raceIdentifier, Date newStartTimeReceived) - throws UnauthorizedException; - - PolarSheetsXYDiagramData createXYDiagramForBoatClass(String itemText) throws UnauthorizedException; - /** * @see SailingServiceAsync#getCompetitorMarkPassings(RegattaAndRaceIdentifier, CompetitorWithBoatDTO, boolean, * com.google.gwt.user.client.rpc.AsyncCallback) @@ -884,17 +380,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS Map getCompetitorRaceLogMarkPassingData(String leaderboardName, String raceColumnName, String fleetName, CompetitorDTO competitor) throws UnauthorizedException, NotFoundException; - void updateSuppressedMarkPassings(String leaderboardName, String raceColumnName, String fleetName, - Integer newZeroBasedIndexOfSuppressedMarkPassing, CompetitorDTO competitorDTO) - throws UnauthorizedException, NotFoundException; - - void updateFixedMarkPassing(String leaderboardName, String raceColumnName, String fleetName, - Integer indexOfWaypoint, Date dateOfMarkPassing, CompetitorDTO competitorDTO) - throws UnauthorizedException, NotFoundException; - - void setCompetitorRegistrationsInRegattaLog(String leaderboardName, Set competitors) - throws UnauthorizedException, DoesNotHaveRegattaLogException, NotFoundException; - /** * A leaderboard may be situated under multiple events (connected via a leaderboardgroup). This method traverses all * events and leaderboardgroup to build the collection of events this leaderboard is coupled to. @@ -909,75 +394,21 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS */ Iterable getRegattas(String manage2SailJsonUrl) throws UnauthorizedException; - void createRegattaStructure(Iterable regattas, EventDTO newEvent) - throws UnauthorizedException, Exception; - - Integer getStructureImportOperationProgress() throws UnauthorizedException; - - void inviteCompetitorsForTrackingViaEmail(String serverUrlWithoutTrailingSlash, EventDTO event, - String leaderboardName, Collection competitors, String iOSAppUrl, String androidAppUrl, - String localeInfo) throws UnauthorizedException, MailException; - - void inviteBuoyTenderViaEmail(String serverUrlWithoutTrailingSlash, EventDTO eventDto, String leaderboardName, - String emails, String iOSAppUrl, String androidAppUrl, String localeInfoName) - throws UnauthorizedException, MailException; - - ArrayList getLeaderboardGroupsByEventId(UUID id) throws UnauthorizedException; - Iterable getMarksInRegattaLog(String leaderboardName) throws UnauthorizedException, DoesNotHaveRegattaLogException; List getDeviceMappings(String leaderboardName) throws UnauthorizedException, DoesNotHaveRegattaLogException, TransformationException, NotFoundException; - void revokeRaceAndRegattaLogEvents(String leaderboardName, List eventIds) - throws UnauthorizedException, NotRevokableException, DoesNotHaveRegattaLogException, NotFoundException; - - void closeOpenEndedDeviceMapping(String leaderboardName, DeviceMappingDTO mappingDto, Date closingTimePoint) - throws UnauthorizedException, TransformationException, DoesNotHaveRegattaLogException, - UnableToCloseDeviceMappingException, NotFoundException; - - void addDeviceMappingToRegattaLog(String leaderboardName, DeviceMappingDTO dto) throws UnauthorizedException, - NoCorrespondingServiceRegisteredException, TransformationException, DoesNotHaveRegattaLogException; - - void addTypedDeviceMappingToRegattaLog(String leaderboardName, TypedDeviceMappingDTO dto) - throws UnauthorizedException, NoCorrespondingServiceRegisteredException, TransformationException, - DoesNotHaveRegattaLogException, NotFoundException; - boolean doesRegattaLogContainCompetitors(String name) throws UnauthorizedException, DoesNotHaveRegattaLogException, NotFoundException; RegattaAndRaceIdentifier getRaceIdentifier(String regattaLikeName, String raceColumnName, String fleetName) throws UnauthorizedException; - void setTrackingTimes(RaceLogSetTrackingTimesDTO dto) throws UnauthorizedException, NotFoundException; - Pair getTrackingTimes(String leaderboardName, String raceColumnName, String fleetName) throws UnauthorizedException, NotFoundException; - /** - * @param raceLogFrom - * identifies the race log to copy from by its leaderboard name, race column name and fleet name - * @param raceLogsTo - * identifies the race log to copy from by their leaderboard name, race column name and fleet name - * @throws NotFoundException - */ - void copyCompetitorsToOtherRaceLogs(Triple fromTriple, - Set> toTriples) throws UnauthorizedException, NotFoundException; - - /** - * @param priority - * TODO - * @param raceLogFrom - * identifies the race log to copy from by its leaderboard name, race column name and fleet name - * @param raceLogsTo - * identifies the race log to copy from by their leaderboard name, race column name and fleet name - * @throws NotFoundException - */ - void copyCourseToOtherRaceLogs(Triple fromTriple, - Set> toTriples, int priority) - throws UnauthorizedException, NotFoundException; - /** * Get the competitors registered for a certain race. This automatically checks, whether competitors are registered * in the raceLog (in case of e.g. splitFleets) or in the RegattaLog (default) @@ -987,33 +418,18 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS Collection getCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) throws UnauthorizedException, DoesNotHaveRegattaLogException, NotFoundException; - void addMarkToRegattaLog(String leaderboardName, MarkDTO mark) - throws UnauthorizedException, DoesNotHaveRegattaLogException; - - void revokeMarkDefinitionEventInRegattaLog(String leaderboardName, MarkDTO markDTO) - throws UnauthorizedException, DoesNotHaveRegattaLogException, NotFoundException; - Collection getCompetitorRegistrationsInRegattaLog(String leaderboardName) throws UnauthorizedException, DoesNotHaveRegattaLogException, NotFoundException; Collection getBoatRegistrationsInRegattaLog(String leaderboardName) throws UnauthorizedException, DoesNotHaveRegattaLogException, NotFoundException; - void setBoatRegistrationsInRegattaLog(String leaderboardName, Set boats) - throws UnauthorizedException, DoesNotHaveRegattaLogException, NotFoundException; - Collection getBoatRegistrationsForLeaderboard(String leaderboardName) throws UnauthorizedException, NotFoundException; Boolean areCompetitorRegistrationsEnabledForRace(String leaderboardName, String raceColumnName, String fleetName) throws UnauthorizedException, NotFoundException; - void disableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) - throws UnauthorizedException, NotRevokableException, NotFoundException; - - void enableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) - throws UnauthorizedException, IllegalArgumentException, NotFoundException; - Pair checkIfMarksAreUsedInOtherRaceLogs(String leaderboardName, String raceColumnName, String fleetName, Set marksToRemove) throws UnauthorizedException, NotFoundException; @@ -1029,9 +445,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS Iterable getMarksInTrackedRace(String leaderboardName, String raceColumnName, String fleetName) throws UnauthorizedException; - MarkTracksDTO getMarkTracks(String leaderboardName, String raceColumnName, String fleetName) - throws UnauthorizedException; - MarkTrackDTO getMarkTrack(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString) throws UnauthorizedException; @@ -1042,15 +455,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS boolean canRemoveMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, GPSFixDTO fix) throws UnauthorizedException; - void removeMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, - GPSFixDTO fix) throws UnauthorizedException, NotRevokableException; - - void addMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, - GPSFixDTO newFix) throws UnauthorizedException; - - void editMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, - GPSFixDTO oldFix, Position newPosition) throws UnauthorizedException, NotRevokableException; - Map, Pair> getTrackingTimes( Collection> raceColumnsAndFleets) throws UnauthorizedException; @@ -1060,9 +464,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS Collection getEliminatedCompetitors(String leaderboardName) throws UnauthorizedException; - void setEliminatedCompetitors(String leaderboardName, Set eliminatedCompetitors) - throws UnauthorizedException, NotFoundException; - /** * Used to determine for a Chart the available Detailtypes. This is for example used to only show the RideHeight as * an option for charts if it actually recorded for the race. @@ -1072,12 +473,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS List getExpeditionDeviceConfigurations() throws UnauthorizedException; - void addOrReplaceExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration expeditionDeviceConfiguration) - throws UnauthorizedException; - - void removeExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration expeditionDeviceConfiguration) - throws UnauthorizedException; - /** * @throws NotFoundException * is thrown if the leaderboard is not found by name @@ -1092,10 +487,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS PairingListDTO getPairingListFromRaceLogs(String leaderboardName) throws UnauthorizedException, NotFoundException; - void fillRaceLogsFromPairingListTemplate(String leaderboardName, int flightMultiplier, - Iterable selectedFlightNames, PairingListDTO pairingListDTO) - throws UnauthorizedException, NotFoundException, CompetitorRegistrationOnRaceLogDisabledException; - List getRaceDisplayNamesFromLeaderboard(String leaderboardName, List raceColumnNames) throws UnauthorizedException, NotFoundException; @@ -1104,21 +495,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS SpotDTO getWindFinderSpot(String spotId) throws UnauthorizedException, Exception; - /** - * Returns {@code true} if the given race can be sliced. Only Smarthphone tracked races can be sliced. In addition - * the race must be part of a {@link RegattaLeaderboard}. - */ - boolean canSliceRace(RegattaAndRaceIdentifier raceIdentifier) throws UnauthorizedException; - - /** - * Slices a new race from the race specified by the given {@link RegattaAndRaceIdentifier} using the given time - * range. A new {@link RaceColumn} with the given name is added to the {@link RegattaLeaderboard}. - * - * @throws ServiceException - */ - RegattaAndRaceIdentifier sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName, - TimePoint sliceFrom, TimePoint sliceTo) throws UnauthorizedException, ServiceException; - /** * Returns specific data needed for the slicing UI. */ @@ -1130,25 +506,7 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS */ Boolean checkIfRaceIsTracking(RegattaAndRaceIdentifier race) throws UnauthorizedException; - /** - * Resizes an {@Link ImageDTO} that is part of an {@link ImageResizingTaskDTO} into a set of resized versions. This - * set only contains one image in most cases, because most {@Link ImageDTO} only hold one predefined - * {@link MediaTagConstants}. All {@link MediaTagConstants} stored in the resizingTask of the - * {@link ImageResizingTaskDTO} create a resize. Since no {@link MediaTagConstants} have the same defined bounds, - * there will be no merge of these {@Link ImageDTO}. Uses the {@link FileStorageService} to store the resized - * images. If an error occurs during resize or storing process, it will be tried to restore the previous state. - * - * @author Robin Fleige (D067799) - * - * @param imageResizingTask - * is an {@link ImageResizingTaskDTO} with the information on how the image saved in the {@Link ImageDTO} - * should be resized. The resizingTask attribute should not be null or empty at this point - * @return returns a set of {@Link ImageDTO}, that contain the resized variants of the {@Link ImageDTO} in - * toResizeImage - * @throws UnauthorizedException, - * Exception can throw different type of exceptions - */ - Set resizeImage(ImageResizingTaskDTO imageResizingTask) throws UnauthorizedException, Exception; + MailInvitationType getMailType() throws UnauthorizedException; @@ -1161,16 +519,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS */ String openRegattaRegistrationQrCode(String url) throws UnauthorizedException; - List getPossibleTennants() throws UnauthorizedException; - - void updateGroupOwnerForEventHierarchy(UUID eventId, - MigrateGroupOwnerForHierarchyDTO migrateGroupOwnerForHierarchyDTO) throws UnauthorizedException; - - void updateGroupOwnerForLeaderboardGroupHierarchy(UUID leaderboardGroupId, - MigrateGroupOwnerForHierarchyDTO migrateGroupOwnerForHierarchyDTO) throws UnauthorizedException; - - String getSecretForRegattaByName(String regattaName) throws UnauthorizedException; - Iterable getAllIgtimiAccountsWithSecurity() throws UnauthorizedException; /** @@ -1187,6 +535,8 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS * Allows reading public Events, or Events that are related to the given regatta */ QRCodeEvent getEvent(UUID eventId, String regattaName, String regattaRegistrationLinkSecret); + + EventDTO getEventById(UUID id, boolean withStatisticalData) throws IOException, UnauthorizedException; /** * Allows reading public Competitors, or Competitors that are registered in the given regatta @@ -1194,12 +544,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS CompetitorDTO getCompetitor(UUID competitorId, String leaderboardName, String regattaRegistrationLinkSecret); - boolean existsSwissTimingConfigurationForCurrentUser(String jsonUrl) throws Exception, UnauthorizedException; - - boolean existsSwissTimingArchiveConfigurationForCurrentUser(String jsonUrl) throws Exception, UnauthorizedException; - - boolean existsTracTracConfigurationForCurrentUser(String jsonUrl) throws Exception, UnauthorizedException; - boolean getTrackedRaceIsUsingMarkPassingCalculator(RegattaAndRaceIdentifier regattaNameAndRaceName); ORCPerformanceCurveLegImpl[] getLegGeometry(String leaderboardName, String raceColumnName, String fleetName, @@ -1217,54 +561,14 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS Map getORCPerformanceCurveLegInfo(RegattaAndRaceIdentifier singleSelectedRace); - /** - * Into the first {@link RaceLog} {@link TrackedRace#getAttachedRaceLogs() attached} to the tracked race identified by - * {@code raceIdentifier} writes {@link RaceLogORCLegDataEvent}s and/or revokation events such that afterwards the - * {@link #getORCPerformanceCurveLegInfo(RegattaAndRaceIdentifier)} will return a map equal to the one passed, except - * for {@code null} values which then would be missing from the results, where here they mean to explicitly revoke any - * previous setting for that leg. - */ - void setORCPerformanceCurveLegInfo(RegattaAndRaceIdentifier raceIdentifier, Map legInfo) throws NotRevokableException; - - /** - * Into the {@link RaceLog} identified by the leaderboard, race column and fleet names, writes - * {@link RaceLogORCLegDataEvent}s and/or revokation events such that afterwards the - * {@link #getORCPerformanceCurveLegInfo(RegattaAndRaceIdentifier)} will return a map equal to the one passed, - * except for {@code null} values which then would be missing from the results, where here they mean to explicitly - * revoke any previous setting for that leg. - * - * @throws NotFoundException - * in case the race log cannot be found by the leaderboard, race column and fleet names provided - */ - void setORCPerformanceCurveLegInfo(String leaderboardName, String raceColumnName, String fleetName, Map legInfo) throws NotFoundException, NotRevokableException; - Collection getBoatRegistrationsForRegatta(RegattaIdentifier regattaIdentifier) throws NotFoundException; Collection getORCCertificates(String json) throws Exception; Map getORCCertificateAssignmentsByBoatIdAsString(RegattaIdentifier regattaIdentifier) throws NotFoundException; - Map getORCCertificateAssignmentsByBoatIdAsString(RegattaAndRaceIdentifier raceIdentifier) throws NotFoundException; - - Map getORCCertificateAssignmentsByBoatIdAsString(String leaderboardName) throws NotFoundException; - Map getORCCertificateAssignmentsByBoatIdAsString(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException; - Triple assignORCPerformanceCurveCertificates(RegattaIdentifier regattaIdentifier, - Map certificatesForBoatsWithIdAsString) throws IOException, NotFoundException; - - Triple assignORCPerformanceCurveCertificates(RegattaAndRaceIdentifier raceIdentifier, Map certificatesForBoatsWithIdAsString) throws IOException, NotFoundException; - - Triple assignORCPerformanceCurveCertificates(String leaderboardName, String raceColumnName, String fleetName, Map certificatesForBoatsWithIdAsString) throws IOException, NotFoundException; - - Triple assignORCPerformanceCurveCertificates(String leaderboardName, - Map certificatesForBoatsWithIdAsString) throws IOException, NotFoundException; - - CompetitorDTO getORCPerformanceCurveScratchBoat(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException; - - void setORCPerformanceCurveScratchBoat(String leaderboardName, String raceColumnName, String fleetName, - CompetitorDTO newScratchBoat) throws NotFoundException; - ImpliedWindSource getImpliedWindSource(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException; void setImpliedWindSource(String leaderboardName, String raceColumnName, String fleetName, @@ -1277,26 +581,10 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS List getMarkTemplates(); - MarkTemplateDTO addOrUpdateMarkTemplate(MarkTemplateDTO markTemplate); - - MarkPropertiesDTO addOrUpdateMarkProperties(MarkPropertiesDTO markProperties); - - MarkPropertiesDTO updateMarkPropertiesPositioning(UUID markPropertiesId, DeviceIdentifierDTO deviceIdentifier, Position position); - List getMarkProperties(); - /** - * Removes mark properties list - * - * @param markPropertiesDTOS - * list of mark properties to remove - */ - void removeMarkProperties(Collection markPropertiesUuids); - List getCourseTemplates(); - CourseTemplateDTO createOrUpdateCourseTemplate(CourseTemplateDTO courseTemplate); - /** * Removes course templates list * @@ -1307,5 +595,4 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS List getMarkRoles(); - MarkRoleDTO createMarkRole(MarkRoleDTO markRole); } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java index 773a9869d87..5db26ee870d 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java @@ -9,29 +9,14 @@ import java.util.Map; import java.util.Set; import java.util.UUID; -import org.apache.shiro.authz.AuthorizationException; - import com.google.gwt.user.client.rpc.AsyncCallback; -import com.sap.sailing.domain.base.Fleet; -import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.common.CompetitorDescriptor; -import com.sap.sailing.domain.common.CompetitorRegistrationType; -import com.sap.sailing.domain.common.DataImportProgress; import com.sap.sailing.domain.common.DetailType; -import com.sap.sailing.domain.common.LeaderboardType; import com.sap.sailing.domain.common.LegIdentifier; import com.sap.sailing.domain.common.MailInvitationType; -import com.sap.sailing.domain.common.MaxPointsReason; -import com.sap.sailing.domain.common.PassingInstruction; -import com.sap.sailing.domain.common.PolarSheetsXYDiagramData; -import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.RaceIdentifier; -import com.sap.sailing.domain.common.RankingMetrics; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.RegattaIdentifier; -import com.sap.sailing.domain.common.RegattaName; -import com.sap.sailing.domain.common.RegattaNameAndRaceName; -import com.sap.sailing.domain.common.ScoringSchemeType; import com.sap.sailing.domain.common.WindSource; import com.sap.sailing.domain.common.abstractlog.TimePointSpecificationFoundInLog; import com.sap.sailing.domain.common.dto.BoatDTO; @@ -45,9 +30,6 @@ import com.sap.sailing.domain.common.dto.PairingListDTO; import com.sap.sailing.domain.common.dto.PairingListTemplateDTO; import com.sap.sailing.domain.common.dto.PersonDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTO; -import com.sap.sailing.domain.common.dto.RaceColumnInSeriesDTO; -import com.sap.sailing.domain.common.dto.RaceDTO; -import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO; import com.sap.sailing.domain.common.dto.TagDTO; import com.sap.sailing.domain.common.impl.KilometersPerHourSpeedImpl; import com.sap.sailing.domain.common.impl.KnotSpeedImpl; @@ -61,21 +43,15 @@ import com.sap.sailing.domain.common.tracking.impl.PreciseCompactGPSFixMovingImp import com.sap.sailing.domain.common.windfinder.SpotDTO; import com.sap.sailing.domain.tracking.TrackedRace; import com.sap.sailing.expeditionconnector.ExpeditionDeviceConfiguration; -import com.sap.sailing.gwt.ui.adminconsole.RaceLogSetTrackingTimesDTO; import com.sap.sailing.gwt.ui.client.shared.charts.MarkPositionService.MarkTrackDTO; -import com.sap.sailing.gwt.ui.client.shared.charts.MarkPositionService.MarkTracksDTO; import com.sap.sailing.gwt.ui.shared.AccountWithSecurityDTO; -import com.sap.sailing.gwt.ui.shared.BulkScoreCorrectionDTO; import com.sap.sailing.gwt.ui.shared.CompactBoatPositionsDTO; import com.sap.sailing.gwt.ui.shared.CompactRaceMapDataDTO; import com.sap.sailing.gwt.ui.shared.CompetitorProviderDTO; import com.sap.sailing.gwt.ui.shared.CompetitorsRaceDataDTO; -import com.sap.sailing.gwt.ui.shared.ControlPointDTO; import com.sap.sailing.gwt.ui.shared.CoursePositionsDTO; import com.sap.sailing.gwt.ui.shared.DeviceConfigurationDTO; -import com.sap.sailing.gwt.ui.shared.DeviceConfigurationDTO.RegattaConfigurationDTO; import com.sap.sailing.gwt.ui.shared.DeviceConfigurationWithSecurityDTO; -import com.sap.sailing.gwt.ui.shared.DeviceIdentifierDTO; import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO; import com.sap.sailing.gwt.ui.shared.EventDTO; import com.sap.sailing.gwt.ui.shared.GPSFixDTO; @@ -83,7 +59,6 @@ import com.sap.sailing.gwt.ui.shared.GPSFixDTOWithSpeedWindTackAndLegType; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; import com.sap.sailing.gwt.ui.shared.ManeuverDTO; import com.sap.sailing.gwt.ui.shared.MarkDTO; -import com.sap.sailing.gwt.ui.shared.MigrateGroupOwnerForHierarchyDTO; import com.sap.sailing.gwt.ui.shared.QRCodeEvent; import com.sap.sailing.gwt.ui.shared.RaceCourseDTO; import com.sap.sailing.gwt.ui.shared.RaceGroupDTO; @@ -108,15 +83,11 @@ import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTOWithSecurity; import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationWithSecurityDTO; import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationWithSecurityDTO; import com.sap.sailing.gwt.ui.shared.SwissTimingEventRecordDTO; -import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDTO; import com.sap.sailing.gwt.ui.shared.SwissTimingReplayRaceDTO; import com.sap.sailing.gwt.ui.shared.TracTracConfigurationWithSecurityDTO; import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDTO; import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO; -import com.sap.sailing.gwt.ui.shared.TypedDeviceMappingDTO; import com.sap.sailing.gwt.ui.shared.UrlDTO; -import com.sap.sailing.gwt.ui.shared.VenueDTO; -import com.sap.sailing.gwt.ui.shared.WindDTO; import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO; import com.sap.sailing.gwt.ui.shared.courseCreation.CourseTemplateDTO; import com.sap.sailing.gwt.ui.shared.courseCreation.MarkPropertiesDTO; @@ -130,25 +101,18 @@ import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.Util.Triple; import com.sap.sse.common.impl.SecondsDurationImpl; -import com.sap.sse.gwt.client.filestorage.FileStorageManagementGwtServiceAsync; -import com.sap.sse.gwt.client.media.ImageDTO; -import com.sap.sse.gwt.client.media.ImageResizingTaskDTO; -import com.sap.sse.gwt.client.media.VideoDTO; import com.sap.sse.gwt.client.replication.RemoteReplicationServiceAsync; import com.sap.sse.pairinglist.PairingList; import com.sap.sse.pairinglist.PairingListTemplate; import com.sap.sse.security.shared.TypeRelativeObjectIdentifier; -import com.sap.sse.security.ui.shared.SuccessInfo; /** * The async counterpart of {@link SailingService} */ -public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsync, RemoteReplicationServiceAsync { +public interface SailingServiceAsync extends RemoteReplicationServiceAsync { void getRegattas(AsyncCallback> callback); - void getRegattasWithUpdatePermission(AsyncCallback> callback); - void getRegattaByName(String regattaName, AsyncCallback asyncCallback); /** @@ -159,67 +123,12 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void listTracTracRacesInEvent(String eventJsonURL, boolean listHiddenRaces, AsyncCallback>> callback); - /** - * @param regattaToAddTo - * if null, the regatta into which the race has previously been loaded will be looked up; if - * found, the race will be loaded into that regatta; otherwise, an existing regatta by the name of the - * TracTrac event with the boat class name appended in parentheses will be looked up; if not found, a - * default regatta with that name will be created, with a single default series and a single default - * fleet. If a valid {@link RegattaIdentifier} is specified, a regatta lookup is performed with that - * identifier; if the regatta is found, it is used to add the races to. Otherwise, a default regatta as - * described above will be created and used. - * @param liveURI - * may be null or the empty string in which case the server will use the - * {@link TracTracRaceRecordDTO#liveURI} from the rr race record. - * @param offsetToStartTimeOfSimulatedRace - * if not null, the connector will adjust the time stamps of all events received such that - * the first mark passing for the first waypoint will be set to "now." It will delay the forwarding of - * all events received such that they seem to be sent in "real-time" plus the - * offsetToStartTimeOfSimulatedRace. So, more or less the time points attached to the events - * sent to the receivers will again approximate the wall time. - * @param useInternalMarkPassingAlgorithm - * whether or not to ignore the TracTrac-provided mark passings; if true, a separate mark - * passing calculator is used, and the TracTrac-provided ones are ignored. - * @param storedURImay - * be null or the empty string in which case the server will use the - * {@link TracTracRaceRecordDTO#storedURI} from the rr race record. - */ - void trackWithTracTrac(RegattaIdentifier regattaToAddTo, Iterable rrs, String liveURI, - String storedURI, String courseDesignUpdateURI, boolean trackWind, boolean correctWindByDeclination, - Duration offsetToStartTimeOfSimulatedRace, boolean useInternalMarkPassingAlgorithm, - boolean useOfficialEventsToUpdateRaceLog, String tracTracUsername, - String tracTracPassword, AsyncCallback callback); - - void trackWithSwissTiming(RegattaIdentifier regattaToAddTo, Iterable rrs, String hostname, - int port, boolean trackWind, boolean correctWindByDeclination, boolean useInternalMarkPassingAlgorithm, - String updateURL, String updateUsername, String updatePassword, String eventName, - String manage2SailEventUrl, AsyncCallback asyncCallback); - void replaySwissTimingRace(RegattaIdentifier regattaIdentifier, Iterable replayRaces, boolean trackWind, boolean correctWindByDeclination, boolean useInternalMarkPassingAlgorithm, AsyncCallback asyncCallback); void getPreviousTracTracConfigurations(AsyncCallback> callback); - void createTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI, - String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword, AsyncCallback callback); - - void deleteTracTracConfigurations(Collection tracTracConfigurations, - AsyncCallback callback); - - void updateTracTracConfiguration(TracTracConfigurationWithSecurityDTO tracTracConfiguration, - AsyncCallback callback); - - void stopTrackingRaces(Iterable racesToStopTracking, AsyncCallback asyncCallback); - - /** - * Untracks the race and removes it from the regatta. It will also be removed in all leaderboards - * - * @param regattaNamesAndRaceNames - * The identifier for the regatta name, and the race name to remove - */ - void removeAndUntrackRaces(Iterable regattaNamesAndRaceNames, AsyncCallback callback); - void getRawWindFixes(RegattaAndRaceIdentifier raceIdentifier, Collection windSources, AsyncCallback callback); @@ -239,15 +148,6 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn long resolutionInMilliseconds, Collection windSourceTypeNames, boolean onlyUpToNewestEvent, AsyncCallback callback); - /** - * @param windSourceTypeNames - * if null, data from all available wind sources will be returned, otherwise only from those - * whose {@link WindSource} name is contained in the windSources collection. - */ - void getAveragedWindInfo(RegattaAndRaceIdentifier raceIdentifier, Date from, long millisecondsStepWidth, - int numberOfFixes, double latDeg, double lngDeg, Collection windSourceTypeNames, - AsyncCallback callback); - /** * @param onlyUpToNewestEvent * if true, no wind data will be returned for time points later than @@ -268,10 +168,6 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getSimulatorResults(LegIdentifier legIdentifier, AsyncCallback callback); - void setWind(RegattaAndRaceIdentifier raceIdentifier, WindDTO wind, AsyncCallback callback); - - void removeWind(RegattaAndRaceIdentifier raceIdentifier, WindDTO windDTO, AsyncCallback callback); - void getRaceTimesInfo(RegattaAndRaceIdentifier raceIdentifier, AsyncCallback callback); void getRaceTimesInfoIncludingTags(RegattaAndRaceIdentifier raceIdentifier, TimePoint searchSince, @@ -286,6 +182,8 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getCoursePositions(RegattaAndRaceIdentifier raceIdentifier, Date date, AsyncCallback asyncCallback); + void getCourseAreas(String leaderboardName, AsyncCallback> callback); + void getLeaderboardByName(String leaderboardName, Date date, Collection namesOfRaceColumnsForWhichToLoadLegDetails, boolean addOverallDetails, String previousLeaderboardId, boolean fillTotalPointsUncorrected, @@ -300,43 +198,6 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getLeaderboardsWithSecurity(AsyncCallback> callback); - void getLeaderboardsByRaceAndRegatta(String raceName, RegattaIdentifier regattaIdentifier, - AsyncCallback> callback); - - void updateLeaderboard(String leaderboardName, String newLeaderboardName, String newLeaderboardDisplayName, - int[] newDiscardingThreasholds, Iterable newCourseAreaIds, - AsyncCallback callback); - - void createFlexibleLeaderboard(String leaderboardName, String leaderboardDisplayName, - int[] discardThresholds, - ScoringSchemeType scoringSchemeType, Iterable courseAreaIds, - AsyncCallback asyncCallback); - - void createRegattaLeaderboard(RegattaName regattaIdentifier, - String leaderboardDisplayName, - int[] discardThresholds, AsyncCallback asyncCallback); - - void createRegattaLeaderboardWithEliminations(String name, String displayName, - String regattaName, - AsyncCallback asyncCallback); - - void removeLeaderboard(String leaderboardName, AsyncCallback asyncCallback); - - void removeLeaderboards(Collection leaderboardNames, AsyncCallback asyncCallback); - - void renameLeaderboard(String leaderboardName, String newLeaderboardName, AsyncCallback asyncCallback); - - void addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace, - AsyncCallback callback); - - void renameLeaderboardColumn(String leaderboardName, String oldColumnName, String newColumnName, - AsyncCallback callback); - - void removeLeaderboardColumn(String leaderboardName, String columnName, AsyncCallback callback); - - void connectTrackedRaceToLeaderboardColumn(String leaderboardName, String raceColumnName, String fleetName, - RegattaAndRaceIdentifier raceIdentifier, AsyncCallback asyncCallback); - /** * The key set of the map returned contains all fleets of the race column identified by the combination of * leaderboardName and raceColumnName. If a value is null, there is no @@ -347,55 +208,10 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getRegattaAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(String leaderboardName, String raceColumnName, AsyncCallback> callback); - void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName, String fleetName, - AsyncCallback callback); - - void updateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Double carriedPoints, - AsyncCallback callback); - - void updateLeaderboardMaxPointsReason(String leaderboardName, String competitorIdAsString, String raceColumnName, - MaxPointsReason maxPointsReason, Date date, - AsyncCallback> asyncCallback); - - void updateLeaderboardScoreCorrection(String leaderboardName, String competitorIdAsString, String columnName, - Double correctedScore, Date date, AsyncCallback> asyncCallback); - - void updateLeaderboardScoreCorrectionMetadata(String leaderboardName, Date timePointOfLastCorrectionValidity, - String comment, AsyncCallback callback); - - void updateLeaderboardScoreCorrectionsAndMaxPointsReasons(BulkScoreCorrectionDTO updates, - AsyncCallback callback); - - void updateCompetitorDisplayNameInLeaderboard(String leaderboardName, String competitorID, String displayName, - AsyncCallback callback); - - void moveLeaderboardColumnUp(String leaderboardName, String columnName, AsyncCallback callback); - - void moveLeaderboardColumnDown(String leaderboardName, String columnName, AsyncCallback callback); - - void updateIsMedalRace(String leaderboardName, String columnName, boolean isMedalRace, AsyncCallback callback); - - void updateRaceDelayToLive(RegattaAndRaceIdentifier regattaAndRaceIdentifier, long delayToLiveInMs, - AsyncCallback callback); - - void updateRacesDelayToLive(List regattaAndRaceIdentifiers, long delayToLiveInMs, - AsyncCallback callback); - void getPreviousSwissTimingConfigurations(AsyncCallback> asyncCallback); void getRacesOfSwissTimingEvent(String eventJsonUrl, AsyncCallback asyncCallback); - void createSwissTimingConfiguration(String configName, String jsonURL, String hostname, Integer port, - String updateURL, String updateUsername, String updatePassword, AsyncCallback asyncCallback); - - void updateSwissTimingConfiguration(SwissTimingConfigurationWithSecurityDTO configuration, - AsyncCallback asyncCallback); - - void deleteSwissTimingConfigurations(Collection configurations, - AsyncCallback asyncCallback); - - void getCountryCodes(AsyncCallback callback); - void getDouglasPoints(RegattaAndRaceIdentifier raceIdentifier, Map competitorTimeRanges, double meters, AsyncCallback>> callback); @@ -407,36 +223,6 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getLeaderboardGroupByName(String groupName, boolean withGeoLocationData, AsyncCallback callback); - /** - * Renames the group with the name oldName to the newName.
    - * If there's no group with the name oldName or there's already a group with the name - * newName a {@link IllegalArgumentException} is thrown. - */ - void renameLeaderboardGroup(String oldName, String newName, AsyncCallback callback); - - /** - * Removes the leaderboard groups with the given names from the service and the persistant store. - */ - void removeLeaderboardGroups(Set groupNames, AsyncCallback asyncCallback); - - /** - * Creates a new group with the name groupname, the description description and an empty - * list of leaderboards.
    - */ - void createLeaderboardGroup(String groupName, String description, String displayName, - boolean displayGroupsInReverseOrder, int[] overallLeaderboardDiscardThresholds, - ScoringSchemeType overallLeaderboardScoringSchemeType, AsyncCallback callback); - - void updateLeaderboardGroup(UUID leaderboardGroupId, String oldName, String newName, String description, String newDisplayName, - List leaderboardNames, int[] overallLeaderboardDiscardThresholds, - ScoringSchemeType overallLeaderboardScoringSchemeType, AsyncCallback callback); - - void setRaceIsKnownToStartUpwind(RegattaAndRaceIdentifier raceIdentifier, boolean raceIsKnownToStartUpwind, - AsyncCallback callback); - - void setWindSourcesToExclude(RegattaAndRaceIdentifier raceIdentifier, Iterable windSourcesToExclude, - AsyncCallback callback); - void getCompetitorBoats(RegattaAndRaceIdentifier raceIdentifier, AsyncCallback> callback); void getRaceboardData(String regattaName, String raceName, String leaderboardName, @@ -455,65 +241,8 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getEvents(AsyncCallback> callback); - /** - * Renames the event with the name oldName to the newName.
    - * If there's no event with the name oldName or there's already a event with the name - * newName a {@link IllegalArgumentException} is thrown. - */ - void renameEvent(UUID eventId, String newName, AsyncCallback callback); - - /** - * Removes the event with the id id from the service and the persistence store. - */ - void removeEvent(UUID eventId, AsyncCallback callback); - - void removeEvents(Collection eventIds, AsyncCallback asyncCallback); - - void createEvent(String eventName, String eventDescription, Date startDate, Date endDate, String venue, - boolean isPublic, List courseAreaNames, String officialWebsiteURL, String baseURL, - Map sailorsInfoWebsiteURLsByLocaleName, Iterable images, - Iterable videos, Iterable leaderboardGroupIDs, - AsyncCallback callback); - - void updateEvent(UUID eventId, String eventName, String eventDescription, Date startDate, Date endDate, - VenueDTO venue, boolean isPublic, Iterable leaderboardGroupIds, String officialWebsiteURL, - String baseURL, Map sailorsInfoWebsiteURLsByLocaleName, Iterable images, - Iterable videos, Iterable windFinderReviewedSpotCollectionIds, AsyncCallback callback); - void resolveImageDimensions(String imageUrlAsString, AsyncCallback> callback); - void createCourseAreas(UUID eventId, String[] courseAreaNames, AsyncCallback callback); - - void removeCourseAreas(UUID eventId, UUID[] idsOfCourseAreasToRemove, AsyncCallback callback); - - void removeRegatta(RegattaIdentifier regattaIdentifier, AsyncCallback callback); - - void removeRegattas(Collection regattas, AsyncCallback asyncCallback); - - void moveRaceColumnInSeriesUp(RegattaIdentifier regattaIdentifier, String seriesName, String columnName, - AsyncCallback callback); - - void moveRaceColumnInSeriesDown(RegattaIdentifier regattaIdentifier, String seriesName, String columnName, - AsyncCallback callback); - - void createRegatta(String regattaName, String boatClassName, boolean canBoatsOfCompetitorsChangePerRace, - CompetitorRegistrationType competitorRegistrationType, String registrationLinkSecret, Date startDate, Date endDate, - RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal, boolean persistent, - ScoringSchemeType scoringSchemeType, Iterable courseAreaIds, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, - boolean controlTrackingFromStartAndFinishTimes, boolean autoRestartTrackingUponCompetitorSetChange, - RankingMetrics rankingMetricType, AsyncCallback callback); - - void addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, - List> columnNames, AsyncCallback> callback); - - void updateSeries(RegattaIdentifier regattaIdentifier, String seriesName, String newSeriesName, boolean isMedal, - boolean isFleetsCanRunInParallel, int[] resultDiscardingThresholds, boolean startsWithZeroScore, - boolean firstRaceIsNonDiscardableCarryForward, boolean hasSplitFleetScore, Integer maximumNumberOfDiscards, - List fleets, AsyncCallback callback); - - void removeRaceColumnsFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, List columnNames, - AsyncCallback callback); - void getScoreCorrectionProviderNames(AsyncCallback> callback); void getScoreCorrectionsOfProvider(String providerName, AsyncCallback callback); @@ -531,9 +260,6 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getRaceCourse(RegattaAndRaceIdentifier raceIdentifier, Date date, AsyncCallback callback); - void updateRaceCourse(RegattaAndRaceIdentifier raceIdentifier, - List> controlPoints, AsyncCallback callback); - void getServerConfiguration(AsyncCallback callback); void updateServerConfiguration(ServerConfigurationDTO serverConfiguration, AsyncCallback callback); @@ -547,10 +273,6 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getResultImportUrls(String resultProviderName, AsyncCallback> callback); - void removeResultImportURLs(String resultProviderName, Set toRemove, AsyncCallback callback); - - void addResultImportUrl(String resultProviderName, UrlDTO urlDTO, AsyncCallback callback); - /* * Validates if a {@link UrlDTO} which could contain a URL / event ID / event short-name can be used by the * specified {@link ResultUrlProvider}. @@ -560,23 +282,10 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getUrlResultProviderNamesAndOptionalSampleURL(AsyncCallback>> callback); - void addColumnsToLeaderboard(String leaderboardName, List> columnsToAdd, - AsyncCallback callback); - - void removeLeaderboardColumns(String leaderboardName, List columnsToRemove, AsyncCallback callback); - - void getCourseAreas(String leaderboardName, AsyncCallback> callback); - void getLeaderboard(String leaderboardName, AsyncCallback callback); void getLeaderboardWithSecurity(String leaderboardName, AsyncCallback callback); - void suppressCompetitorInLeaderboard(String leaderboardName, String competitorIdAsString, boolean suppressed, - AsyncCallback asyncCallback); - - void updateLeaderboardColumnFactor(String leaderboardName, String columnName, Double newFactor, - AsyncCallback callback); - void listSwissTiminigReplayRaces(String swissTimingUrl, AsyncCallback> asyncCallback); /** @@ -600,21 +309,6 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getPreviousSwissTimingArchiveConfigurations( AsyncCallback> asyncCallback); - void createSwissTimingArchiveConfiguration(String jsonUrl, - AsyncCallback asyncCallback); - - void updateSwissTimingArchiveConfiguration(SwissTimingArchiveConfigurationWithSecurityDTO dto, - AsyncCallback asyncCallback); - - void deleteSwissTimingArchiveConfigurations(Collection dtos, - AsyncCallback asyncCallback); - - void updateRegatta(RegattaIdentifier regattaIdentifier, Date startDate, Date endDate, Iterable courseAreaUuids, - RegattaConfigurationDTO regattaConfiguration, Double buoyZoneRadiusInHullLengths, - boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes, - boolean autoRestartTrackingUponCompetitorSetChange, String registrationLinkSecret, - CompetitorRegistrationType registrationType, AsyncCallback callback); - /** * @param detailType * supports {@link DetailType#REGATTA_RANK}, {@link DetailType#REGATTA_NET_POINTS_SUM} and @@ -629,18 +323,12 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getLeaderboardsNamesOfMetaLeaderboard(String metaLeaderboardName, AsyncCallback>> callback); - void getLeaderboardType(String leaderboardName, AsyncCallback callback); - void getRegattaStructureForEvent(UUID eventId, AsyncCallback> asyncCallback); - + void getRaceStateEntriesForRaceGroup(UUID eventId, List visibleCourseAreas, List visibleRegattas, boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay, Duration clientTimeZoneOffset, AsyncCallback> markedAsyncCallback); - void getRaceStateEntriesForLeaderboard(String leaderboardName, boolean showOnlyCurrentlyRunningRaces, - boolean showOnlyRacesOfSameDay, Duration clientTimeZoneOffset, List visibleRegattas, - AsyncCallback> callback); - void reloadRaceLog(String leaderboardName, RaceColumnDTO raceColumnDTO, FleetDTO fleet, AsyncCallback asyncCallback); @@ -649,14 +337,6 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getRegattaLog(String leaderboardName, AsyncCallback callback); - void importMasterData(String host, String[] names, boolean override, boolean compress, boolean exportWind, - boolean exportDeviceConfigurations, String targetServerUsername, String targetServerPassword, - boolean exportTrackedRacesAndStartTracking, AsyncCallback asyncCallback); - - void getImportOperationProgress(UUID id, AsyncCallback asyncCallback); - - void getStructureImportOperationProgress(AsyncCallback asyncCallback); - void getLeaderboardGroupNamesFromRemoteServer(String host, String username, String password, AsyncCallback> leaderboardGroupNames); @@ -667,38 +347,16 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getCompetitorsAndBoatsOfRace(String leaderboardName, String raceColumnName, String fleetName, AsyncCallback> asyncCallback); - void addOrUpdateCompetitors(List competitors, AsyncCallback> asyncCallback); - - void addOrUpdateCompetitorWithBoat(CompetitorWithBoatDTO competitor, AsyncCallback asyncCallback); - - void addOrUpdateCompetitorWithoutBoat(CompetitorDTO competitor, AsyncCallback asyncCallback); - - void addCompetitors(List competitorsForSaving, String searchTag, AsyncCallback> asyncCallback); - - void allowCompetitorResetToDefaults(Iterable competitors, AsyncCallback asyncCallback); - void getAllBoats(AsyncCallback> asyncCallback); void getStandaloneBoats(AsyncCallback> asyncCallback); - void addOrUpdateBoat(BoatDTO boat, AsyncCallback asyncCallback); - - void allowBoatResetToDefaults(Iterable boats, AsyncCallback asyncCallback); - - void linkBoatToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString, String boatIdAsString, AsyncCallback asyncCallback); - - void unlinkBoatFromCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString, AsyncCallback asyncCallback); - void getBoatLinkedToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString, AsyncCallback asyncCallback); void getDeviceConfigurations(AsyncCallback> asyncCallback); - void getDeviceConfiguration(UUID id, AsyncCallback callback); - void createOrUpdateDeviceConfiguration(DeviceConfigurationDTO configurationDTO, AsyncCallback callback); - void removeDeviceConfiguration(UUID deviceConfigurationId, AsyncCallback asyncCallback); - /** * Sets the a new start time. * @@ -731,97 +389,16 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getFinishingAndFinishTime(String leaderboardName, String raceColumnName, String fleetName, AsyncCallback> asyncCallback); - void getAllIgtimiAccountEmailAddresses(AsyncCallback> callback); - void getIgtimiAuthorizationUrl(String redirectProtocol, String redirectHostname, String redirectPort, AsyncCallback callback); - void authorizeAccessToIgtimiUser(String eMailAddress, String password, AsyncCallback callback); - - void removeIgtimiAccount(String eMailOfAccountToRemove, AsyncCallback asyncCallback); - - void importWindFromIgtimi(List selectedRaces, boolean correctByDeclination, - AsyncCallback> asyncCallback); - - void getEventById(UUID id, boolean withStatisticalData, AsyncCallback callback); - - /** - * @return {@code true} if the race was not yet denoted for race log tracking and now has successfully been denoted - * so - */ - void denoteForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName, - AsyncCallback callback); - - void denoteForRaceLogTracking(String leaderboardName, AsyncCallback callback); - - void denoteForRaceLogTracking(String leaderboardName,String prefix, AsyncCallback callback); - - void startRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName, boolean trackWind, - boolean correctWindByDeclination, AsyncCallback callback); - - void startRaceLogTracking(List> leaderboardRaceColumnFleetNames, - final boolean trackWind, final boolean correctWindByDeclination, AsyncCallback callback); - - /** - * Set the competitor (with contained boats) registrations in the racelog. Unregisters formerly registered competitors that are not listed - * in {@code competitors}. - */ - void setCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName, - Set competitors, AsyncCallback callback); - - /** - * Set the competitor and boat registrations in the racelog. Unregisters formerly registered competitors that are not listed - * in {@code competitors}. - */ - void setCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName, - Map competitorsAndBoats, AsyncCallback callback); - - /** - * Set the competitor registrations in the leaderboard. Unregisters formerly registered competitors that are not - * listed in {@code competitors}. - */ - void setCompetitorRegistrationsInRegattaLog(String leaderboardName, Set competitors, - AsyncCallback callback); - - void getCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName, AsyncCallback> callback); - - void addCourseDefinitionToRaceLog(String leaderboardName, String raceColumnName, String fleetName, - List> course, int priority, AsyncCallback callback); - - void addTag(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment, - String imageURL, String resizedImageURL, boolean visibleForPublic, TimePoint raceTimepoint, - AsyncCallback asyncCallback); - - void updateTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tagToUpdate, String tag, - String comment, String imageURL, String resizedImageURL, boolean visibleForPublic, AsyncCallback asyncCallback); - - void removeTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag, - AsyncCallback asyncCallback); - - void getAllTags(String leaderboardName, String raceColumnName, String fleetName, - AsyncCallback> asyncCallback); - - void getPublicTags(String leaderboardName, String raceColumnName, String fleetName, - AsyncCallback> asyncCallback); - void getPrivateTags(String leaderboardName, String raceColumnName, String fleetName, AsyncCallback> asyncCallback); void getLastCourseDefinitionInRaceLog(String leaderboardName, String raceColumnName, String fleetName, AsyncCallback callback); - void pingMark(String leaderboardName, MarkDTO mark, - TimePoint timePoint, Position position, AsyncCallback callback); - void getDeserializableDeviceIdentifierTypes(AsyncCallback> callback); - void revokeRaceAndRegattaLogEvents(String leaderboardName, String raceColumnName, String fleetName, - List eventIds, AsyncCallback callback); - - void removeSeries(RegattaIdentifier regattaIdentifier, String seriesName, AsyncCallback callback); - - void removeDenotationForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName, - AsyncCallback callback); - void getGPSFixImporterTypes(AsyncCallback> callback); void getSensorDataImporterTypes(AsyncCallback> callback); @@ -829,11 +406,6 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getTrackFileImportDeviceIds(List uuids, AsyncCallback> callback); - void setStartTimeReceivedForRace(RaceIdentifier raceIdentifier, Date newStartTimeReceived, - AsyncCallback callback); - - void createXYDiagramForBoatClass(String itemText, AsyncCallback asyncCallback); - void getEventsForLeaderboard(String leaderboardName, AsyncCallback> callback); /** @@ -855,77 +427,18 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getCompetitorRaceLogMarkPassingData(String leaderboardName, String raceColumnName, String fleetName, CompetitorDTO competitor, AsyncCallback> callback); - void updateSuppressedMarkPassings(String leaderboardName, String raceColumnName, String fleetName, - Integer newZeroBasedIndexOfSuppressedMarkPassing, CompetitorDTO competitorDTO, AsyncCallback callback); - - void createRegattaStructure(Iterable regattaNames, EventDTO newEvent, - AsyncCallback asyncCallback); - - void updateFixedMarkPassing(String leaderboardName, String raceColumnName, String fleetName, - Integer indexOfWaypoint, Date dateOfMarkPassing, CompetitorDTO competitorDTO, AsyncCallback callback); - - void getActiveFileStorageServiceName(AsyncCallback callback); - - void inviteCompetitorsForTrackingViaEmail(String serverUrlWithoutTrailingSlash, EventDTO event, - String leaderboardName, Collection competitors, String iOSAppUrl, String androidAppUrl, - String localeInfo, - AsyncCallback callback); - - void inviteBuoyTenderViaEmail(String serverUrlWithoutTrailingSlash, EventDTO eventDto, String leaderboardName, - String emails, String iOSAppUrl, String androidAppUrl, String localeInfoName, AsyncCallback callback); - - void getLeaderboardGroupsByEventId(UUID id, AsyncCallback> callback); - void getMarksInRegattaLog(String leaderboardName, AsyncCallback> callback); void getDeviceMappings(String leaderboardName, AsyncCallback> asyncCallback); - void revokeRaceAndRegattaLogEvents(String leaderboardName, List eventIds, AsyncCallback callback); - - void closeOpenEndedDeviceMapping(String leaderboardName, DeviceMappingDTO mappingDto, Date closingTimePoint, - AsyncCallback asyncCallback); - - void addDeviceMappingToRegattaLog(String leaderboardName, DeviceMappingDTO dto, AsyncCallback callback); - - void addTypedDeviceMappingToRegattaLog(String leaderboardName, TypedDeviceMappingDTO dto, AsyncCallback callback); - void doesRegattaLogContainCompetitors(String name, AsyncCallback regattaLogCallBack); void getRaceIdentifier(String regattaLikeName, String raceColumnName, String fleetName, AsyncCallback asyncCallback); - void setTrackingTimes(RaceLogSetTrackingTimesDTO dto, AsyncCallback callback); - void getTrackingTimes(String leaderboardName, String raceColumnName, String fleetName, AsyncCallback> callback); - /** - * Copies one race's competitor set to other races. - * @param fromTriple - * leaderboard name, race column name, and fleet name identifying the race from which to copy the - * competitors - * @param toTriples leaderboard name, race column name, and fleet name identifying the races to which to copy the - * competitors - */ - void copyCompetitorsToOtherRaceLogs(Triple fromTriple, - Set> toTriples, AsyncCallback callback); - - void copyCourseToOtherRaceLogs(Triple fromTriple, - Set> toTriples, int priority, AsyncCallback callback); - - void addMarkToRegattaLog(String leaderboardName, MarkDTO mark, AsyncCallback asyncCallback); - - void revokeMarkDefinitionEventInRegattaLog(String leaderboardName, MarkDTO markDTO, AsyncCallback callback); - - void areCompetitorRegistrationsEnabledForRace(String leaderboardName, String raceColumnName, String fleetName, - AsyncCallback asyncCallback); - - void disableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName, - AsyncCallback asyncCallback); - - void enableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName, - AsyncCallback asyncCallback); - void checkIfMarksAreUsedInOtherRaceLogs(String leaderboardName, String raceColumnName, String fleetName, Set marksToRemove, AsyncCallback> asyncCallback); @@ -941,29 +454,14 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getBoatRegistrationsInRegattaLog(String leaderboardName, AsyncCallback> setBoatsCallback); - void setBoatRegistrationsInRegattaLog(String leaderboardName, Set boats, - AsyncCallback callback); - void getBoatRegistrationsForLeaderboard(String leaderboardName, AsyncCallback> callback); - void addMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, - GPSFixDTO newFix, AsyncCallback callback); - - void editMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, - GPSFixDTO oldFix, Position newPosition, AsyncCallback callback); - - void removeMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, - GPSFixDTO fix, AsyncCallback callback); - void canRemoveMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, GPSFixDTO fix, AsyncCallback callback); void getMarksInTrackedRace(String leaderboardName, String raceColumnName, String fleetName, AsyncCallback> callback); - void getMarkTracks(String leaderboardName, String raceColumnName, String fleetName, - AsyncCallback callback); - void getMarkTrack(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, AsyncCallback callback); @@ -980,8 +478,6 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn */ void getEliminatedCompetitors(String leaderboardName, AsyncCallback> asyncCallback); - void setEliminatedCompetitors(String leaderboardName, Set eliminatedCompetitors, AsyncCallback callback); - /** * Used to determine for a Chart the available Detailtypes. This is for example used, to only show the RideHeight as * an option for charts, if it actually recorded for the race. @@ -991,10 +487,6 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getExpeditionDeviceConfigurations(AsyncCallback> callback); - void removeExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration expeditionDeviceConfiguration, AsyncCallback asyncCallback); - - void addOrReplaceExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration expeditionDeviceConfiguration, AsyncCallback asyncCallback); - /** * Calculates a {@link PairingListTemplate} based on a competitor count, flight count and group count of the * leaderboard. Since the competitor count must not be the competitors that are registered on the leaderboard, it @@ -1038,35 +530,11 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn */ void getPairingListFromRaceLogs(final String leaderboardName, AsyncCallback callback); - /** - * Registers all competitors of a {@link PairingList} in the respective {@link RaceColumn}s and {@link Fleet}s. - * - * @param leaderboardName - * the name of the leaderboard - * @param flightMultiplier - * specifies how often the flights will be cloned - * @param callback - */ - void fillRaceLogsFromPairingListTemplate(final String leaderboardName, final int flightMultiplier, - final Iterable selectedFlightNames,PairingListDTO pairingListDTO, AsyncCallback callback); - void getRaceDisplayNamesFromLeaderboard(final String leaderboardName, List raceColumnNames, AsyncCallback> callback); void getAvailableDetailTypesForLeaderboard(String leaderboardName, RegattaAndRaceIdentifier raceOrNull, AsyncCallback> asyncCallback); - /** - * Checks whether the user may cut the race identified by {@code radeIdentifier} into multiple races. For this, it - * has to be found and it has to be a "smartphone-tracked" race with a valid start-of-tracking time. If not, - * {@code false} will be returned. If the user it not permitted to slice the race, e.g., because no - * permission has been granted to modify the leaderboard or regatta, an {@link AuthorizationException} will be - * thrown. - */ - void canSliceRace(RegattaAndRaceIdentifier raceIdentifier, AsyncCallback callback); - - void sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName, TimePoint sliceFrom, TimePoint sliceTo, - AsyncCallback callback); - void prepareForSlicingOfRace(RegattaAndRaceIdentifier raceIdentifier, AsyncCallback callback); @@ -1084,13 +552,6 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn */ void checkIfRaceIsTracking(RegattaAndRaceIdentifier raceIdentifier, AsyncCallback asyncCallback); - /** - * @see SailingService#resizeImage(ImageResizingTaskDTO) - * @param imageResizingTask the information on how the contained ImageDTO should be resized - * @param asyncCallback The callback called after finishing resizing, storing the returned ImageDTOs somewhere is proposed - */ - void resizeImage(ImageResizingTaskDTO imageResizingTask, AsyncCallback> asyncCallback); - void getMailType(AsyncCallback callback); /** @@ -1100,19 +561,6 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn */ void openRegattaRegistrationQrCode(String url, AsyncCallback asyncCallback); - /** - * gets a (possibly imcomplete) list of available tennants to choose from. - */ - void getPossibleTennants(AsyncCallback> asyncCallback); - - void updateGroupOwnerForEventHierarchy(UUID eventId, - MigrateGroupOwnerForHierarchyDTO migrateGroupOwnerForHierarchyDTO, AsyncCallback callback); - - void updateGroupOwnerForLeaderboardGroupHierarchy(UUID leaderboardGroupId, - MigrateGroupOwnerForHierarchyDTO migrateGroupOwnerForHierarchyDTO, AsyncCallback callback); - - void getSecretForRegattaByName(String leaderboardName, AsyncCallback asyncCallback); - void getAllIgtimiAccountsWithSecurity(AsyncCallback> callback); /** @@ -1139,15 +587,8 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getCompetitor(UUID competitorId, String leaderboardName, String regattaRegistrationLinkSecret, AsyncCallback asyncCallback); - void existsSwissTimingConfigurationForCurrentUser(String jsonUrl, AsyncCallback callback); - - void existsSwissTimingArchiveConfigurationForCurrentUser(String jsonUrl, AsyncCallback callback); - - void existsTracTracConfigurationForCurrentUser(String jsonUrl, AsyncCallback callback); - void getTrackedRaceIsUsingMarkPassingCalculator(RegattaAndRaceIdentifier regattaNameAndRaceName, AsyncCallback callback); - void getLegGeometry(String leaderboardName, String raceColumnName, String fleetName, int[] zeroBasedLegIndices, ORCPerformanceCurveLegTypes[] legTypes, AsyncCallback callback); @@ -1160,46 +601,14 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getORCPerformanceCurveLegInfo(RegattaAndRaceIdentifier singleSelectedRace, AsyncCallback> asyncCallback); - void setORCPerformanceCurveLegInfo(RegattaAndRaceIdentifier raceIdentifier, - Map legInfo, AsyncCallback callback); - - void setORCPerformanceCurveLegInfo(String leaderboardName, String raceColumnName, String fleetName, - Map legInfo, AsyncCallback callback); - void getBoatRegistrationsForRegatta(RegattaIdentifier regattaIdentifier, AsyncCallback> callback); void getORCCertificates(String json, AsyncCallback> callback); void getORCCertificateAssignmentsByBoatIdAsString(RegattaIdentifier regattaIdentifier, AsyncCallback> asyncCallback); - void getORCCertificateAssignmentsByBoatIdAsString(RegattaAndRaceIdentifier raceIdentifier, AsyncCallback> asyncCallback); - - void getORCCertificateAssignmentsByBoatIdAsString(String leaderboardName, AsyncCallback> asyncCallback); - void getORCCertificateAssignmentsByBoatIdAsString(String leaderboardName, String raceColumnName, String fleetName, AsyncCallback> asyncCallback); - void assignORCPerformanceCurveCertificates(RegattaIdentifier regattaIdentifier, - Map certificatesForBoatsWithIdAsString, - AsyncCallback> callback); - - void assignORCPerformanceCurveCertificates(RegattaAndRaceIdentifier raceIdentifier, - Map certificatesForBoatsWithIdAsString, - AsyncCallback> callback); - - void assignORCPerformanceCurveCertificates(String leaderboardName, String raceColumnName, String fleetName, - Map certificatesForBoatsWithIdAsString, - AsyncCallback> callback); - - void assignORCPerformanceCurveCertificates(String leaderboardName, - Map certificatesForBoatsWithIdAsString, - AsyncCallback> callback); - - void getORCPerformanceCurveScratchBoat(String leaderboardName, String raceColumnName, String fleetName, - AsyncCallback asyncCallback); - - void setORCPerformanceCurveScratchBoat(String leaderboardName, String raceColumnName, String fleetName, CompetitorDTO newScratchBoat, - AsyncCallback asyncCallback); - /** * Obtains the {@link ImpliedWindSource} set in the race log identified by the triple {@code leaderboardName}, * {@code raceColumnName}, and {@code fleetName}. Note that other than in the ORC Performance Curve ranking metric @@ -1227,18 +636,10 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn void getMarkTemplates(AsyncCallback> callback); - void addOrUpdateMarkTemplate(MarkTemplateDTO markTemplate, AsyncCallback asyncCallback); - - void addOrUpdateMarkProperties(MarkPropertiesDTO markProperties, AsyncCallback asyncCallback); - - void updateMarkPropertiesPositioning(UUID markPropertiesId, DeviceIdentifierDTO deviceIdentifier, Position position, AsyncCallback asyncCallback); - void getMarkProperties(AsyncCallback> asyncCallback); void getCourseTemplates(AsyncCallback> asyncCallback); - void createOrUpdateCourseTemplate(CourseTemplateDTO courseTemplate, AsyncCallback asyncCallback); - /** * Remove course templates by UUIDs * @@ -1249,17 +650,13 @@ public interface SailingServiceAsync extends FileStorageManagementGwtServiceAsyn */ void removeCourseTemplates(Collection courseTemplatesUuids, AsyncCallback asyncCallback); - /** - * Remove mark properties by UUIDs - * - * @param markPropertiesUuids - * the {@link Collection} of mark properties' UUIDs which will be remove - * @param asyncCallback - * {@link AsyncCallback} object - */ - void removeMarkProperties(Collection markPropertiesUuids, AsyncCallback asyncCallback); - void getMarkRoles(AsyncCallback> callback); - void createMarkRole(MarkRoleDTO markRole, AsyncCallback asyncCallback); + void areCompetitorRegistrationsEnabledForRace(String leaderboardName, String raceColumnName, String fleetName, + AsyncCallback callback); + + void getCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName, + AsyncCallback> callback); + + void getEventById(UUID id, boolean withStatisticalData, AsyncCallback callback); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceHelper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceHelper.java index 5a3598bb1b9..bfe28d58731 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceHelper.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceHelper.java @@ -18,6 +18,14 @@ public abstract class SailingServiceHelper { public static SailingServiceAsync createSailingServiceInstance() { return createSailingServiceInstance(true, null); } + + /** + * Creates a new {@link SailingServiceWriteAsync} instance, should be used when code resides in the same bundle as the sailing service code. + */ + public static SailingServiceWriteAsync createSailingServiceWriteInstance() { + return createSailingServiceWriteInstance(true, null); + } + /** * Creates a new {@link SailingServiceAsync} instance. * @@ -54,4 +62,29 @@ public abstract class SailingServiceHelper { } return service; } + + /** + * Creates a new {@link SailingServiceWriteAsync} instance that uses a routing provider, for code in same bundle. + */ + public static SailingServiceWriteAsync createSailingServiceWriteInstance(ServiceRoutingProvider routingProvider) { + return createSailingServiceWriteInstance(true, routingProvider); + } + + public static SailingServiceWriteAsync createSailingServiceWriteInstance(boolean sameBundle, ServiceRoutingProvider routingProvider) { + final SailingServiceWriteAsync service = GWT.create(SailingServiceWrite.class); + final ServiceDefTarget serviceToRegister = (ServiceDefTarget) service; + + final StringBuilder servicePath = new StringBuilder(RemoteServiceMappingConstants.sailingServiceWriteRemotePath); + if (routingProvider != null) { + servicePath.append(routingProvider.routingSuffixPath()); + } + + final String servicePathWithRoutingSuffix = servicePath.toString(); + if (sameBundle) { + EntryPointHelper.registerASyncService(serviceToRegister, servicePathWithRoutingSuffix); + } else { + EntryPointHelper.registerASyncService(serviceToRegister, RemoteServiceMappingConstants.WEB_CONTEXT_PATH, servicePathWithRoutingSuffix); + } + return service; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceWrite.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceWrite.java new file mode 100644 index 00000000000..c18451040c4 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceWrite.java @@ -0,0 +1,656 @@ +package com.sap.sailing.gwt.ui.client; + +import java.io.IOException; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.shiro.authz.UnauthorizedException; + +import com.sap.sailing.domain.abstractlog.orc.RaceLogORCLegDataEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.RaceLogTagEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.common.CompetitorDescriptor; +import com.sap.sailing.domain.common.CompetitorRegistrationType; +import com.sap.sailing.domain.common.DataImportProgress; +import com.sap.sailing.domain.common.MaxPointsReason; +import com.sap.sailing.domain.common.NoWindException; +import com.sap.sailing.domain.common.NotFoundException; +import com.sap.sailing.domain.common.PassingInstruction; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.RankingMetrics; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.RegattaIdentifier; +import com.sap.sailing.domain.common.RegattaName; +import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.common.ServiceException; +import com.sap.sailing.domain.common.UnableToCloseDeviceMappingException; +import com.sap.sailing.domain.common.WindSource; +import com.sap.sailing.domain.common.abstractlog.NotRevokableException; +import com.sap.sailing.domain.common.dto.BoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTO; +import com.sap.sailing.domain.common.dto.FleetDTO; +import com.sap.sailing.domain.common.dto.PairingListDTO; +import com.sap.sailing.domain.common.dto.RaceColumnInSeriesDTO; +import com.sap.sailing.domain.common.dto.RaceDTO; +import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO; +import com.sap.sailing.domain.common.dto.TagDTO; +import com.sap.sailing.domain.common.orc.ORCCertificate; +import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveLegImpl; +import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException; +import com.sap.sailing.domain.common.racelog.tracking.DoesNotHaveRegattaLogException; +import com.sap.sailing.domain.common.racelog.tracking.NotDenotableForRaceLogTrackingException; +import com.sap.sailing.domain.common.racelog.tracking.NotDenotedForRaceLogTrackingException; +import com.sap.sailing.domain.common.racelog.tracking.TransformationException; +import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; +import com.sap.sailing.domain.racelog.tracking.SensorFixStore; +import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapter; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.expeditionconnector.ExpeditionDeviceConfiguration; +import com.sap.sailing.gwt.ui.adminconsole.RaceLogSetTrackingTimesDTO; +import com.sap.sailing.gwt.ui.shared.BulkScoreCorrectionDTO; +import com.sap.sailing.gwt.ui.shared.ControlPointDTO; +import com.sap.sailing.gwt.ui.shared.DeviceConfigurationDTO.RegattaConfigurationDTO; +import com.sap.sailing.gwt.ui.shared.DeviceIdentifierDTO; +import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO; +import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sailing.gwt.ui.shared.GPSFixDTO; +import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; +import com.sap.sailing.gwt.ui.shared.MarkDTO; +import com.sap.sailing.gwt.ui.shared.MigrateGroupOwnerForHierarchyDTO; +import com.sap.sailing.gwt.ui.shared.RegattaDTO; +import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTOWithSecurity; +import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationWithSecurityDTO; +import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationWithSecurityDTO; +import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDTO; +import com.sap.sailing.gwt.ui.shared.TracTracConfigurationWithSecurityDTO; +import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDTO; +import com.sap.sailing.gwt.ui.shared.TypedDeviceMappingDTO; +import com.sap.sailing.gwt.ui.shared.UrlDTO; +import com.sap.sailing.gwt.ui.shared.VenueDTO; +import com.sap.sailing.gwt.ui.shared.WindDTO; +import com.sap.sailing.gwt.ui.shared.courseCreation.CourseTemplateDTO; +import com.sap.sailing.gwt.ui.shared.courseCreation.MarkPropertiesDTO; +import com.sap.sailing.gwt.ui.shared.courseCreation.MarkRoleDTO; +import com.sap.sailing.gwt.ui.shared.courseCreation.MarkTemplateDTO; +import com.sap.sse.common.Duration; +import com.sap.sse.common.NoCorrespondingServiceRegisteredException; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.Util.Triple; +import com.sap.sse.common.mail.MailException; +import com.sap.sse.common.media.MediaTagConstants; +import com.sap.sse.filestorage.FileStorageService; +import com.sap.sse.gwt.client.filestorage.FileStorageManagementGwtService; +import com.sap.sse.gwt.client.media.ImageDTO; +import com.sap.sse.gwt.client.media.ImageResizingTaskDTO; +import com.sap.sse.gwt.client.media.VideoDTO; +import com.sap.sse.gwt.shared.filestorage.FileStorageServiceDTO; +import com.sap.sse.gwt.shared.filestorage.FileStorageServicePropertyErrorsDTO; +import com.sap.sse.security.interfaces.UserStore; +import com.sap.sse.security.ui.shared.SuccessInfo; + +public interface SailingServiceWrite extends FileStorageManagementGwtService, SailingService { + + void setORCPerformanceCurveScratchBoat(String leaderboardName, String raceColumnName, String fleetName, + CompetitorDTO newScratchBoatDTO) throws NotFoundException; + + CompetitorDTO getORCPerformanceCurveScratchBoat(String leaderboardName, String raceColumnName, String fleetName) + throws NotFoundException; + + Triple assignORCPerformanceCurveCertificates(String leaderboardName, + String raceColumnName, String fleetName, Map certificatesForBoatsWithIdAsString) + throws IOException, NotFoundException; + + Triple assignORCPerformanceCurveCertificates(RegattaIdentifier regattaIdentifier, + Map certificatesForBoatsWithIdAsString) throws IOException, NotFoundException; + + String getSecretForRegattaByName(String regattaName); + + void updateGroupOwnerForLeaderboardGroupHierarchy(UUID leaderboardGroupId, + MigrateGroupOwnerForHierarchyDTO migrateGroupOwnerForHierarchyDTO); + + void updateGroupOwnerForEventHierarchy(UUID eventId, + MigrateGroupOwnerForHierarchyDTO migrateGroupOwnerForHierarchyDTO); + + /** + * Resizes an {@Link ImageDTO} that is part of an {@link ImageResizingTaskDTO} into a set of resized versions. This + * set only contains one image in most cases, because most {@Link ImageDTO} only hold one predefined + * {@link MediaTagConstants}. All {@link MediaTagConstants} stored in the resizingTask of the + * {@link ImageResizingTaskDTO} create a resize. Since no {@link MediaTagConstants} have the same defined bounds, + * there will be no merge of these {@Link ImageDTO}. Uses the {@link FileStorageService} to store the resized + * images. If an error occurs during resize or storing process, it will be tried to restore the previous state. + * + * @author Robin Fleige (D067799) + * + * @param imageResizingTask + * is an {@link ImageResizingTaskDTO} with the information on how the image saved in the {@Link ImageDTO} + * should be resized. The resizingTask attribute should not be null or empty at this point + * @return returns a set of {@Link ImageDTO}, that contain the resized variants of the {@Link ImageDTO} in + * toResizeImage + * @throws UnauthorizedException, + * Exception can throw different type of exceptions + */ + Set resizeImage(final ImageResizingTaskDTO resizingTask) throws Exception; + + void removeExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration deviceConfiguration); + + void setEliminatedCompetitors(String leaderboardName, Set newEliminatedCompetitorDTOs) + throws NotFoundException; + + void editMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, + GPSFixDTO oldFix, Position newPosition) throws NotRevokableException; + + void removeMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, + GPSFixDTO fix) throws NotRevokableException; + + void enableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) + throws IllegalArgumentException, NotFoundException; + + void disableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) + throws NotRevokableException, NotFoundException; + + void inviteBuoyTenderViaEmail(String serverUrlWithoutTrailingSlash, EventDTO eventDto, String leaderboardName, + String emails, String iOSAppUrl, String androidAppUrl, String localeInfoName) throws MailException; + + void inviteCompetitorsForTrackingViaEmail(String serverUrlWithoutTrailingSlash, EventDTO eventDto, + String leaderboardName, Collection competitorDtos, String iOSAppUrl, String androidAppUrl, + String localeInfoName) throws MailException; + + String getActiveFileStorageServiceName(); + + void setActiveFileStorageService(String serviceName, String localeInfoName); + + void startRaceLogTracking(List> leaderboardRaceColumnFleetNames, boolean trackWind, + boolean correctWindByDeclination) + throws UnauthorizedException, NotDenotedForRaceLogTrackingException, Exception; + + FileStorageServicePropertyErrorsDTO testFileStorageServiceProperties(String serviceName, String localeInfoName) + throws IOException; + + void setFileStorageServiceProperties(String serviceName, Map properties); + + FileStorageServiceDTO[] getAvailableFileStorageServices(String localeInfoName); + + void updateSuppressedMarkPassings(String leaderboardName, String raceColumnName, String fleetName, + Integer newZeroBasedIndexOfSuppressedMarkPassing, CompetitorDTO competitorDTO) throws NotFoundException; + + void updateFixedMarkPassing(String leaderboardName, String raceColumnName, String fleetName, + Integer indexOfWaypoint, Date dateOfMarkPassing, CompetitorDTO competitorDTO) throws NotFoundException; + + void closeOpenEndedDeviceMapping(String leaderboardName, DeviceMappingDTO mappingDTO, Date closingTimePoint) + throws TransformationException, DoesNotHaveRegattaLogException, UnableToCloseDeviceMappingException, + NotFoundException; + + void revokeRaceAndRegattaLogEvents(String leaderboardName, List eventIds) + throws NotRevokableException, DoesNotHaveRegattaLogException, NotFoundException; + + void addTypedDeviceMappingToRegattaLog(String leaderboardName, TypedDeviceMappingDTO dto) + throws NoCorrespondingServiceRegisteredException, TransformationException, DoesNotHaveRegattaLogException, + NotFoundException; + + void addDeviceMappingToRegattaLog(String leaderboardName, DeviceMappingDTO dto) + throws NoCorrespondingServiceRegisteredException, TransformationException, DoesNotHaveRegattaLogException; + + void revokeMarkDefinitionEventInRegattaLog(String leaderboardName, MarkDTO markDTO) + throws DoesNotHaveRegattaLogException, NotFoundException; + + void fillRaceLogsFromPairingListTemplate(final String leaderboardName, final int flightMultiplier, + final List selectedFlightNames, final PairingListDTO pairingListDTO) + throws NotFoundException, CompetitorRegistrationOnRaceLogDisabledException; + + void setBoatRegistrationsInRegattaLog(String leaderboardName, Set boatDTOs) + throws DoesNotHaveRegattaLogException, NotFoundException; + + void setCompetitorRegistrationsInRegattaLog(String leaderboardName, Set competitorDTOs) + throws DoesNotHaveRegattaLogException, NotFoundException; + + void setCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName, + Set competitorDTOs) + throws CompetitorRegistrationOnRaceLogDisabledException, NotFoundException; + + void setCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName, + Map competitorAndBoatDTOs) + throws CompetitorRegistrationOnRaceLogDisabledException, NotFoundException; + + void denoteForRaceLogTracking(String leaderboardName, String prefix) throws Exception; + + Boolean denoteForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName) + throws NotFoundException, NotDenotableForRaceLogTrackingException; + + Map importWindFromIgtimi(List selectedRaces, + boolean correctByDeclination) + throws IllegalStateException, Exception; + + void removeIgtimiAccount(String eMailOfAccountToRemove); + + boolean authorizeAccessToIgtimiUser(String eMailAddress, String password) throws Exception; + + void setTrackingTimes(RaceLogSetTrackingTimesDTO dto) throws NotFoundException; + + boolean removeDeviceConfiguration(UUID deviceConfigurationId); + + DataImportProgress getImportOperationProgress(UUID id) throws UnauthorizedException; + + void allowCompetitorResetToDefaults(List competitors); + + UUID importMasterData(String host, String[] groupNames, boolean override, boolean compress, boolean exportWind, + boolean exportDeviceConfigurations, String targetServerUsername, String targetServerPassword, + boolean exportTrackedRacesAndStartTracking) throws UnauthorizedException; + + RegattaDTO createRegatta(String regattaName, String boatClassName, boolean canBoatsOfCompetitorsChangePerRace, + CompetitorRegistrationType competitorRegistrationType, String registrationLinkSecret, Date startDate, + Date endDate, RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal, + boolean persistent, ScoringSchemeType scoringSchemeType, List courseAreaIds, + Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, + boolean controlTrackingFromStartAndFinishTimes, boolean autoRestartTrackingUponCompetitorSetChange, RankingMetrics rankingMetricType) + throws UnauthorizedException; + + void removeRaceColumnsFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, List columnNames) + throws UnauthorizedException; + + void updateSeries(RegattaIdentifier regattaIdentifier, String seriesName, String newSeriesName, boolean isMedal, + boolean isFleetsCanRunInParallel, int[] resultDiscardingThresholds, boolean startsWithZeroScore, + boolean firstRaceIsNonDiscardableCarryForward, boolean hasSplitFleetScore, Integer maximumNumberOfDiscards, + List fleets) throws UnauthorizedException; + + void updateRegatta(RegattaIdentifier regattaIdentifier, Date startDate, Date endDate, List courseAreaUuids, + RegattaConfigurationDTO regattaConfiguration, Double buoyZoneRadiusInHullLengths, + boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes, + boolean autoRestartTrackingUponCompetitorSetChange, String registrationLinkSecret, CompetitorRegistrationType registrationType) throws UnauthorizedException; + + void removeSeries(RegattaIdentifier regattaIdentifier, String seriesName) throws UnauthorizedException; + + void removeRegatta(RegattaIdentifier regattaIdentifier) throws UnauthorizedException; + + void removeRegattas(Collection regattas) throws UnauthorizedException; + + void renameEvent(UUID eventId, String newName) throws UnauthorizedException; + + void removeEvent(UUID eventId) throws UnauthorizedException; + + void removeEvents(Collection eventIds) throws UnauthorizedException; + + void removeCourseAreas(UUID eventId, UUID[] courseAreaIds) throws UnauthorizedException; + + void createCourseAreas(UUID eventId, String[] courseAreaNames) throws UnauthorizedException; + + EventDTO createEvent(String eventName, String eventDescription, Date startDate, Date endDate, String venue, + boolean isPublic, List courseAreaNames, String officialWebsiteURLAsString, String baseURLAsString, + Map sailorsInfoWebsiteURLsByLocaleName, List images, + List videos, List leaderboardGroupIds) + throws UnauthorizedException; + + EventDTO updateEvent(UUID eventId, String eventName, String eventDescription, Date startDate, Date endDate, + VenueDTO venue, boolean isPublic, List leaderboardGroupIds, String officialWebsiteURLString, + String baseURLAsString, Map sailorsInfoWebsiteURLsByLocaleName, List images, + List videos, List windFinderReviewedSpotCollectionIds) + throws UnauthorizedException, IOException; + + void updateLeaderboardGroup(UUID leaderboardGroupId, String oldName, String newName, String newDescription, + String newDisplayName, List leaderboardNames, int[] overallLeaderboardDiscardThresholds, + ScoringSchemeType overallLeaderboardScoringSchemeType); + + LeaderboardGroupDTO createLeaderboardGroup(String groupName, String description, String displayName, + boolean displayGroupsInReverseOrder, int[] overallLeaderboardDiscardThresholds, + ScoringSchemeType overallLeaderboardScoringSchemeType); + + void trackWithSwissTiming(RegattaIdentifier regattaToAddTo, List rrs, String hostname, + int port, boolean trackWind, boolean correctWindByDeclination, boolean useInternalMarkPassingAlgorithm, + String updateURL, String updateUsername, String updatePassword, String eventName, String manage2SailEventUrl) throws UnauthorizedException, Exception; + + void updateSwissTimingConfiguration(SwissTimingConfigurationWithSecurityDTO configuration) + throws UnauthorizedException, Exception; + + void deleteSwissTimingConfigurations(Collection configurations) + throws UnauthorizedException, Exception; + + void createSwissTimingConfiguration(String configName, String jsonURL, String hostname, Integer port, + String updateURL, String updateUsername, String updatePassword) throws UnauthorizedException, Exception; + + void updateRacesDelayToLive(List regattaAndRaceIdentifiers, long delayToLiveInMs); + + void updateIsMedalRace(String leaderboardName, String columnName, boolean isMedalRace); + + void moveLeaderboardColumnUp(String leaderboardName, String columnName) throws UnauthorizedException; + + void moveLeaderboardColumnDown(String leaderboardName, String columnName) throws UnauthorizedException; + + void updateCompetitorDisplayNameInLeaderboard(String leaderboardName, String competitorIdAsString, + String displayName); + + void updateLeaderboardScoreCorrectionsAndMaxPointsReasons(BulkScoreCorrectionDTO updates) throws NoWindException; + + void updateLeaderboardScoreCorrectionMetadata(String leaderboardName, Date timePointOfLastCorrectionValidity, + String comment); + + com.sap.sse.common.Util.Triple updateLeaderboardScoreCorrection(String leaderboardName, + String competitorIdAsString, String columnName, Double correctedScore, Date date) throws NoWindException; + + void updateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Double carriedPoints); + + void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName, String fleetName) + throws UnauthorizedException; + + boolean connectTrackedRaceToLeaderboardColumn(String leaderboardName, String raceColumnName, String fleetName, + RegattaAndRaceIdentifier raceIdentifier) throws UnauthorizedException; + + void suppressCompetitorInLeaderboard(String leaderboardName, String competitorIdAsString, boolean suppressed); + + void updateLeaderboardColumnFactor(String leaderboardName, String columnName, Double newFactor); + + void renameLeaderboardColumn(String leaderboardName, String oldColumnName, String newColumnName) + throws UnauthorizedException; + + void removeLeaderboardColumn(String leaderboardName, String columnName) throws UnauthorizedException; + + void removeLeaderboardGroups(Set groupNames); + + void removeLeaderboard(String leaderboardName) throws UnauthorizedException; + + void removeLeaderboards(Collection leaderboardNames) throws UnauthorizedException; + + StrippedLeaderboardDTOWithSecurity updateLeaderboard(String leaderboardName, String newLeaderboardDisplayName, + int[] newDiscardingThreasholds, List newCourseAreaIds) + throws UnauthorizedException; + + StrippedLeaderboardDTOWithSecurity createRegattaLeaderboardWithEliminations(String name, String displayName, + String regattaName) throws UnauthorizedException; + + StrippedLeaderboardDTOWithSecurity createRegattaLeaderboard(RegattaName regattaIdentifier, + String leaderboardDisplayName, int[] discardThresholds) throws UnauthorizedException; + + StrippedLeaderboardDTOWithSecurity createFlexibleLeaderboard(String leaderboardName, String leaderboardDisplayName, + int[] discardThresholds, ScoringSchemeType scoringSchemeType, List courseAreaIds) + throws UnauthorizedException; + + void removeResultImportURLs(String resultProviderName, Set toRemove) throws Exception; + + void deleteSwissTimingArchiveConfigurations(Collection dtos) + throws UnauthorizedException, Exception; + + void updateSwissTimingArchiveConfiguration(SwissTimingArchiveConfigurationWithSecurityDTO dto) + throws UnauthorizedException, Exception; + + void createSwissTimingArchiveConfiguration(String jsonUrl) + throws UnauthorizedException, Exception; + + void createRegattaStructure(final List regattas, final EventDTO newEvent) throws IOException; + + void removeWind(RegattaAndRaceIdentifier raceIdentifier, WindDTO windDTO); + + void setWindSourcesToExclude(RegattaAndRaceIdentifier raceIdentifier, List windSourcesToExclude); + + void setRaceIsKnownToStartUpwind(RegattaAndRaceIdentifier raceIdentifier, boolean raceIsKnownToStartUpwind); + + void updateRaceCourse(RegattaAndRaceIdentifier raceIdentifier, + List> courseDTO); + + void setWind(RegattaAndRaceIdentifier raceIdentifier, WindDTO windDTO); + + void removeAndUntrackRaces(List regattaAndRaceIdentifiers); + + void stopTrackingRaces(List regattaAndRaceIdentifiers) throws Exception; + + void updateTracTracConfiguration(TracTracConfigurationWithSecurityDTO tracTracConfiguration) + throws UnauthorizedException, Exception; + + void deleteTracTracConfigurations(Collection tracTracConfigurations) + throws UnauthorizedException, Exception; + + void createTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI, + String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword) throws Exception; + + void trackWithTracTrac(RegattaIdentifier regattaToAddTo, List rrs, String liveURI, + String storedURI, String courseDesignUpdateURI, boolean trackWind, boolean correctWindByDeclination, + Duration offsetToStartTimeOfSimulatedRace, boolean useInternalMarkPassingAlgorithm, boolean useOfficialEventsToUpdateRaceLog, + String tracTracUsername, String tracTracPassword) throws UnauthorizedException, Exception; + + MarkPropertiesDTO updateMarkPropertiesPositioning(UUID markPropertiesId, DeviceIdentifierDTO deviceIdentifier, + Position fixedPosition); + + CourseTemplateDTO createOrUpdateCourseTemplate(CourseTemplateDTO courseTemplate); + + /** + * Removes mark properties list + * + * @param markPropertiesDTOS + * list of mark properties to remove + */ + void removeMarkProperties(Collection markPropertiesUuids); + + MarkRoleDTO createMarkRole(MarkRoleDTO markRole); + + List addCompetitors(List competitorsForSaving, String searchTag) + throws UnauthorizedException, Exception; + + void addColumnsToLeaderboard(String leaderboardName, List> columnsToAdd) + throws UnauthorizedException; + + void addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace) + throws UnauthorizedException; + + /** + * Adds the course definition to the racelog, while trying to reuse existing marks, controlpoints and waypoints from + * the previous course definition in the racelog. + * + * @param priority + * TODO + * @throws UnauthorizedException, + * NotFoundException + */ + void addCourseDefinitionToRaceLog(String leaderboardName, String raceColumnName, String fleetName, + List> course, int priority) + throws UnauthorizedException, NotFoundException; + + void addMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, + GPSFixDTO newFix) throws UnauthorizedException; + + void addMarkToRegattaLog(String leaderboardName, MarkDTO mark) + throws UnauthorizedException, DoesNotHaveRegattaLogException; + + void addOrReplaceExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration expeditionDeviceConfiguration) + throws UnauthorizedException; + + BoatDTO addOrUpdateBoat(BoatDTO boat) throws UnauthorizedException, Exception; + + List addOrUpdateCompetitors(List competitors) throws UnauthorizedException, Exception; + + CompetitorWithBoatDTO addOrUpdateCompetitorWithBoat(CompetitorWithBoatDTO competitor) + throws UnauthorizedException, Exception; + + CompetitorDTO addOrUpdateCompetitorWithoutBoat(CompetitorDTO competitor) throws UnauthorizedException, Exception; + + MarkPropertiesDTO addOrUpdateMarkProperties(MarkPropertiesDTO markProperties); + + MarkTemplateDTO addOrUpdateMarkTemplate(MarkTemplateDTO markTemplate); + + List addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, + List> columnNames) throws UnauthorizedException; + + void addResultImportUrl(String resultProviderName, UrlDTO url) throws UnauthorizedException, Exception; + + /** + * Adds public tag as {@link RaceLogTagEvent} to {@link RaceLog} and private tag to + * {@link com.sap.sse.security.interfaces.UserStore UserStore}. + * + * @param leaderboardName + * required to identify {@link RaceLog}, must NOT be null + * @param raceColumnName + * required to identify {@link RaceLog}, must NOT be null + * @param fleetName + * required to identify {@link RaceLog}, must NOT be null + * @param tag + * title of tag, must NOT be null + * @param comment + * optional comment of tag + * @param imageURLs + * optional image URLs of tag + * @param visibleForPublic + * when set to true tag will be saved as public tag (visible for every user), when set to + * false tag will be saved as private tag (visible only for creator) + * @param raceTimepoint + * timepoint in race where user created tag, must NOT be null + * @return successful {@link SuccessInfo} if tag was added successfully, otherwise + * non-successful {@link SuccessInfo} + */ + SuccessInfo addTag(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment, + String imageURL, String resizedImageURL, boolean visibleForPublic, TimePoint raceTimepoint) + throws UnauthorizedException; + + void allowBoatResetToDefaults(List boats) throws UnauthorizedException; + + /** + * Into the first {@link RaceLog} {@link TrackedRace#getAttachedRaceLogs() attached} to the tracked race identified + * by {@code raceIdentifier} writes {@link RaceLogORCLegDataEvent}s and/or revokation events such that afterwards + * the {@link #getORCPerformanceCurveLegInfo(RegattaAndRaceIdentifier)} will return a map equal to the one passed, + * except for {@code null} values which then would be missing from the results, where here they mean to explicitly + * revoke any previous setting for that leg. + */ + void setORCPerformanceCurveLegInfo(RegattaAndRaceIdentifier raceIdentifier, + Map legInfo) throws NotRevokableException; + + /** + * Into the {@link RaceLog} identified by the leaderboard, race column and fleet names, writes + * {@link RaceLogORCLegDataEvent}s and/or revokation events such that afterwards the + * {@link #getORCPerformanceCurveLegInfo(RegattaAndRaceIdentifier)} will return a map equal to the one passed, + * except for {@code null} values which then would be missing from the results, where here they mean to explicitly + * revoke any previous setting for that leg. + * + * @throws NotFoundException + * in case the race log cannot be found by the leaderboard, race column and fleet names provided + */ + void setORCPerformanceCurveLegInfo(String leaderboardName, String raceColumnName, String fleetName, + Map legInfo) throws NotFoundException, NotRevokableException; + + /** + * @return The RaceDTO of the modified race or null, if the given newStartTimeReceived was null. + */ + RaceDTO setStartTimeReceivedForRace(RaceIdentifier raceIdentifier, Date newStartTimeReceived) + throws UnauthorizedException; + + /** + * Slices a new race from the race specified by the given {@link RegattaAndRaceIdentifier} using the given time + * range. A new {@link RaceColumn} with the given name is added to the {@link RegattaLeaderboard}. + * + * @throws ServiceException + */ + RegattaAndRaceIdentifier sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName, + TimePoint sliceFrom, TimePoint sliceTo) throws UnauthorizedException, ServiceException; + + /** + * @return the new net points in {@link Pair#getA()} and the new total points in {@link Pair#getB()} for time point + * date after the max points reason has been updated to maxPointsReasonAsString. + */ + Util.Triple updateLeaderboardMaxPointsReason(String leaderboardName, + String competitorIdAsString, String raceColumnName, MaxPointsReason maxPointsReason, Date date) + throws NoWindException, UnauthorizedException; + + /** + * Updates given tagToUpdate with the given attributes tag, comment, + * imageURL and visibleForPublic. Tags are not really updated, instead public tags are + * revoked/private tags removed first and then the new tags gets saved depending on the new value + * visibleForPublic. + * + * @param leaderboardName + * required to identify {@link RaceLog}, must NOT be null + * @param raceColumnName + * required to identify {@link RaceLog}, must NOT be null + * @param fleetName + * required to identify {@link RaceLog}, must NOT be null + * @param tagToUpdate + * tag to be updated + * @param tag + * new tag title + * @param comment + * new comment + * @param imageURL + * new image url + * @param visibleForPublic + * new visibility status + * @return successful {@link SuccessInfo} if tag was updated successfully, otherwise + * non-successful {@link SuccessInfo} + */ + SuccessInfo updateTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tagToUpdate, + String tag, String comment, String imageURL, String resizedImageURL, boolean visibleForPublic) + throws UnauthorizedException; + /** + * Returns {@code true} if the given race can be sliced. Only Smarthphone tracked races can be sliced. In addition + * the race must be part of a {@link RegattaLeaderboard}. + */ + boolean canSliceRace(RegattaAndRaceIdentifier raceIdentifier) throws UnauthorizedException; + + + /** + * @param raceLogFrom + * identifies the race log to copy from by its leaderboard name, race column name and fleet name + * @param raceLogsTo + * identifies the race log to copy from by their leaderboard name, race column name and fleet name + * @throws NotFoundException + */ + void copyCompetitorsToOtherRaceLogs(Triple fromTriple, + Set> toTriples) throws UnauthorizedException, NotFoundException; + /** + * @param priority + * TODO + * @param raceLogFrom + * identifies the race log to copy from by its leaderboard name, race column name and fleet name + * @param raceLogsTo + * identifies the race log to copy from by their leaderboard name, race column name and fleet name + * @throws NotFoundException + */ + void copyCourseToOtherRaceLogs(Triple fromTriple, + Set> toTriples, int priority) + throws UnauthorizedException, NotFoundException; + + /** + * Adds a fix to the {@link SensorFixStore}, and creates a mapping with a virtual device for exactly the current + * timepoint. + * + * @param timePoint + * the time point for the fix; if {@code null}, the current time is used + * + * @throws DoesNotHaveRegattaLogException + * @throws NotFoundException + */ + void pingMark(String leaderboardName, MarkDTO mark, TimePoint timePoint, Position position) + throws UnauthorizedException, DoesNotHaveRegattaLogException, NotFoundException; + + /** + * Revoke the {@link RaceLogDenoteForTrackingEvent}. This does not affect an existing {@code RaceLogRaceTracker} or + * {@link TrackedRace} for this {@code RaceLog}. + * + * @throws UnauthorizedException, + * NotFoundException + * + * @see RaceLogTrackingAdapter#removeDenotationForRaceLogTracking + */ + void removeDenotationForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName) + throws UnauthorizedException, NotFoundException; + + /** + * Removes public {@link TagDTO tag} from {@link RaceLog} and private {@link TagDTO tag} from {@link UserStore}. + * + * @param leaderboardName + * required to identify {@link RaceLog}, must NOT be null + * @param raceColumnName + * required to identify {@link RaceLog}, must NOT be null + * @param fleetName + * required to identify {@link RaceLog}, must NOT be null + * @param tag + * tag to remove + * @return successful {@link SuccessInfo} if tag was removed successfully, otherwise + * non-successful {@link SuccessInfo} + */ + SuccessInfo removeTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag) + throws UnauthorizedException; + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceWriteAsync.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceWriteAsync.java new file mode 100644 index 00000000000..6ed0410fa34 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceWriteAsync.java @@ -0,0 +1,564 @@ +package com.sap.sailing.gwt.ui.client; + +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.shiro.authz.AuthorizationException; +import org.apache.shiro.authz.UnauthorizedException; + +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.common.CompetitorDescriptor; +import com.sap.sailing.domain.common.CompetitorRegistrationType; +import com.sap.sailing.domain.common.DataImportProgress; +import com.sap.sailing.domain.common.MaxPointsReason; +import com.sap.sailing.domain.common.PassingInstruction; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.RankingMetrics; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.RegattaIdentifier; +import com.sap.sailing.domain.common.RegattaName; +import com.sap.sailing.domain.common.RegattaNameAndRaceName; +import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.common.WindSource; +import com.sap.sailing.domain.common.dto.BoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTO; +import com.sap.sailing.domain.common.dto.FleetDTO; +import com.sap.sailing.domain.common.dto.PairingListDTO; +import com.sap.sailing.domain.common.dto.RaceColumnInSeriesDTO; +import com.sap.sailing.domain.common.dto.RaceDTO; +import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO; +import com.sap.sailing.domain.common.dto.TagDTO; +import com.sap.sailing.domain.common.orc.ORCCertificate; +import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveLegImpl; +import com.sap.sailing.expeditionconnector.ExpeditionDeviceConfiguration; +import com.sap.sailing.gwt.ui.adminconsole.RaceLogSetTrackingTimesDTO; +import com.sap.sailing.gwt.ui.shared.BulkScoreCorrectionDTO; +import com.sap.sailing.gwt.ui.shared.ControlPointDTO; +import com.sap.sailing.gwt.ui.shared.DeviceConfigurationDTO.RegattaConfigurationDTO; +import com.sap.sailing.gwt.ui.shared.DeviceIdentifierDTO; +import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO; +import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sailing.gwt.ui.shared.GPSFixDTO; +import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; +import com.sap.sailing.gwt.ui.shared.MarkDTO; +import com.sap.sailing.gwt.ui.shared.MigrateGroupOwnerForHierarchyDTO; +import com.sap.sailing.gwt.ui.shared.RegattaDTO; +import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTOWithSecurity; +import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationWithSecurityDTO; +import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationWithSecurityDTO; +import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDTO; +import com.sap.sailing.gwt.ui.shared.TracTracConfigurationWithSecurityDTO; +import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDTO; +import com.sap.sailing.gwt.ui.shared.TypedDeviceMappingDTO; +import com.sap.sailing.gwt.ui.shared.UrlDTO; +import com.sap.sailing.gwt.ui.shared.VenueDTO; +import com.sap.sailing.gwt.ui.shared.WindDTO; +import com.sap.sailing.gwt.ui.shared.courseCreation.CourseTemplateDTO; +import com.sap.sailing.gwt.ui.shared.courseCreation.MarkPropertiesDTO; +import com.sap.sailing.gwt.ui.shared.courseCreation.MarkRoleDTO; +import com.sap.sailing.gwt.ui.shared.courseCreation.MarkTemplateDTO; +import com.sap.sse.common.Duration; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.Util.Triple; +import com.sap.sse.gwt.client.filestorage.FileStorageManagementGwtServiceAsync; +import com.sap.sse.gwt.client.media.ImageDTO; +import com.sap.sse.gwt.client.media.ImageResizingTaskDTO; +import com.sap.sse.gwt.client.media.VideoDTO; +import com.sap.sse.pairinglist.PairingList; +import com.sap.sse.security.ui.shared.SuccessInfo; + +public interface SailingServiceWriteAsync extends FileStorageManagementGwtServiceAsync, SailingServiceAsync { + + void addCourseDefinitionToRaceLog(String leaderboardName, String raceColumnName, String fleetName, + List> course, int priority, AsyncCallback callback) + throws UnauthorizedException; + + void addMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, + GPSFixDTO newFix, AsyncCallback callback) throws UnauthorizedException; + + void addMarkToRegattaLog(String leaderboardName, MarkDTO mark, AsyncCallback callback) + throws UnauthorizedException/*, DoesNotHaveRegattaLogException*/; + + void addOrReplaceExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration expeditionDeviceConfiguration, AsyncCallback callback) + throws UnauthorizedException; + + void addOrUpdateBoat(BoatDTO boat, AsyncCallback callback) throws UnauthorizedException; + + void addOrUpdateCompetitors(List competitors, AsyncCallback> callback) throws UnauthorizedException; + + void addOrUpdateCompetitorWithBoat(CompetitorWithBoatDTO competitor, AsyncCallback callback) + throws UnauthorizedException; + + void addOrUpdateCompetitorWithoutBoat(CompetitorDTO competitor, AsyncCallback callback) throws UnauthorizedException; + + void addOrUpdateMarkProperties(MarkPropertiesDTO markProperties, AsyncCallback callback); + + void addOrUpdateMarkTemplate(MarkTemplateDTO markTemplate, AsyncCallback callback); + + void addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, + List> columnNames, AsyncCallback> callback); + + void addResultImportUrl(String resultProviderName, UrlDTO url, AsyncCallback callback) throws UnauthorizedException/*, Exception*/; + + void addTag(String leaderboardName, String raceColumnName, String fleetName, String tag, String comment, + String imageURL, String resizedImageURL, boolean visibleForPublic, TimePoint raceTimepoint, + AsyncCallback callback) throws UnauthorizedException; + + void addCompetitors(List competitorsForSaving, String searchTag, AsyncCallback> callback) + throws UnauthorizedException; + + void addColumnsToLeaderboard(String leaderboardName, List> columnsToAdd, AsyncCallback callback) + throws UnauthorizedException; + + void addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace, AsyncCallback callback) + throws UnauthorizedException; + + void addTypedDeviceMappingToRegattaLog(String leaderboardName, TypedDeviceMappingDTO dto, AsyncCallback callback) + /*throws NoCorrespondingServiceRegisteredException, TransformationException, DoesNotHaveRegattaLogException, + NotFoundException*/; + + void addDeviceMappingToRegattaLog(String leaderboardName, DeviceMappingDTO dto, AsyncCallback callback) + /*throws NoCorrespondingServiceRegisteredException, TransformationException, DoesNotHaveRegattaLogException*/; + + + void allowBoatResetToDefaults(List boats, AsyncCallback callback) throws UnauthorizedException; + + void setTrackingTimes(RaceLogSetTrackingTimesDTO dto, AsyncCallback callback); + + /** + * Copies one race's competitor set to other races. + * @param fromTriple + * leaderboard name, race column name, and fleet name identifying the race from which to copy the + * competitors + * @param toTriples leaderboard name, race column name, and fleet name identifying the races to which to copy the + * competitors + */ + void copyCompetitorsToOtherRaceLogs(Triple fromTriple, + Set> toTriples, AsyncCallback callback); + + void copyCourseToOtherRaceLogs(Triple fromTriple, + Set> toTriples, int priority, AsyncCallback callback); + + void revokeMarkDefinitionEventInRegattaLog(String leaderboardName, MarkDTO markDTO, AsyncCallback callback); + + void disableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName, + AsyncCallback asyncCallback); + + void enableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName, + AsyncCallback asyncCallback); + + void setBoatRegistrationsInRegattaLog(String leaderboardName, Set boats, + AsyncCallback callback); + + void editMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, + GPSFixDTO oldFix, Position newPosition, AsyncCallback callback); + + void removeMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, + GPSFixDTO fix, AsyncCallback callback); + + void setEliminatedCompetitors(String leaderboardName, Set eliminatedCompetitors, AsyncCallback callback); + + void removeExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration expeditionDeviceConfiguration, AsyncCallback asyncCallback); + + /** + * Registers all competitors of a {@link PairingList} in the respective {@link RaceColumn}s and {@link Fleet}s. + * + * @param leaderboardName + * the name of the leaderboard + * @param flightMultiplier + * specifies how often the flights will be cloned + * @param callback + */ + void fillRaceLogsFromPairingListTemplate(final String leaderboardName, final int flightMultiplier, + final List selectedFlightNames,PairingListDTO pairingListDTO, AsyncCallback callback); + + /** + * Checks whether the user may cut the race identified by {@code radeIdentifier} into multiple races. For this, it + * has to be found and it has to be a "smartphone-tracked" race with a valid start-of-tracking time. If not, + * {@code false} will be returned. If the user it not permitted to slice the race, e.g., because no + * permission has been granted to modify the leaderboard or regatta, an {@link AuthorizationException} will be + * thrown. + */ + void canSliceRace(RegattaAndRaceIdentifier raceIdentifier, AsyncCallback callback); + + void sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName, TimePoint sliceFrom, TimePoint sliceTo, + AsyncCallback callback); + + + /** + * @see SailingService#resizeImage(ImageResizingTaskDTO) + * @param imageResizingTask the information on how the contained ImageDTO should be resized + * @param asyncCallback The callback called after finishing resizing, storing the returned ImageDTOs somewhere is proposed + */ + void resizeImage(ImageResizingTaskDTO imageResizingTask, AsyncCallback> asyncCallback); + void updateGroupOwnerForEventHierarchy(UUID eventId, + MigrateGroupOwnerForHierarchyDTO migrateGroupOwnerForHierarchyDTO, AsyncCallback callback); + + void updateGroupOwnerForLeaderboardGroupHierarchy(UUID leaderboardGroupId, + MigrateGroupOwnerForHierarchyDTO migrateGroupOwnerForHierarchyDTO, AsyncCallback callback); + + void getSecretForRegattaByName(String leaderboardName, AsyncCallback asyncCallback); + + void setORCPerformanceCurveLegInfo(RegattaAndRaceIdentifier raceIdentifier, + Map legInfo, AsyncCallback callback); + + void setORCPerformanceCurveLegInfo(String leaderboardName, String raceColumnName, String fleetName, + Map legInfo, AsyncCallback callback); + + void assignORCPerformanceCurveCertificates(RegattaIdentifier regattaIdentifier, + Map certificatesForBoatsWithIdAsString, + AsyncCallback> callback); + + void assignORCPerformanceCurveCertificates(String leaderboardName, String raceColumnName, String fleetName, + Map certificatesForBoatsWithIdAsString, + AsyncCallback> callback); + + void getORCPerformanceCurveScratchBoat(String leaderboardName, String raceColumnName, String fleetName, + AsyncCallback asyncCallback); + + void setORCPerformanceCurveScratchBoat(String leaderboardName, String raceColumnName, String fleetName, CompetitorDTO newScratchBoat, + AsyncCallback asyncCallback); + + void updateMarkPropertiesPositioning(UUID markPropertiesId, DeviceIdentifierDTO deviceIdentifier, Position position, AsyncCallback asyncCallback); + + void createOrUpdateCourseTemplate(CourseTemplateDTO courseTemplate, AsyncCallback asyncCallback); + + /** + * Remove mark properties by UUIDs + * + * @param markPropertiesUuids + * the {@link Collection} of mark properties' UUIDs which will be remove + * @param asyncCallback + * {@link AsyncCallback} object + */ + void removeMarkProperties(Collection markPropertiesUuids, AsyncCallback asyncCallback); + + void createMarkRole(MarkRoleDTO markRole, AsyncCallback asyncCallback); + + /** + * @param regattaToAddTo + * if null, the regatta into which the race has previously been loaded will be looked up; if + * found, the race will be loaded into that regatta; otherwise, an existing regatta by the name of the + * TracTrac event with the boat class name appended in parentheses will be looked up; if not found, a + * default regatta with that name will be created, with a single default series and a single default + * fleet. If a valid {@link RegattaIdentifier} is specified, a regatta lookup is performed with that + * identifier; if the regatta is found, it is used to add the races to. Otherwise, a default regatta as + * described above will be created and used. + * @param liveURI + * may be null or the empty string in which case the server will use the + * {@link TracTracRaceRecordDTO#liveURI} from the rr race record. + * @param offsetToStartTimeOfSimulatedRace + * if not null, the connector will adjust the time stamps of all events received such that + * the first mark passing for the first waypoint will be set to "now." It will delay the forwarding of + * all events received such that they seem to be sent in "real-time" plus the + * offsetToStartTimeOfSimulatedRace. So, more or less the time points attached to the events + * sent to the receivers will again approximate the wall time. + * @param useInternalMarkPassingAlgorithm + * whether or not to ignore the TracTrac-provided mark passings; if true, a separate mark + * passing calculator is used, and the TracTrac-provided ones are ignored. + * @param storedURImay + * be null or the empty string in which case the server will use the + * {@link TracTracRaceRecordDTO#storedURI} from the rr race record. + */ + void trackWithTracTrac(RegattaIdentifier regattaToAddTo, List rrs, String liveURI, + String storedURI, String courseDesignUpdateURI, boolean trackWind, boolean correctWindByDeclination, + Duration offsetToStartTimeOfSimulatedRace, boolean useInternalMarkPassingAlgorithm, + boolean useOfficialEventsToUpdateRaceLog, String tracTracUsername, + String tracTracPassword, AsyncCallback callback); + + void trackWithSwissTiming(RegattaIdentifier regattaToAddTo, List rrs, String hostname, + int port, boolean trackWind, boolean correctWindByDeclination, boolean useInternalMarkPassingAlgorithm, + String updateURL, String updateUsername, String updatePassword, String eventName, + String manage2SailEventUrl, AsyncCallback asyncCallback); + + + void createTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI, + String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword, AsyncCallback callback); + + void deleteTracTracConfigurations(Collection tracTracConfigurations, + AsyncCallback callback); + + void updateTracTracConfiguration(TracTracConfigurationWithSecurityDTO tracTracConfiguration, + AsyncCallback callback); + + void stopTrackingRaces(List racesToStopTracking, AsyncCallback asyncCallback); + + /** + * Untracks the race and removes it from the regatta. It will also be removed in all leaderboards + * + * @param regattaNamesAndRaceNames + * The identifier for the regatta name, and the race name to remove + */ + void removeAndUntrackRaces(List regattaNamesAndRaceNames, AsyncCallback callback); + + void setWind(RegattaAndRaceIdentifier raceIdentifier, WindDTO wind, AsyncCallback callback); + + void removeWind(RegattaAndRaceIdentifier raceIdentifier, WindDTO windDTO, AsyncCallback callback); + + + void updateLeaderboard(String leaderboardName, String newLeaderboardDisplayName, int[] newDiscardingThreasholds, + List newCourseAreaIds, AsyncCallback callback); + + void createFlexibleLeaderboard(String leaderboardName, String leaderboardDisplayName, + int[] discardThresholds, + ScoringSchemeType scoringSchemeType, List courseAreaIds, + AsyncCallback asyncCallback); + + void createRegattaLeaderboard(RegattaName regattaIdentifier, + String leaderboardDisplayName, + int[] discardThresholds, AsyncCallback asyncCallback); + + void createRegattaLeaderboardWithEliminations(String name, String displayName, + String regattaName, + AsyncCallback asyncCallback); + + void removeLeaderboard(String leaderboardName, AsyncCallback asyncCallback); + + void removeLeaderboards(Collection leaderboardNames, AsyncCallback asyncCallback); + + void renameLeaderboardColumn(String leaderboardName, String oldColumnName, String newColumnName, + AsyncCallback callback); + + void removeLeaderboardColumn(String leaderboardName, String columnName, AsyncCallback callback); + + void connectTrackedRaceToLeaderboardColumn(String leaderboardName, String raceColumnName, String fleetName, + RegattaAndRaceIdentifier raceIdentifier, AsyncCallback asyncCallback); + + void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName, String fleetName, + AsyncCallback callback); + + void updateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Double carriedPoints, + AsyncCallback callback); + + void updateLeaderboardMaxPointsReason(String leaderboardName, String competitorIdAsString, String raceColumnName, + MaxPointsReason maxPointsReason, Date date, + AsyncCallback> asyncCallback); + + void updateLeaderboardScoreCorrection(String leaderboardName, String competitorIdAsString, String columnName, + Double correctedScore, Date date, AsyncCallback> asyncCallback); + + void updateLeaderboardScoreCorrectionMetadata(String leaderboardName, Date timePointOfLastCorrectionValidity, + String comment, AsyncCallback callback); + + void updateLeaderboardScoreCorrectionsAndMaxPointsReasons(BulkScoreCorrectionDTO updates, + AsyncCallback callback); + + void updateCompetitorDisplayNameInLeaderboard(String leaderboardName, String competitorID, String displayName, + AsyncCallback callback); + + void moveLeaderboardColumnUp(String leaderboardName, String columnName, AsyncCallback callback); + + void moveLeaderboardColumnDown(String leaderboardName, String columnName, AsyncCallback callback); + + void updateIsMedalRace(String leaderboardName, String columnName, boolean isMedalRace, AsyncCallback callback); + + void updateRacesDelayToLive(List regattaAndRaceIdentifiers, long delayToLiveInMs, + AsyncCallback callback); + + void createSwissTimingConfiguration(String configName, String jsonURL, String hostname, Integer port, + String updateURL, String updateUsername, String updatePassword, AsyncCallback asyncCallback); + + void updateSwissTimingConfiguration(SwissTimingConfigurationWithSecurityDTO configuration, + AsyncCallback asyncCallback); + + void deleteSwissTimingConfigurations(Collection configurations, + AsyncCallback asyncCallback); + + /** + * Removes the leaderboard groups with the given names from the service and the persistant store. + */ + void removeLeaderboardGroups(Set groupNames, AsyncCallback asyncCallback); + + /** + * Creates a new group with the name groupname, the description description and an empty + * list of leaderboards.
    + */ + void createLeaderboardGroup(String groupName, String description, String displayName, + boolean displayGroupsInReverseOrder, int[] overallLeaderboardDiscardThresholds, + ScoringSchemeType overallLeaderboardScoringSchemeType, AsyncCallback callback); + + void updateLeaderboardGroup(UUID leaderboardGroupId, String oldName, String newName, String description, String newDisplayName, + List leaderboardNames, int[] overallLeaderboardDiscardThresholds, + ScoringSchemeType overallLeaderboardScoringSchemeType, AsyncCallback callback); + + void setRaceIsKnownToStartUpwind(RegattaAndRaceIdentifier raceIdentifier, boolean raceIsKnownToStartUpwind, + AsyncCallback callback); + + void setWindSourcesToExclude(RegattaAndRaceIdentifier raceIdentifier, List windSourcesToExclude, + AsyncCallback callback); + + + /** + * Renames the event with the name oldName to the newName.
    + * If there's no event with the name oldName or there's already a event with the name + * newName a {@link IllegalArgumentException} is thrown. + */ + void renameEvent(UUID eventId, String newName, AsyncCallback callback); + + /** + * Removes the event with the id id from the service and the persistence store. + */ + void removeEvent(UUID eventId, AsyncCallback callback); + + void removeEvents(Collection eventIds, AsyncCallback asyncCallback); + + void createEvent(String eventName, String eventDescription, Date startDate, Date endDate, String venue, + boolean isPublic, List courseAreaNames, String officialWebsiteURL, String baseURL, + Map sailorsInfoWebsiteURLsByLocaleName, List images, + List videos, List leaderboardGroupIDs, + AsyncCallback callback); + + void updateEvent(UUID eventId, String eventName, String eventDescription, Date startDate, Date endDate, + VenueDTO venue, boolean isPublic, List leaderboardGroupIds, String officialWebsiteURL, + String baseURL, Map sailorsInfoWebsiteURLsByLocaleName, List images, + List videos, List windFinderReviewedSpotCollectionIds, AsyncCallback callback); + + void createCourseAreas(UUID eventId, String[] courseAreaNames, AsyncCallback callback); + + void removeCourseAreas(UUID eventId, UUID[] idsOfCourseAreasToRemove, AsyncCallback callback); + + void removeRegatta(RegattaIdentifier regattaIdentifier, AsyncCallback callback); + + void removeRegattas(Collection regattas, AsyncCallback asyncCallback); + + void createRegatta(String regattaName, String boatClassName, boolean canBoatsOfCompetitorsChangePerRace, + CompetitorRegistrationType competitorRegistrationType, String registrationLinkSecret, Date startDate, Date endDate, + RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal, boolean persistent, + ScoringSchemeType scoringSchemeType, List courseAreaIds, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, + boolean controlTrackingFromStartAndFinishTimes, boolean autoRestartTrackingUponCompetitorSetChange, + RankingMetrics rankingMetricType, AsyncCallback callback); + + void updateSeries(RegattaIdentifier regattaIdentifier, String seriesName, String newSeriesName, boolean isMedal, + boolean isFleetsCanRunInParallel, int[] resultDiscardingThresholds, boolean startsWithZeroScore, + boolean firstRaceIsNonDiscardableCarryForward, boolean hasSplitFleetScore, Integer maximumNumberOfDiscards, + List fleets, AsyncCallback callback); + + void removeRaceColumnsFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, List columnNames, + AsyncCallback callback); + + void updateRaceCourse(RegattaAndRaceIdentifier raceIdentifier, + List> controlPoints, AsyncCallback callback); + + void removeResultImportURLs(String resultProviderName, Set toRemove, AsyncCallback callback); + + void suppressCompetitorInLeaderboard(String leaderboardName, String competitorIdAsString, boolean suppressed, + AsyncCallback asyncCallback); + + void updateLeaderboardColumnFactor(String leaderboardName, String columnName, Double newFactor, + AsyncCallback callback); + + void createSwissTimingArchiveConfiguration(String jsonUrl, AsyncCallback asyncCallback); + + void updateSwissTimingArchiveConfiguration(SwissTimingArchiveConfigurationWithSecurityDTO dto, + AsyncCallback asyncCallback); + + void deleteSwissTimingArchiveConfigurations(Collection dtos, + AsyncCallback asyncCallback); + + void updateRegatta(RegattaIdentifier regattaIdentifier, Date startDate, Date endDate, List courseAreaUuids, + RegattaConfigurationDTO regattaConfiguration, Double buoyZoneRadiusInHullLengths, + boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes, + boolean autoRestartTrackingUponCompetitorSetChange, String registrationLinkSecret, + CompetitorRegistrationType registrationType, AsyncCallback callback); + + void importMasterData(String host, String[] names, boolean override, boolean compress, boolean exportWind, + boolean exportDeviceConfigurations, String targetServerUsername, String targetServerPassword, + boolean exportTrackedRacesAndStartTracking, AsyncCallback asyncCallback); + + void getImportOperationProgress(UUID id, AsyncCallback asyncCallback); + + void allowCompetitorResetToDefaults(List competitors, AsyncCallback asyncCallback); + + void removeDeviceConfiguration(UUID deviceConfigurationId, AsyncCallback asyncCallback); + + void authorizeAccessToIgtimiUser(String eMailAddress, String password, AsyncCallback callback); + + void removeIgtimiAccount(String eMailOfAccountToRemove, AsyncCallback asyncCallback); + + void importWindFromIgtimi(List selectedRaces, boolean correctByDeclination, + AsyncCallback> asyncCallback); + + /** + * @return {@code true} if the race was not yet denoted for race log tracking and now has successfully been denoted + * so + */ + void denoteForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName, + AsyncCallback callback); + + void denoteForRaceLogTracking(String leaderboardName,String prefix, AsyncCallback callback); + + void startRaceLogTracking(List> leaderboardRaceColumnFleetNames, + final boolean trackWind, final boolean correctWindByDeclination, AsyncCallback callback); + + /** + * Set the competitor (with contained boats) registrations in the racelog. Unregisters formerly registered competitors that are not listed + * in {@code competitors}. + */ + void setCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName, + Set competitors, AsyncCallback callback); + + /** + * Set the competitor and boat registrations in the racelog. Unregisters formerly registered competitors that are not listed + * in {@code competitors}. + */ + void setCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName, + Map competitorsAndBoats, AsyncCallback callback); + + /** + * Set the competitor registrations in the leaderboard. Unregisters formerly registered competitors that are not + * listed in {@code competitors}. + */ + void setCompetitorRegistrationsInRegattaLog(String leaderboardName, Set competitors, + AsyncCallback callback); + + void updateTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tagToUpdate, String tag, + String comment, String imageURL, String resizedImageURL, boolean visibleForPublic, AsyncCallback asyncCallback); + + void removeTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag, + AsyncCallback asyncCallback); + + void pingMark(String leaderboardName, MarkDTO mark, + TimePoint timePoint, Position position, AsyncCallback callback); + + void removeSeries(RegattaIdentifier regattaIdentifier, String seriesName, AsyncCallback callback); + + void removeDenotationForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName, + AsyncCallback callback); + + void setStartTimeReceivedForRace(RaceIdentifier raceIdentifier, Date newStartTimeReceived, + AsyncCallback callback); + + void updateSuppressedMarkPassings(String leaderboardName, String raceColumnName, String fleetName, + Integer newZeroBasedIndexOfSuppressedMarkPassing, CompetitorDTO competitorDTO, AsyncCallback callback); + + void createRegattaStructure(List regattaNames, EventDTO newEvent, + AsyncCallback asyncCallback); + + void updateFixedMarkPassing(String leaderboardName, String raceColumnName, String fleetName, + Integer indexOfWaypoint, Date dateOfMarkPassing, CompetitorDTO competitorDTO, AsyncCallback callback); + + void inviteCompetitorsForTrackingViaEmail(String serverUrlWithoutTrailingSlash, EventDTO event, + String leaderboardName, Collection competitors, String iOSAppUrl, String androidAppUrl, + String localeInfo, + AsyncCallback callback); + + void inviteBuoyTenderViaEmail(String serverUrlWithoutTrailingSlash, EventDTO eventDto, String leaderboardName, + String emails, String iOSAppUrl, String androidAppUrl, String localeInfoName, AsyncCallback callback); + + void revokeRaceAndRegattaLogEvents(String leaderboardName, List eventIds, AsyncCallback callback); + + void closeOpenEndedDeviceMapping(String leaderboardName, DeviceMappingDTO mappingDto, Date closingTimePoint, + AsyncCallback asyncCallback); + + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java index cf2f0a6121a..e3b9f9b9db5 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.java @@ -976,6 +976,9 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String editCompetitor(); String pleaseEnterASailNumber(); String pleaseEnterASailNumberOrABoatName(); + String addCompetitor(); + String editCompetitorWithBoat(); + String withBoat(); String successfullyAllowedCompetitorReset(String names); String successfullyAllowedBoatReset(String names); String allowReload(); @@ -2382,4 +2385,5 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages, String whitelabelFooterLanguage(); String whitelabelSailing(); String unableToLoadCourseAreas(String message); + String insufficientPermissions(); } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties index 6282f110213..69ef2f8835f 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages.properties @@ -966,6 +966,9 @@ filterBoats=Filter boats by name, boat class, sail number or ID editCompetitor=Edit Competitor pleaseEnterASailNumber=Please enter a sail number pleaseEnterASailNumberOrABoatName=Please enter a sail number or a boat name +addCompetitor=Add Competitor +editCompetitorWithBoat=Edit competitor with boat +withBoat=With Boat successfullyAllowedCompetitorReset=Successfully allowed reload of competitor(s) {0}. successfullyAllowedBoatReset=Successfully allowed reload of boats(s) {0}. id=ID @@ -2375,7 +2378,7 @@ runVMG=Run VMG beatAngles=Beat angles runAngles=Run angles exportTrackedRacesAndStartTracking=Import Tracked Races and Start Tracking -exportTrackedRacesAndStartTrackingTooltip=Please make sure you add the connector specific URL in the Connectors tab afterwards, as they will not be imported currently +exportTrackedRacesAndStartTrackingTooltip=Import the tracked Races, start the tracking and add the connectivity parameters to the connectors-tab importTrackedRaces=Importing Tracked Races unsetPosition=Unset position errorTryingToUpdateMarkProperties=Error trying to update mark properties: {0} @@ -2385,4 +2388,6 @@ keepEmptyForDefaultUserAndPassword=If username and password are left empty the c autoRestartTrackingUponCompetitorSetChange=Restart tracking of races automatically when competitor set changes whitelabelFooterLanguage=Sailing in whitelabelSailing=Sailing -unableToLoadCourseAreas=Unable to load course areas: {0} \ No newline at end of file +unableToLoadCourseAreas=Unable to load course areas: {0} +serverName=Server Name: {0} +insufficientPermissions=The current user has insufficient permissions for this action. Please log in with an authorized user. \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties index 876c3fd3c85..60d4d5b9f36 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_de.properties @@ -950,6 +950,9 @@ filterBoats=Filtere Boote nach Name, Bootsklasse, Segelnummer oder ID editCompetitor=Teilnehmer bearbeiten pleaseEnterASailNumber=Bitte die Segelnummer eingeben pleaseEnterASailNumberOrABoatName=Bitte die Segelnummer oder den Bootsnamen eingeben +addCompetitor=Teilnehmer hinzufügen +editCompetitorWithBoat=Teilnehmer mit Boot bearbeiten +withBoat=Mit Boot successfullyAllowedCompetitorReset=Aktualisierung der Daten zu Teilnehmer(n) {0} erfolgreich ermöglicht.id=ID successfullyAllowedBoatReset=Aktualisierung der Daten zu Boot(en) {0} erfolgreich ermöglicht.id=ID allowReload=Aktualisierung ermöglichen @@ -2386,11 +2389,13 @@ beatAngles=Kreuzwinkel runAngles=Vorwindwinkel unsetPosition=Positionsangabe entfernen exportTrackedRacesAndStartTracking=Getrackte Rennen importieren und Tracking starten -exportTrackedRacesAndStartTrackingTooltip=Die Connector-spezifischen Verbindungsinformationen (Connectors tab) werden nicht importiert. Sollten diese benötigt werden müssen sie manuell eingefügt werden. +exportTrackedRacesAndStartTrackingTooltip=Getrackte Rennen importieren, Tracking starten und Konnektor-spezifische Informationen zum Konnektoren-Tab hinzufügen importTrackedRaces=Getrackte Rennen werden importiert errorTryingToUpdateMarkProperties=Fehler beim Ändern der Bahnmarkeneigenschaften: {0} confirmUnsettingPositionForMarkProperties=Positionierungsinformation für Bahnmarkeneigenschaften {0} wirklich entfernen? useOfficialResultsForAutomaticUpdates=Automatisch von "offiziellen" von TracTrac veröffentlichten Ergebnissen aktualisieren keepEmptyForDefaultUserAndPassword=Wenn kein Benutzername und kein Kennwort eingetragen werden, wird der aktuelle Benutzer zum importieren verwendet. Wenn der aktuelle Nutzer die Berechtigung zum Exportieren der Daten auf dem Zielserver hat, können die Felder leer bleiben. Sollen jedoch die Daten eines anderen Benutzers importiert werden, sind Benutzername und Kennwort des Benutzers einzutragen. autoRestartTrackingUponCompetitorSetChange=Tracking der Rennen automatisch neu starten, wenn sich die Teilnehmerliste ändert -unableToLoadCourseAreas=Liste der Regattabahnen kann nicht geladen werden: {0} \ No newline at end of file +unableToLoadCourseAreas=Liste der Regattabahnen kann nicht geladen werden: {0} +serverName=Server Name: {0} +insufficientPermissions=Aktuelle Berechtigungen reichen nicht aus um die gewählte Aktion auszuführen. Bitte melden Sie sich als ein authorisier Benutzer an. \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties index 8b3ad366ded..d77ec0e4b73 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_es.properties @@ -960,6 +960,9 @@ filterBoats=Filtrar competidores por nombre, clase de embarcación, número de v editCompetitor=Editar competidor pleaseEnterASailNumber=Indique un número de vela pleaseEnterASailNumberOrABoatName=Indique un número de vela o un nombre de embarcación +addCompetitor=Añadir competidor +editCompetitorWithBoat=Editar competidor con embarcación +withBoat=Con embarcación successfullyAllowedCompetitorReset=Se ha permitido la recarga de competidor(es) {0}. successfullyAllowedBoatReset=Se ha permitido la recarga de embarcación(es) {0}. id=ID @@ -2378,3 +2381,4 @@ keepEmptyForDefaultUserAndPassword=Si el nombre de usuario se deja en blanco, el autoRestartTrackingUponCompetitorSetChange=Reiniciar seguimiento de carreras automáticamente cuando un competidor fija modificaciones whitelabelFooterLanguage=Navegando en whitelabelSailing=Navegando +unableToLoadCourseAreas=Imposible cargar zonas de rumbo: {0} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties index 437976d8971..ad71c44ca06 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_fr.properties @@ -960,6 +960,9 @@ filterBoats=Filtrer les bateaux par nom, catégorie de bateau, numéro de voile editCompetitor=Modifier concurrent pleaseEnterASailNumber=Saisissez un numéro de voile. pleaseEnterASailNumberOrABoatName=Saisissez un numéro de voile ou un nom de bateau. +addCompetitor=Ajouter un concurrent +editCompetitorWithBoat=Modifier un concurrent avec bateau +withBoat=Avec bateau successfullyAllowedCompetitorReset=Autorisation de rechargement de concurrent(s) réussie {0}. successfullyAllowedBoatReset=Autorisation de rechargement de bateau(x) réussie {0}. id=ID @@ -1401,9 +1404,9 @@ orcPerformanceCurveLeaderForBaselineRankingMetric=Courbe de performance ORC (>=2 orcPerformanceCurveByImpliedWindRankingMetric=Courbe de performance ORC avec vent implicite individuel (>=2015) timeOnTimeAndDistanceRankingMetric=Temps sur temps/Temps sur distance oneDesignRankingMetricDescription=Monotype : le vainqueur est le premier à franchir la ligne.\nLe classement se base sur les positions au vent (dans le lit du vent/vent arrière) ou en fonction de la position dans la course (jusqu''à atteindre un point). -orcPerformanceCurveRankingMetricDescription=Courbe de performance ORC : procédé de distribution des handicaps sophistiqué qui accorde des compensations de temps en fonction d''un VPP/polaire, en partant d''angles de portions de parcours prédéfinis par rapport au vent ;\nla valeur de vent implicite la plus élevée est déterminée ; tous les bateaux sont classés par un mappage de cette valeur la plus élevée du vent implicite sur leurs courbes de performance, determinant ainsi la compensation qui leur est accordée pour ce vent implicite\n, ensuite, calculant le delta par rapport au temps écoulé de la course de leur bateau. Le temps total calculé est déterminé en utilisant le temps écoulé de la course du bateau avec la valeur GPH la moins élevée comme valeur de référence. +orcPerformanceCurveRankingMetricDescription=Courbe de performance ORC : procédé de distribution des handicaps sophistiqué qui accorde des compensations de temps en fonction d''un VPP/polaire, en partant d''angles de portions de parcours prédéfinis par rapport au vent ;\nla valeur de vent implicite la plus élevée est déterminée ; tous les bateaux sont classés par un mappage de cette valeur la plus élevée du vent implicite sur leurs courbes de performance, déterminant ainsi la compensation qui leur est accordée pour ce vent implicite\n, ensuite, calculant le delta par rapport au temps écoulé de la course de leur bateau. Le temps total calculé est déterminé en utilisant le temps écoulé de la course du bateau avec la valeur GPH la moins élevée comme valeur de référence. orcPerformanceCurveByImpliedWindRankingMetricDescription=Courbe de performance ORC : procédé de distribution des handicaps sophistiqué qui accorde des compensations de temps en fonction d''un VPP/polaire, en imaginant des angles de portions de parcours prédéfinis par rapport au vent.\nEn fonction de ces compensations, un "vent implicite" est calculé et sert de base au classement.\nLe vent implicite peut être calculé à n''importe quel moment dans la course et sert alors de base pour le classement dans la course. -orcPerformanceCurveLeaderForBaselineRankingMetricDescription=Courbe de performance ORC : procédé de distribution des handicaps sophistiqué qui accorde des compensations de temps en fonction d''un VPP/polaire, en partant d''angles de portions de parcours prédéfinis par rapport au vent ;\nla valeur de vent implicite la plus élevée est déterminée ; touts les bateaux sont classées par un mappage de cette valeur la plus élevée du vent implicite sur leurs courbes de performance, determinant ainsi la compensation qui leur est accordée pour ce vent implicite\n, ensuite, calculant le delta par rapport au temps écoulé de la course de leur bateau. La valeur de référence pour les temps ajustés est le bateau avec le temps ajusté relatif le moins élevé. +orcPerformanceCurveLeaderForBaselineRankingMetricDescription=Courbe de performance ORC : procédé de distribution des handicaps sophistiqué qui accorde des compensations de temps en fonction d''un VPP/polaire, en partant d''angles de portions de parcours prédéfinis par rapport au vent ;\nla valeur de vent implicite la plus élevée est déterminée ; tous les bateaux sont classées par un mappage de cette valeur la plus élevée du vent implicite sur leurs courbes de performance, déterminant ainsi la compensation qui leur est accordée pour ce vent implicite\n, ensuite, calculant le delta par rapport au temps écoulé de la course de leur bateau. La valeur de référence pour les temps ajustés est le bateau avec le temps ajusté relatif le moins élevé. timeOnTimeAndDistanceRankingMetricDescription=Temps sur temps/Temps sur distance : classement final par temps calculé ;\nle temps est calculé en appliquant, de façon facultative, un facteur au temps réel (1.0 par défaut)\net en soustrayant une compensation en secondes par mille marin,\nappliqué à la longueur de la course.\nLe classement est effectué sur la base de l''arrivée estimée selon la position actuelle du bateau le plus rapide\nen supposant le VMG/VMC moyen. yardstickNumber=Numéro de mètre (échelle {0}) changeScale=Modifier échelle @@ -2352,14 +2355,14 @@ invalidImageURL=URL de l''image non valide invalidURL=URL non valide ou incomplet setDeviceIdentifier=Définir l''identificateur d''appareil setPosition=Définir la position -spareMarksAndTheirOptionalDefaultMarkRoles=Marques de rechange et leur rôles de marque par défaut facultatifs +spareMarksAndTheirOptionalDefaultMarkRoles=Marques de rechange et leurs rôles de marque par défaut facultatifs impliedWind=Vent implicite impliedWindTooltip=Le vent implicite est la vitesse réelle du vent hypothétique à laquelle le concurrent aurait terminé la partie de la course parcourue jusqu''à présent dans le temps écoulé jusqu''à présent, en fonction des prévisions de vitesse/fiche polaire. orcCertificate=Certificat ORC linkToOrcCertificate=Version PDF du certificat orcFileId=ID de fichier orcCertificateReferenceNumber=Numéro de référence -cdl=Longueur de divsion de classe (CDL) +cdl=Longueur de division de classe (CDL) gph=Handicap générique (GPH) lengthOverAllInMeters=Longueur totale (LOA) timeAllowances=Compensations de temps @@ -2378,3 +2381,4 @@ keepEmptyForDefaultUserAndPassword=Si le nom d''utilisateur et le mot de passe n autoRestartTrackingUponCompetitorSetChange=Relancer le suivi des courses automatiquement lorsque le concurrent active les modifications whitelabelFooterLanguage=Sailing en whitelabelSailing=Sailing +unableToLoadCourseAreas=Impossible de charger les zones de courses : {0} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_it.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_it.properties index 9ebbc4f738a..efb73b7b503 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_it.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_it.properties @@ -960,6 +960,9 @@ filterBoats=Filtra barche per nome, classe di barche, ID o numero vela editCompetitor=Modifica concorrente pleaseEnterASailNumber=Inserire un numero vela pleaseEnterASailNumberOrABoatName=Inserire un numero vela o un nome barca +addCompetitor=Aggiungi concorrente +editCompetitorWithBoat=Modifica concorrente con barca +withBoat=Con barca successfullyAllowedCompetitorReset=Ricaricamento concorrente/i consentito correttamente {0}. successfullyAllowedBoatReset=Ricaricamento barca/barche consentito correttamente {0}. id=ID @@ -2378,3 +2381,4 @@ keepEmptyForDefaultUserAndPassword=Se il nome utente e la password vengono lasci autoRestartTrackingUponCompetitorSetChange=Riavvia tracciamento gare automaticamente quando il concorrente ha impostato modifiche whitelabelFooterLanguage=Sailing in whitelabelSailing=Navigazione +unableToLoadCourseAreas=Impossibile caricare aree rotta: {0} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties index 08d3e5b0601..4ba92e4a2cc 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ja.properties @@ -960,6 +960,9 @@ filterBoats=艇をフィルタリングする名前、艇種、セールナン editCompetitor=競技者編集 pleaseEnterASailNumber=セールナンバーを入力してください pleaseEnterASailNumberOrABoatName=セールナンバーまたは艇名を入力してください +addCompetitor=競技者追加 +editCompetitorWithBoat=競技者編集 (艇あり) +withBoat=艇あり successfullyAllowedCompetitorReset=競技者 {0} のリロードが許可されました。 successfullyAllowedBoatReset=艇 {0} のリロードが許可されました。 id=ID @@ -2378,3 +2381,4 @@ keepEmptyForDefaultUserAndPassword=ユーザ名とパスワードが空白のま autoRestartTrackingUponCompetitorSetChange=競技者セットの変更でレースの追跡を自動的に再実行 whitelabelFooterLanguage=帆走: whitelabelSailing=帆走 +unableToLoadCourseAreas=コースエリアをロードできません: {0} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_pt.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_pt.properties index 0cc2cd3521e..ef3cc8a51ff 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_pt.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_pt.properties @@ -960,6 +960,9 @@ filterBoats=Filtrar barcos por nome, classe de barcos, número da vela ou ID editCompetitor=Processar competidor pleaseEnterASailNumber=Insira um número da vela. pleaseEnterASailNumberOrABoatName=Insira um número da vela ou um nome de barco +addCompetitor=Adicionar competidor +editCompetitorWithBoat=Processar competidor com barco +withBoat=Com barco successfullyAllowedCompetitorReset=Recarregamento de competidor(es) {0} permitido com êxito. successfullyAllowedBoatReset=Recarregamento de barco(s) {0} permitido com êxito. id=ID @@ -2378,3 +2381,4 @@ keepEmptyForDefaultUserAndPassword=Se o nome do usuário e a senha forem deixado autoRestartTrackingUponCompetitorSetChange=Reiniciar rastreamento de corridas automaticamente quando um concorrente define modificações whitelabelFooterLanguage=Vela em whitelabelSailing=Vela +unableToLoadCourseAreas=Impossível carregar áreas de percurso: {0} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties index c90fd1e38c5..1ceb8dde7b0 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_ru.properties @@ -960,6 +960,9 @@ filterBoats=Фильтрация лодок по названию, классу editCompetitor=Изменить участника pleaseEnterASailNumber=Введите номер на парусе pleaseEnterASailNumberOrABoatName=Введите номер на парусе или название лодки +addCompetitor=Добавить участника +editCompetitorWithBoat=Изменить участника с лодкой +withBoat=С лодкой successfullyAllowedCompetitorReset=Успешно разрешена перезагрузка участников: {0}. successfullyAllowedBoatReset=Успешно разрешена перезагрузка лодок:{0}. id=Ид. @@ -2378,3 +2381,4 @@ keepEmptyForDefaultUserAndPassword=Если имя пользователя и autoRestartTrackingUponCompetitorSetChange=Перезапускать отслеживание гонок автоматически при изменении набора участников whitelabelFooterLanguage=Отходит в whitelabelSailing=Плавание +unableToLoadCourseAreas=Невозможно загрузить зоны гонки: {0} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties index 8f87ddc6c4e..62a71470f7e 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/StringMessages_zh.properties @@ -960,6 +960,9 @@ filterBoats=按名称、船只级别、帆号或编号筛选船只 editCompetitor=编辑参赛队 pleaseEnterASailNumber=请输入帆号 pleaseEnterASailNumberOrABoatName=请输入帆号或船只名称 +addCompetitor=添加参赛队 +editCompetitorWithBoat=编辑参赛队与船只 +withBoat=与船只 successfullyAllowedCompetitorReset=已成功允许重新加载参赛队 {0}。 successfullyAllowedBoatReset=已成功允许重新加载船只 {0}。 id=编号 @@ -2378,3 +2381,4 @@ keepEmptyForDefaultUserAndPassword=如果用户名和密码留为空白,当前 autoRestartTrackingUponCompetitorSetChange=当参赛队设置更改时,自动重启比赛的跟踪 whitelabelFooterLanguage=Sailing 语言 whitelabelSailing=航行 +unableToLoadCourseAreas=无法加载场地区域:{0} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/MediaPlayerManagerComponent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/MediaPlayerManagerComponent.java index 7b83268d812..4a6022220b6 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/MediaPlayerManagerComponent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/MediaPlayerManagerComponent.java @@ -31,7 +31,7 @@ import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.gwt.ui.adminconsole.FileStorageServiceConnectionTestObservable; import com.sap.sailing.gwt.ui.client.MediaServiceAsync; import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.media.popup.PopoutWindowPlayer; import com.sap.sailing.gwt.ui.client.media.popup.PopoutWindowPlayer.PlayerCloseListener; @@ -94,7 +94,7 @@ public class MediaPlayerManagerComponent extends AbstractComponent playerChangeListener = new ArrayList<>(); public MediaPlayerManagerComponent(Component parent, ComponentContext context, - MediaPlayerLifecycle mediaPlayerLifecycle, SailingServiceAsync sailingService, + MediaPlayerLifecycle mediaPlayerLifecycle, SailingServiceWriteAsync sailingServiceWrite, RegattaAndRaceIdentifier selectedRaceIdentifier, RaceTimesInfoProvider raceTimesInfoProvider, Timer raceTimer, MediaServiceAsync mediaService, UserService userService, StringMessages stringMessages, ErrorReporter errorReporter, @@ -118,7 +118,7 @@ public class MediaPlayerManagerComponent extends AbstractComponent implements FileS @Override public String getErrorMessage(MediaTrack media) { String errorMessage = null; - if (media.url == null || media.url.trim().isEmpty()) { errorMessage = stringMessages.pleaseEnterNonEmptyUrl(); } else if (media.title == null || media.title.trim().isEmpty()) { @@ -74,10 +73,8 @@ public class NewMediaDialog extends DataEntryDialog implements FileS } else if (media.duration == null) { errorMessage = stringMessages.pleaseEnterA(stringMessages.duration()); } - return errorMessage; } - } protected final StringMessages stringMessages; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/NewMediaWithRaceSelectionDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/NewMediaWithRaceSelectionDialog.java index bdf14b61adb..560d6107f19 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/NewMediaWithRaceSelectionDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/media/NewMediaWithRaceSelectionDialog.java @@ -12,7 +12,7 @@ import com.sap.sailing.gwt.ui.adminconsole.FileStorageServiceConnectionTestObser import com.sap.sailing.gwt.ui.client.MediaServiceAsync; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.RegattasDisplayer; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sse.common.TimePoint; import com.sap.sse.gwt.client.ErrorReporter; @@ -20,7 +20,7 @@ import com.sap.sse.security.ui.client.UserService; public class NewMediaWithRaceSelectionDialog extends NewMediaDialog { - private SailingServiceAsync sailingService; + private SailingServiceWriteAsync sailingService; private ErrorReporter errorReporter; @@ -35,13 +35,13 @@ public class NewMediaWithRaceSelectionDialog extends NewMediaDialog { private UserService userService; public NewMediaWithRaceSelectionDialog(MediaServiceAsync mediaService, TimePoint defaultStartTime, - StringMessages stringMessages, SailingServiceAsync sailingService, UserService userService, + StringMessages stringMessages, SailingServiceWriteAsync sailingServiceWrite, UserService userService, ErrorReporter errorReporter, RegattaRefresher regattaRefresher, Set regattasDisplayers, FileStorageServiceConnectionTestObservable storageServiceConnection, com.sap.sse.gwt.client.dialog.DataEntryDialog.DialogCallback dialogCallback) { super(mediaService, defaultStartTime, stringMessages, null, storageServiceConnection, dialogCallback); - this.sailingService = sailingService; + this.sailingService = sailingServiceWrite; this.errorReporter = errorReporter; this.regattaRefresher = regattaRefresher; this.regattasDisplayers = regattasDisplayers; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/EditMarkPassingsPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/EditMarkPassingsPanel.java index 72f34aaec7b..ecf1fd5e3b7 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/EditMarkPassingsPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/EditMarkPassingsPanel.java @@ -36,6 +36,7 @@ import com.sap.sailing.gwt.ui.adminconsole.SetTimePointDialog; import com.sap.sailing.gwt.ui.client.CompetitorSelectionChangeListener; import com.sap.sailing.gwt.ui.client.CompetitorSelectionProvider; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.charts.RaceIdentifierToLeaderboardRaceColumnAndFleetMapper.LeaderboardNameRaceColumnNameAndFleetName; import com.sap.sailing.gwt.ui.shared.RaceCourseDTO; @@ -64,6 +65,7 @@ public class EditMarkPassingsPanel extends AbstractCompositeComponent parent, ComponentContext context, - final SailingServiceAsync sailingService, - final RegattaAndRaceIdentifier raceIdentifier, - final StringMessages stringMessages, final CompetitorSelectionProvider competitorSelectionModel, - final ErrorReporter errorReporter, final Timer timer) { + SailingServiceAsync sailingService, + final SailingServiceWriteAsync sailingServiceWrite, + final RegattaAndRaceIdentifier raceIdentifier, final StringMessages stringMessages, + final CompetitorSelectionProvider competitorSelectionModel, final ErrorReporter errorReporter, final Timer timer) { super(parent, context); this.raceIdentifierToLeaderboardRaceColumnAndFleetMapper = new RaceIdentifierToLeaderboardRaceColumnAndFleetMapper(); this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.raceIdentifier = raceIdentifier; this.errorReporter = errorReporter; this.competitorSelectionModel = competitorSelectionModel; @@ -182,7 +185,7 @@ public class EditMarkPassingsPanel extends AbstractCompositeComponent selectedObject = waypointSelectionModel.getSelectedObject(); - sailingService.updateFixedMarkPassing(leaderboardNameRaceColumnNameAndFleetName.getLeaderboardName(), + sailingServiceWrite.updateFixedMarkPassing(leaderboardNameRaceColumnNameAndFleetName.getLeaderboardName(), leaderboardNameRaceColumnNameAndFleetName.getRaceColumnName(), leaderboardNameRaceColumnNameAndFleetName.getFleetName(), selectedObject.getA(), null, competitor, new AsyncCallback() { @@ -226,7 +229,7 @@ public class EditMarkPassingsPanel extends AbstractCompositeComponent() { + // it's okay to require a master response here because replicas don't have their own mark passing calculator + sailingServiceWrite.getTrackedRaceIsUsingMarkPassingCalculator(raceIdentifier, new AsyncCallback() { @Override public void onSuccess(Boolean result) { warningChangesHaveNoEffect.setVisible(!result); @@ -311,7 +315,7 @@ public class EditMarkPassingsPanel extends AbstractCompositeComponent() { @@ -469,7 +473,7 @@ public class EditMarkPassingsPanel extends AbstractCompositeComponent() { @Override public void onFailure(Throwable caught) { - errorReporter.reportError(stringMessages.errorTryingToObtainRaceCourse(caught.getMessage())); + errorReporter.reportError(stringMessages.errorTryingToObtainRaceCourse(caught.getMessage()), /* silent */ true); } @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/EditMarkPositionPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/EditMarkPositionPanel.java index 8bc30e49a73..02ec0143b59 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/EditMarkPositionPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/EditMarkPositionPanel.java @@ -82,6 +82,7 @@ import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.dto.LeaderboardDTO; import com.sap.sailing.domain.common.impl.DegreePosition; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.charts.MarkPositionService.MarkTrackDTO; import com.sap.sailing.gwt.ui.client.shared.racemap.BoundsUtil; @@ -140,10 +141,10 @@ public class EditMarkPositionPanel extends AbstractRaceChart i final SingleRaceLeaderboardPanel leaderboardPanel, RegattaAndRaceIdentifier selectedRaceIdentifier, String leaderboardName, final StringMessages stringMessages, SailingServiceAsync sailingService, Timer timer, TimeRangeWithZoomProvider timeRangeWithZoomProvider, - AsyncActionsExecutor asyncActionsExecutor, ErrorReporter errorReporter) { + AsyncActionsExecutor asyncActionsExecutor, ErrorReporter errorReporter, SailingServiceWriteAsync sailingServiceWrite) { super(parent, context, sailingService, selectedRaceIdentifier, timer, timeRangeWithZoomProvider, stringMessages, asyncActionsExecutor, errorReporter); - this.markPositionService = new MarkPositionServiceForSailingService(sailingService); + this.markPositionService = new MarkPositionServiceForSailingService(sailingServiceWrite); this.raceIdentifierToLeaderboardRaceColumnAndFleetMapper = new RaceIdentifierToLeaderboardRaceColumnAndFleetMapper(); this.raceMap = raceMap; this.leaderboardPanel = leaderboardPanel; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/MarkPositionServiceForSailingService.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/MarkPositionServiceForSailingService.java index 05fe6a96b81..a9348e4554c 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/MarkPositionServiceForSailingService.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/MarkPositionServiceForSailingService.java @@ -2,49 +2,49 @@ package com.sap.sailing.gwt.ui.client.shared.charts; import com.google.gwt.user.client.rpc.AsyncCallback; import com.sap.sailing.domain.common.Position; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.shared.charts.RaceIdentifierToLeaderboardRaceColumnAndFleetMapper.LeaderboardNameRaceColumnNameAndFleetName; import com.sap.sailing.gwt.ui.shared.GPSFixDTO; import com.sap.sailing.gwt.ui.shared.MarkDTO; public class MarkPositionServiceForSailingService implements MarkPositionService { - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; - public MarkPositionServiceForSailingService(SailingServiceAsync sailingService) { + public MarkPositionServiceForSailingService(SailingServiceWriteAsync sailingServiceWrite) { super(); - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; } @Override public void getMarksInTrackedRace(LeaderboardNameRaceColumnNameAndFleetName raceIdentifier, AsyncCallback> callback) { - sailingService.getMarksInTrackedRace(raceIdentifier.getLeaderboardName(), raceIdentifier.getRaceColumnName(), raceIdentifier.getFleetName(), callback); + sailingServiceWrite.getMarksInTrackedRace(raceIdentifier.getLeaderboardName(), raceIdentifier.getRaceColumnName(), raceIdentifier.getFleetName(), callback); } @Override public void getMarkTrack(LeaderboardNameRaceColumnNameAndFleetName raceIdentifier, String markIdAsString, AsyncCallback callback) { - sailingService.getMarkTrack(raceIdentifier.getLeaderboardName(), raceIdentifier.getRaceColumnName(), raceIdentifier.getFleetName(), markIdAsString, callback); + sailingServiceWrite.getMarkTrack(raceIdentifier.getLeaderboardName(), raceIdentifier.getRaceColumnName(), raceIdentifier.getFleetName(), markIdAsString, callback); } @Override public void canRemoveMarkFix(LeaderboardNameRaceColumnNameAndFleetName raceIdentifier, MarkDTO mark, GPSFixDTO fix, AsyncCallback callback) { - sailingService.canRemoveMarkFix(raceIdentifier.getLeaderboardName(), raceIdentifier.getRaceColumnName(), raceIdentifier.getFleetName(), mark.getIdAsString(), fix, callback); + sailingServiceWrite.canRemoveMarkFix(raceIdentifier.getLeaderboardName(), raceIdentifier.getRaceColumnName(), raceIdentifier.getFleetName(), mark.getIdAsString(), fix, callback); } @Override public void removeMarkFix(LeaderboardNameRaceColumnNameAndFleetName raceIdentifier, MarkDTO mark, GPSFixDTO fix, AsyncCallback callback) { - sailingService.removeMarkFix(raceIdentifier.getLeaderboardName(), raceIdentifier.getRaceColumnName(), raceIdentifier.getFleetName(), mark.getIdAsString(), fix, callback); + sailingServiceWrite.removeMarkFix(raceIdentifier.getLeaderboardName(), raceIdentifier.getRaceColumnName(), raceIdentifier.getFleetName(), mark.getIdAsString(), fix, callback); } @Override public void addMarkFix(LeaderboardNameRaceColumnNameAndFleetName raceIdentifier, MarkDTO mark, GPSFixDTO newFix, AsyncCallback callback) { - sailingService.addMarkFix(raceIdentifier.getLeaderboardName(), raceIdentifier.getRaceColumnName(), raceIdentifier.getFleetName(), mark.getIdAsString(), newFix, callback); + sailingServiceWrite.addMarkFix(raceIdentifier.getLeaderboardName(), raceIdentifier.getRaceColumnName(), raceIdentifier.getFleetName(), mark.getIdAsString(), newFix, callback); } @Override public void editMarkFix(LeaderboardNameRaceColumnNameAndFleetName raceIdentifier, MarkDTO mark, GPSFixDTO oldFix, Position newPosition, AsyncCallback callback) { - sailingService.editMarkFix(raceIdentifier.getLeaderboardName(), raceIdentifier.getRaceColumnName(), raceIdentifier.getFleetName(), mark.getIdAsString(), oldFix, newPosition, callback); + sailingServiceWrite.editMarkFix(raceIdentifier.getLeaderboardName(), raceIdentifier.getRaceColumnName(), raceIdentifier.getFleetName(), mark.getIdAsString(), oldFix, newPosition, callback); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/controls/MultipleLinkCell.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/controls/MultipleLinkCell.java index 3cb335254a7..566a8df0e16 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/controls/MultipleLinkCell.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/controls/MultipleLinkCell.java @@ -112,7 +112,6 @@ public class MultipleLinkCell extends AbstractCell value, NativeEvent event, ValueUpdater> valueUpdater) { super.onBrowserEvent(context, parent, value, event, valueUpdater); - if (isBlockLinkEvent) { event.preventDefault(); EventTarget eventTarget = event.getEventTarget(); @@ -128,20 +127,18 @@ public class MultipleLinkCell extends AbstractCell links, SafeHtmlBuilder sb) { - if (links.isEmpty()) { - return; - } - SafeHtml rendered; - boolean isFirst = true; - for (CellLink link : links) { - if (isFirst) { - isFirst = false; - } else { - sb.appendHtmlConstant("
    "); + if (!links.isEmpty()) { + SafeHtml rendered; + boolean isFirst = true; + for (CellLink link : links) { + if (isFirst) { + isFirst = false; + } else { + sb.appendHtmlConstant("
    "); + } + rendered = linkTemplates.cell(link.getTarget(), UriUtils.fromString(link.getHref()), link.getText()); + sb.append(rendered); } - rendered = linkTemplates.cell(link.getTarget(), UriUtils.fromString(link.getHref()), link.getText()); - sb.append(rendered); } } - } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/DataMiningEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/DataMiningEntryPoint.java index 2bb402aadbd..bd495d9eb61 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/DataMiningEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/datamining/DataMiningEntryPoint.java @@ -23,7 +23,7 @@ import com.google.gwt.user.client.ui.SplitLayoutPanel; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.authentication.FixedSailingAuthentication; import com.sap.sailing.gwt.common.authentication.SAPSailingHeaderWithAuthentication; -import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint; +import com.sap.sailing.gwt.ui.client.AbstractSailingReadEntryPoint; import com.sap.sailing.gwt.ui.client.RemoteServiceMappingConstants; import com.sap.sailing.gwt.ui.datamining.presentation.TabbedSailingResultsPresenter; import com.sap.sailing.gwt.ui.shared.settings.SailingSettingsConstants; @@ -51,7 +51,7 @@ import com.sap.sse.security.ui.authentication.generic.GenericAuthentication; import com.sap.sse.security.ui.authentication.generic.GenericAuthorizedContentDecorator; import com.sap.sse.security.ui.authentication.generic.sapheader.SAPHeaderWithAuthentication; -public class DataMiningEntryPoint extends AbstractSailingEntryPoint { +public class DataMiningEntryPoint extends AbstractSailingReadEntryPoint { public static final ComponentResources resources = GWT.create(ComponentResources.class); private static final Logger LOG = Logger.getLogger(DataMiningEntryPoint.class.getName()); @@ -80,7 +80,7 @@ public class DataMiningEntryPoint extends AbstractSailingEntryPoint { } private void createDataminingPanel(ServerInfoDTO serverInfo, final String queryIdentifier) { - removeUrlParameter(); + removeUrlParameter();; SAPHeaderWithAuthentication header = new SAPSailingHeaderWithAuthentication(getStringMessages().dataMining()); GenericAuthentication genericSailingAuthentication = new FixedSailingAuthentication(getUserService(), header.getAuthenticationMenuView()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java index 9133d11f089..924d3fcccd6 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java @@ -26,7 +26,7 @@ import com.sap.sailing.gwt.settings.client.leaderboard.MetaLeaderboardPerspectiv import com.sap.sailing.gwt.settings.client.leaderboard.MultiCompetitorLeaderboardChartLifecycle; import com.sap.sailing.gwt.settings.client.leaderboard.MultiCompetitorLeaderboardChartSettings; import com.sap.sailing.gwt.settings.client.utils.StoredSettingsLocationFactory; -import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint; +import com.sap.sailing.gwt.ui.client.AbstractSailingReadEntryPoint; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.SailingServiceHelper; import com.sap.sailing.gwt.ui.client.StringMessages; @@ -44,7 +44,7 @@ import com.sap.sse.gwt.settings.SettingsToUrlSerializer; import com.sap.sse.security.ui.settings.ComponentContextWithSettingsStorage; import com.sap.sse.security.ui.settings.StoredSettingsLocation; -public class LeaderboardEntryPoint extends AbstractSailingEntryPoint implements ProvidesLeaderboardRouting { +public class LeaderboardEntryPoint extends AbstractSailingReadEntryPoint implements ProvidesLeaderboardRouting { public static final long DEFAULT_REFRESH_INTERVAL_MILLIS = 3000l; private static final Logger logger = Logger.getLogger(LeaderboardEntryPoint.class.getName()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/MultiRaceLeaderboardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/MultiRaceLeaderboardPanel.java index ec4b344bbd0..66fcc039400 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/MultiRaceLeaderboardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/MultiRaceLeaderboardPanel.java @@ -254,7 +254,10 @@ public class MultiRaceLeaderboardPanel extends LeaderboardPanel getRetrieverAction() { final Date date = getLeaderboardDisplayDate(); - return new GetLeaderboardByNameAction(getSailingService(), getLeaderboardName(), + // need to call super here otherwise it might take the instantiated types method implementation, + // but fields there might not be initialized if we are within a constructor call. + SailingServiceAsync sailingService = super.getSailingService(); + return new GetLeaderboardByNameAction(sailingService, getLeaderboardName(), useNullAsTimePoint() ? null : date, /* namesOfRaceColumnsForWhichToLoadLegDetails */getNamesOfExpandedRaceColumns(), shallAddOverallDetails(), /* previousLeaderboard */ diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/EditableLeaderboardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/EditableLeaderboardPanel.java index 64e950547bd..0f3c9b0938c 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/EditableLeaderboardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/EditableLeaderboardPanel.java @@ -54,7 +54,7 @@ import com.sap.sailing.gwt.ui.client.Collator; import com.sap.sailing.gwt.ui.client.CompetitorSelectionModel; import com.sap.sailing.gwt.ui.client.FlagImageRenderer; import com.sap.sailing.gwt.ui.client.FlagImageResolverImpl; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.leaderboard.ClassicLeaderboardStyle; import com.sap.sailing.gwt.ui.leaderboard.CompetitorColumnBase; @@ -93,6 +93,8 @@ public class EditableLeaderboardPanel extends MultiRaceLeaderboardPanel { private CheckBox showUncorrectedTotalPointsCheckbox; + private final SailingServiceWriteAsync sailingServiceWrite; + private class SettingsClickHandler implements ClickHandler { private final StringMessages stringMessages; @@ -587,13 +589,14 @@ public class EditableLeaderboardPanel extends MultiRaceLeaderboardPanel { } } - public EditableLeaderboardPanel(final SailingServiceAsync sailingService, AsyncActionsExecutor asyncActionsExecutor, + public EditableLeaderboardPanel(final SailingServiceWriteAsync sailingServiceWrite, AsyncActionsExecutor asyncActionsExecutor, String leaderboardName, String leaderboardGroupName, final ErrorReporter errorReporter, final StringMessages stringMessages, UserAgentDetails userAgent, Iterable availableDetailTypes) { - super(null, null, sailingService, asyncActionsExecutor, new MultiRaceLeaderboardSettings(), + super(null, null, sailingServiceWrite, asyncActionsExecutor, new MultiRaceLeaderboardSettings(), new CompetitorSelectionModel(/* hasMultiSelection */true), leaderboardName, errorReporter, stringMessages, /* showRaceDetails */ true, new ClassicLeaderboardStyle(), FlagImageResolverImpl.get(), availableDetailTypes); + this.sailingServiceWrite = sailingServiceWrite; suppressedCompetitorsShown = new ListDataProvider<>(new ArrayList<>()); suppressedCompetitorsTable = createSuppressedCompetitorsTable(); ImageResource importIcon = resources.importIcon(); @@ -603,7 +606,7 @@ public class EditableLeaderboardPanel extends MultiRaceLeaderboardPanel { importAnchor.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - sailingService.getScoreCorrectionProviderNames(new AsyncCallback>() { + sailingServiceWrite.getScoreCorrectionProviderNames(new AsyncCallback>() { @Override public void onSuccess(Iterable providerNames) { ResultSelectionAndApplyDialog dialog = new ResultSelectionAndApplyDialog(EditableLeaderboardPanel.this, providerNames, getSailingService(), @@ -640,7 +643,7 @@ public class EditableLeaderboardPanel extends MultiRaceLeaderboardPanel { final String lastScoreCorrectionComment = lastScoreCorrectionCommentBox.getText(); final Date lastScoreCorrectionTime = lastScoreCorrectionTimeBox.getValue(); - sailingService.updateLeaderboardScoreCorrectionMetadata(getLeaderboardName(), lastScoreCorrectionTime, lastScoreCorrectionComment, new AsyncCallback() { + sailingServiceWrite.updateLeaderboardScoreCorrectionMetadata(getLeaderboardName(), lastScoreCorrectionTime, lastScoreCorrectionComment, new AsyncCallback() { @Override public void onSuccess(Void noarg) { updateScoreCorrectionInformation(lastScoreCorrectionComment, lastScoreCorrectionTime); @@ -1042,4 +1045,8 @@ public class EditableLeaderboardPanel extends MultiRaceLeaderboardPanel { protected void blurFocusedElementAfterSelectionChange() { } + public SailingServiceWriteAsync getSailingService() { + return sailingServiceWrite; + } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/LeaderboardEditPage.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/LeaderboardEditPage.java index 88eaca1794a..97357e3fe61 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/LeaderboardEditPage.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/LeaderboardEditPage.java @@ -17,7 +17,7 @@ import com.sap.sailing.gwt.common.authentication.FixedSailingAuthentication; import com.sap.sailing.gwt.common.authentication.SAPSailingHeaderWithAuthentication; import com.sap.sailing.gwt.common.communication.routing.ProvidesLeaderboardRouting; import com.sap.sailing.gwt.settings.client.leaderboardedit.LeaderboardEditContextDefinition; -import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint; +import com.sap.sailing.gwt.ui.client.AbstractSailingWriteEntryPoint; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardEntryPoint; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTOWithSecurity; import com.sap.sse.gwt.client.async.AsyncActionsExecutor; @@ -30,7 +30,7 @@ import com.sap.sse.security.ui.authentication.generic.GenericAuthentication; import com.sap.sse.security.ui.authentication.generic.GenericAuthorizedContentDecorator; import com.sap.sse.security.ui.authentication.generic.sapheader.SAPHeaderWithAuthentication; -public class LeaderboardEditPage extends AbstractSailingEntryPoint implements ProvidesLeaderboardRouting { +public class LeaderboardEditPage extends AbstractSailingWriteEntryPoint implements ProvidesLeaderboardRouting { private static final Logger logger = Logger.getLogger(LeaderboardEntryPoint.class.getName()); private String leaderboardName; @@ -120,4 +120,5 @@ public class LeaderboardEditPage extends AbstractSailingEntryPoint implements Pr public String getLeaderboardName() { return leaderboardName; } + } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/MatchAndApplyScoreCorrectionsDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/MatchAndApplyScoreCorrectionsDialog.java index 90eb1c0886a..9ebc1d8f0be 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/MatchAndApplyScoreCorrectionsDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/MatchAndApplyScoreCorrectionsDialog.java @@ -28,7 +28,7 @@ import com.sap.sailing.domain.common.dto.LeaderboardEntryDTO; import com.sap.sailing.domain.common.dto.LeaderboardRowDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTO; import com.sap.sailing.gwt.ui.client.SailNumberCanonicalizerAndMatcher; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.BulkScoreCorrectionDTO; import com.sap.sailing.gwt.ui.shared.RegattaScoreCorrectionDTO; @@ -54,10 +54,10 @@ public class MatchAndApplyScoreCorrectionsDialog extends DataEntryDialog(); @@ -338,15 +338,15 @@ public class MatchAndApplyScoreCorrectionsDialog extends DataEntryDialog { - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final StringMessages stringMessages; private final ErrorReporter errorReporter; private final EditableLeaderboardPanel leaderboardPanel; - public Callback(EditableLeaderboardPanel leaderboardPanel, SailingServiceAsync sailingService, StringMessages stringMessages, ErrorReporter errorReporter) { + public Callback(EditableLeaderboardPanel leaderboardPanel, SailingServiceWriteAsync sailingServiceWrite, StringMessages stringMessages, ErrorReporter errorReporter) { super(); this.leaderboardPanel = leaderboardPanel; - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.stringMessages = stringMessages; this.errorReporter = errorReporter; } @@ -359,7 +359,7 @@ public class MatchAndApplyScoreCorrectionsDialog extends DataEntryDialog() { + sailingServiceWrite.updateLeaderboardScoreCorrectionsAndMaxPointsReasons(result, new AsyncCallback() { @Override public void onFailure(Throwable caught) { leaderboardPanel.removeBusyTask(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/ResultSelectionAndApplyDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/ResultSelectionAndApplyDialog.java index 16cb9695052..9aaba249c19 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/ResultSelectionAndApplyDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboardedit/ResultSelectionAndApplyDialog.java @@ -19,6 +19,7 @@ import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.dto.BoatClassDTO; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.RegattaScoreCorrectionDTO; import com.sap.sailing.gwt.ui.shared.ScoreCorrectionProviderDTO; @@ -44,10 +45,10 @@ public class ResultSelectionAndApplyDialog extends DataEntryDialog scoreCorrectionProviderNames, - SailingServiceAsync sailingService, StringMessages stringMessages, ErrorReporter errorReporter) { + SailingServiceWriteAsync sailingServiceWrite, StringMessages stringMessages, ErrorReporter errorReporter) { super(stringMessages.importOfficialResults(), null, stringMessages.ok(), stringMessages.cancel(), new Validator(stringMessages), - new Callback(sailingService, leaderboardPanel, errorReporter, stringMessages)); - this.sailingService = sailingService; + new Callback(sailingServiceWrite, leaderboardPanel, errorReporter, stringMessages)); + this.sailingService = sailingServiceWrite; this.stringMessages = stringMessages; this.errorReporter = errorReporter; boatClass = leaderboardPanel.getLeaderboard().getBoatClass(); @@ -194,13 +195,13 @@ public class ResultSelectionAndApplyDialog extends DataEntryDialog>> { private final EditableLeaderboardPanel leaderboardPanel; - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final StringMessages stringMessages; private final ErrorReporter errorReporter; - public Callback(SailingServiceAsync sailingService, EditableLeaderboardPanel leaderboardPanel, ErrorReporter errorReporter, + public Callback(SailingServiceWriteAsync sailingServiceWrite, EditableLeaderboardPanel leaderboardPanel, ErrorReporter errorReporter, StringMessages stringMessages) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.leaderboardPanel = leaderboardPanel; this.stringMessages = stringMessages; this.errorReporter = errorReporter; @@ -218,7 +219,7 @@ public class ResultSelectionAndApplyDialog extends DataEntryDialog() { @Override public void onFailure(Throwable caught) { @@ -230,8 +231,8 @@ public class ResultSelectionAndApplyDialog extends DataEntryDialog leaderboardsRefresher, LeaderboardGroupsRefresher leaderboardGroupsRefresher, MediaTracksRefresher mediaTracksRefresher) { - this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.stringMessages = stringMessages; this.regattaRefresher = regattaRefresher; this.eventRefresher = eventsRefresher; this.leaderboardsRefresher = leaderboardsRefresher; this.leaderboardGroupsRefresher = leaderboardGroupsRefresher; this.mediaTracksRefresher = mediaTracksRefresher; - HorizontalPanel serverAddressPanel = new HorizontalPanel(); serverAddressPanel.add(new Label(stringMessages.importRemoteHost())); hostBox = new TextBox(); @@ -106,35 +105,27 @@ public class MasterDataImportPanel extends VerticalPanel { fetchIdsButton.ensureDebugId("fetchLeaderboardGroupList"); DialogUtils.linkEnterToButton(fetchIdsButton, usernameBox); DialogUtils.linkEnterToButton(fetchIdsButton, passwordBox); - this.add(serverAddressPanel); this.add(userContextInformation); this.add(usernamePanel); this.add(passwordPanel); this.add(fetchIdsButton); - ScrollPanel scrollPanel = new ScrollPanel(); this.add(scrollPanel); - VerticalPanel contentPanel = new VerticalPanel(); scrollPanel.setWidget(contentPanel); - addContentToLeftPanel(contentPanel); - setListeners(); } private void setListeners() { fetchIdsButton.addClickHandler(new ClickHandler() { - @Override public void onClick(ClickEvent event) { fireIdRequestsAndFillLists(); } }); - hostBox.addKeyDownHandler(new KeyDownHandler() { - @Override public void onKeyDown(KeyDownEvent event) { if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { @@ -142,9 +133,7 @@ public class MasterDataImportPanel extends VerticalPanel { } } }); - importLeaderboardGroupsButton.addClickHandler(new ClickHandler() { - @Override public void onClick(ClickEvent event) { importLeaderboardGroups(); @@ -170,9 +159,8 @@ public class MasterDataImportPanel extends VerticalPanel { boolean exportWind = exportWindSwitch.getValue(); boolean exportDeviceConfigs = exportDeviceConfigsSwitch.getValue(); boolean exportTrackedRacesAndStartTracking = exportTrackedRacesAndStartTrackingSwitch.getValue(); - sailingService.importMasterData(currentHost, groupNames, override, compress, exportWind, + sailingServiceWrite.importMasterData(currentHost, groupNames, override, compress, exportWind, exportDeviceConfigs, usernameBox.getValue(), passwordBox.getValue(), exportTrackedRacesAndStartTracking, new AsyncCallback() { - @Override public void onFailure(Throwable caught) { showErrorAlert(caught.getLocalizedMessage()); @@ -181,12 +169,10 @@ public class MasterDataImportPanel extends VerticalPanel { @Override public void onSuccess(final UUID resultId) { final Timer timer = new Timer() { - @Override public void run() { - sailingService.getImportOperationProgress(resultId, + sailingServiceWrite.getImportOperationProgress(resultId, new AsyncCallback() { - @Override public void onFailure(Throwable caught) { showErrorAlert(stringMessages.importServerError()); @@ -325,10 +311,8 @@ public class MasterDataImportPanel extends VerticalPanel { private void fireLgIdRequestAndFillList(final String host) { currentHost = host; disableAllButtons(); - // FIXME what about login here? - sailingService.getLeaderboardGroupNamesFromRemoteServer(host, usernameBox.getValue(), passwordBox.getValue(), + sailingServiceWrite.getLeaderboardGroupNamesFromRemoteServer(host, usernameBox.getValue(), passwordBox.getValue(), new AsyncCallback>() { - @Override public void onFailure(Throwable caught) { showErrorAlert(stringMessages.importGetLeaderboardsFailed(host, caught.getMessage())); @@ -349,7 +333,6 @@ public class MasterDataImportPanel extends VerticalPanel { filterLeaderboardGroupList(); } } - }); } @@ -359,47 +342,38 @@ public class MasterDataImportPanel extends VerticalPanel { private void addContentToLeftPanel(VerticalPanel contentPanel) { contentPanel.add(new Label(stringMessages.availableLeaderboardGroups())); - HorizontalPanel filterPanel = new HorizontalPanel(); filterPanel.add(new Label(stringMessages.filterName() + ":")); filterBox = new TextBox(); setFilterHandler(filterBox); filterPanel.add(filterBox); contentPanel.add(filterPanel); - leaderboardgroupListBox = new ListBox(); leaderboardgroupListBox.ensureDebugId("LeaderBoardGroupListBox"); leaderboardgroupListBox.setMultipleSelect(true); - addSelectionChangedListener(); contentPanel.add(leaderboardgroupListBox); - overrideSwitch = new CheckBox(stringMessages.importOverrideSwitchLabel()); overrideSwitch.ensureDebugId("overrideExisting"); overrideSwitch.setValue(false); contentPanel.add(overrideSwitch); - compressSwitch = new CheckBox(stringMessages.compress()); compressSwitch.setTitle(stringMessages.compressTooltip()); compressSwitch.setValue(true); contentPanel.add(compressSwitch); - exportWindSwitch = new CheckBox(stringMessages.importWind()); exportWindSwitch.setTitle(stringMessages.importWindTooltip()); exportWindSwitch.setValue(true); exportWindSwitch.ensureDebugId("wind"); contentPanel.add(exportWindSwitch); - exportDeviceConfigsSwitch = new CheckBox(stringMessages.importDeviceConfigurations()); exportDeviceConfigsSwitch.setTitle(stringMessages.importDeviceConfigurationsTooltip()); exportDeviceConfigsSwitch.setValue(false); contentPanel.add(exportDeviceConfigsSwitch); - exportTrackedRacesAndStartTrackingSwitch = new CheckBox(stringMessages.exportTrackedRacesAndStartTracking()); exportTrackedRacesAndStartTrackingSwitch.setTitle(stringMessages.exportTrackedRacesAndStartTrackingTooltip()); exportTrackedRacesAndStartTrackingSwitch.setValue(false); contentPanel.add(exportTrackedRacesAndStartTrackingSwitch); - importLeaderboardGroupsButton = new Button(stringMessages.importSelectedLeaderboardGroups()); importLeaderboardGroupsButton.ensureDebugId("import"); importLeaderboardGroupsButton.setEnabled(false); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/pairinglist/PairingListEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/pairinglist/PairingListEntryPoint.java index 5f4d4739f3c..618935b6361 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/pairinglist/PairingListEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/pairinglist/PairingListEntryPoint.java @@ -20,13 +20,13 @@ import com.sap.sailing.gwt.common.authentication.FixedSailingAuthentication; import com.sap.sailing.gwt.common.authentication.SAPSailingHeaderWithAuthentication; import com.sap.sailing.gwt.common.communication.routing.ProvidesLeaderboardRouting; import com.sap.sailing.gwt.ui.adminconsole.PairingListPreviewDialog; -import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint; +import com.sap.sailing.gwt.ui.client.AbstractSailingReadEntryPoint; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTO; import com.sap.sse.common.Color; import com.sap.sse.gwt.settings.SettingsToUrlSerializer; -public class PairingListEntryPoint extends AbstractSailingEntryPoint implements ProvidesLeaderboardRouting { +public class PairingListEntryPoint extends AbstractSailingReadEntryPoint implements ProvidesLeaderboardRouting { private PairingListContextDefinition pairingListContextDefinition; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/EmbeddedMapAndWindChartEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/EmbeddedMapAndWindChartEntryPoint.java index 063e5243b12..cec749f5812 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/EmbeddedMapAndWindChartEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/EmbeddedMapAndWindChartEntryPoint.java @@ -27,7 +27,7 @@ import com.sap.sailing.gwt.common.authentication.FixedSailingAuthentication; import com.sap.sailing.gwt.common.authentication.SAPSailingHeaderWithAuthentication; import com.sap.sailing.gwt.common.communication.routing.ProvidesLeaderboardRouting; import com.sap.sailing.gwt.settings.client.raceboard.RaceBoardPerspectiveOwnSettings; -import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint; +import com.sap.sailing.gwt.ui.client.AbstractSailingReadEntryPoint; import com.sap.sailing.gwt.ui.client.CompetitorColorProvider; import com.sap.sailing.gwt.ui.client.CompetitorColorProviderImpl; import com.sap.sailing.gwt.ui.client.RaceCompetitorSelectionModel; @@ -63,7 +63,7 @@ import com.sap.sse.gwt.client.player.Timer.PlayModes; import com.sap.sse.gwt.shared.GwtHttpRequestUtils; import com.sap.sse.security.ui.authentication.generic.sapheader.SAPHeaderWithAuthentication; -public class EmbeddedMapAndWindChartEntryPoint extends AbstractSailingEntryPoint implements ProvidesLeaderboardRouting { +public class EmbeddedMapAndWindChartEntryPoint extends AbstractSailingReadEntryPoint implements ProvidesLeaderboardRouting { private static final String PARAM_REGATTA_LIKE_NAME = "regattaLikeName"; private static final String PARAM_RACE_COLUMN_NAME = "raceColumnName"; private static final String PARAM_FLEET_NAME = "fleetName"; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java index fbf334253d8..358f7fbaeae 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardEntryPoint.java @@ -1,6 +1,8 @@ package com.sap.sailing.gwt.ui.raceboard; +import static com.sap.sailing.gwt.ui.client.SailingServiceHelper.createSailingServiceWriteInstance; + import java.util.Collections; import com.google.gwt.core.client.GWT; @@ -19,7 +21,7 @@ import com.sap.sailing.gwt.common.communication.routing.ProvidesLeaderboardRouti import com.sap.sailing.gwt.settings.client.raceboard.RaceBoardPerspectiveOwnSettings; import com.sap.sailing.gwt.settings.client.raceboard.RaceboardContextDefinition; import com.sap.sailing.gwt.settings.client.utils.StoredSettingsLocationFactory; -import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint; +import com.sap.sailing.gwt.ui.client.AbstractSailingReadEntryPoint; import com.sap.sailing.gwt.ui.client.CompetitorSelectionChangeListener; import com.sap.sailing.gwt.ui.client.MediaService; import com.sap.sailing.gwt.ui.client.MediaServiceAsync; @@ -40,7 +42,7 @@ import com.sap.sse.security.ui.authentication.generic.sapheader.SAPHeaderWithAut import com.sap.sse.security.ui.settings.ComponentContextWithSettingsStorage; import com.sap.sse.security.ui.settings.StoredSettingsLocation; -public class RaceBoardEntryPoint extends AbstractSailingEntryPoint implements ProvidesLeaderboardRouting { +public class RaceBoardEntryPoint extends AbstractSailingReadEntryPoint implements ProvidesLeaderboardRouting { /** * Controls the predefined mode into which to switch or configure the race viewer. @@ -154,7 +156,7 @@ public class RaceBoardEntryPoint extends AbstractSailingEntryPoint implements Pr raceboardContextDefinition.getLeaderboardName(), raceboardContextDefinition.getLeaderboardGroupName(), raceboardContextDefinition.getEventId(), RaceBoardEntryPoint.this, getStringMessages(), userAgent, raceTimesInfoProvider, showChartMarkEditMediaButtonsAndVideo, true, availableDetailTypes, - raceboardData.getLeaderboard(), selectedRace, raceboardData.getTrackingConnectorInfo()); + raceboardData.getLeaderboard(), selectedRace, raceboardData.getTrackingConnectorInfo(), createSailingServiceWriteInstance() /* create write instance for later admin usage*/); RootLayoutPanel.get().add(raceBoardPerspective.getEntryWidget()); if (raceBoardMode != null) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java index 9c9284d8739..e839b016726 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/RaceBoardPanel.java @@ -62,6 +62,7 @@ import com.sap.sailing.gwt.ui.client.RaceTimePanelLifecycle; import com.sap.sailing.gwt.ui.client.RaceTimePanelSettings; import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.media.MediaPlayerLifecycle; import com.sap.sailing.gwt.ui.client.media.MediaPlayerManager.PlayerChangeListener; @@ -136,6 +137,7 @@ public class RaceBoardPanel extends AbstractPerspectiveComposite implements LeaderboardUpdateListener, PopupPositionProvider, RequiresResize { private final SailingServiceAsync sailingService; + private SailingServiceWriteAsync sailingServiceWrite; private final MediaServiceAsync mediaService; private final UUID eventId; private final StringMessages stringMessages; @@ -186,7 +188,7 @@ public class RaceBoardPanel private static final RaceMapResources raceMapResources = GWT.create(RaceMapResources.class); private TrackingConnectorInfoDTO trackingConnectorInfo; - + /** * @param eventId * an optional event that can be used for "back"-navigation in case the race board shows a race in the @@ -216,9 +218,10 @@ public class RaceBoardPanel UserAgentDetails userAgent, RaceTimesInfoProvider raceTimesInfoProvider, boolean showChartMarkEditMediaButtonsAndVideo, boolean showHeaderPanel, Iterable availableDetailTypes, StrippedLeaderboardDTOWithSecurity leaderboardDTO, - final RaceWithCompetitorsAndBoatsDTO raceDTO, TrackingConnectorInfoDTO trackingConnectorInfo) { + final RaceWithCompetitorsAndBoatsDTO raceDTO, TrackingConnectorInfoDTO trackingConnectorInfo, SailingServiceWriteAsync sailingServiceWrite) { super(parent, componentContext, lifecycle, settings); this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.mediaService = mediaService; this.stringMessages = stringMessages; this.raceTimesInfoProvider = raceTimesInfoProvider; @@ -331,7 +334,7 @@ public class RaceBoardPanel } } taggingPanel = new TaggingPanel(parent, componentContext, stringMessages, sailingService, userService, timer, - raceTimesInfoProvider, sharedTagTimePoint, sharedTagTitle, leaderboardDTO); + raceTimesInfoProvider, sharedTagTimePoint, sharedTagTitle, leaderboardDTO, sailingServiceWrite); addChildComponent(taggingPanel); taggingPanel.setVisible(showTaggingPanel); // Determine if the screen is large enough to initially display the leaderboard panel on the left side of the @@ -417,8 +420,8 @@ public class RaceBoardPanel errorReporter, true, true, leaderboardGroupName, leaderboardName); competitorChart.setVisible(false); competitorChart.updateSettings(multiCompetitorRaceChartSettings); - new SliceRaceHandler(sailingService, userService, errorReporter, competitorChart, selectedRaceIdentifier, - leaderboardGroupName, leaderboardName, event, leaderboard, raceDTO); + new SliceRaceHandler(sailingServiceWrite, userService, errorReporter, competitorChart, selectedRaceIdentifier, + leaderboardGroupName, leaderboardName, event, leaderboard, raceDTO, stringMessages); componentsForSideBySideViewer.add(competitorChart); windChart = new WindChart(this, getComponentContext(), windChartLifecycle, sailingService, selectedRaceIdentifier, timer, @@ -427,7 +430,6 @@ public class RaceBoardPanel true); windChart.setVisible(false); componentsForSideBySideViewer.add(windChart); - } maneuverTablePanel = new ManeuverTablePanel(this, getComponentContext(), sailingService, asyncActionsExecutor, selectedRaceIdentifier, stringMessages, competitorSelectionProvider, errorReporter, timer, @@ -437,9 +439,9 @@ public class RaceBoardPanel componentsForSideBySideViewer.add(maneuverTablePanel); } editMarkPassingPanel = new EditMarkPassingsPanel(this, getComponentContext(), sailingService, + sailingServiceWrite, selectedRaceIdentifier, - stringMessages, - competitorSelectionProvider, errorReporter, timer); + stringMessages, competitorSelectionProvider, errorReporter, timer); if (showChartMarkEditMediaButtonsAndVideo) { editMarkPassingPanel.setLeaderboard(leaderboardPanel.getLeaderboard()); editMarkPassingPanel.getEntryWidget().setTitle(stringMessages.editMarkPassings()); @@ -448,15 +450,14 @@ public class RaceBoardPanel editMarkPositionPanel = new EditMarkPositionPanel(this, getComponentContext(), raceMap, leaderboardPanel, selectedRaceIdentifier, leaderboardName, stringMessages, sailingService, timer, timeRangeWithZoomModel, - asyncActionsExecutor, errorReporter); + asyncActionsExecutor, errorReporter, sailingServiceWrite); if (showChartMarkEditMediaButtonsAndVideo) { editMarkPositionPanel.setLeaderboard(leaderboardPanel.getLeaderboard()); componentsForSideBySideViewer.add(editMarkPositionPanel); } mediaPlayerManagerComponent = new MediaPlayerManagerComponent(this, getComponentContext(), mediaPlayerLifecycle, - sailingService, selectedRaceIdentifier, raceTimesInfoProvider, timer, mediaService, userService, + sailingServiceWrite, selectedRaceIdentifier, raceTimesInfoProvider, timer, mediaService, userService, stringMessages, errorReporter, userAgent, this, mediaPlayerSettings, raceDTO); - final LeaderboardWithSecurityFetcher asyncFetcher = new LeaderboardWithSecurityFetcher() { @Override public void getLeaderboardWithSecurity(Consumer consumer) { @@ -478,15 +479,12 @@ public class RaceBoardPanel mapViewer = new SideBySideComponentViewer(leaderboardPanel, raceMap, taggingPanel, mediaPlayerManagerComponent, componentsForSideBySideViewer, stringMessages, userService, editMarkPassingPanel, editMarkPositionPanel, maneuverTablePanel, asyncFetcher); - mediaPlayerManagerComponent.addPlayerChangeListener(new PlayerChangeListener() { - @Override public void notifyStateChange() { updateRaceTimePanelOverlay(); } }); - for (Component component : componentsForSideBySideViewer) { addChildComponent(component); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/SliceRaceHandler.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/SliceRaceHandler.java index 4d5daa105a3..9173e14b3fb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/SliceRaceHandler.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/SliceRaceHandler.java @@ -13,7 +13,7 @@ import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; -import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.charts.ChartZoomChangedEvent; import com.sap.sailing.gwt.ui.client.shared.charts.MultiCompetitorRaceChart; @@ -25,6 +25,8 @@ import com.sap.sse.common.TimeRange; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.common.impl.TimeRangeImpl; import com.sap.sse.gwt.client.ErrorReporter; +import com.sap.sse.gwt.client.Notification; +import com.sap.sse.gwt.client.Notification.NotificationType; import com.sap.sse.gwt.client.dialog.DataEntryDialog; import com.sap.sse.security.shared.HasPermissions.DefaultActions; import com.sap.sse.security.ui.client.UserService; @@ -59,7 +61,7 @@ public class SliceRaceHandler { private final UUID eventId; - private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final UserService userService; @@ -76,11 +78,11 @@ public class SliceRaceHandler { /** * Registers this handler as a zoom event handler on the {@code competitorRaceChart}. */ - public SliceRaceHandler(SailingServiceAsync sailingService, UserService userService, final ErrorReporter errorReporter, + public SliceRaceHandler(SailingServiceWriteAsync sailingServiceWrite, UserService userService, final ErrorReporter errorReporter, MultiCompetitorRaceChart competitorRaceChart, RegattaAndRaceIdentifier selectedRaceIdentifier, final String leaderboardGroupName, String leaderboardName, UUID eventId, - StrippedLeaderboardDTOWithSecurity leaderboardDTO, RaceWithCompetitorsAndBoatsDTO raceDTO) { - this.sailingService = sailingService; + StrippedLeaderboardDTOWithSecurity leaderboardDTO, RaceWithCompetitorsAndBoatsDTO raceDTO, StringMessages stringMessages) { + this.sailingServiceWrite = sailingServiceWrite; this.userService = userService; this.errorReporter = errorReporter; this.selectedRaceIdentifier = selectedRaceIdentifier; @@ -92,7 +94,7 @@ public class SliceRaceHandler { styles.ensureInjected(); sliceButtonUi = new Button(); sliceButtonUi.setStyleName(styles.sliceButtonBackgroundImage()); - sliceButtonUi.setTitle(StringMessages.INSTANCE.sliceRace()); + sliceButtonUi.setTitle(stringMessages.sliceRace()); competitorRaceChart.addToolbarButton(sliceButtonUi); sliceButtonUi.setVisible(false); competitorRaceChart.addChartZoomChangedHandler(this::checkIfMaySliceSelectedRegattaAndRace); @@ -100,21 +102,16 @@ public class SliceRaceHandler { visibleRange = null; updateVisibility(); }); - sliceButtonUi.addClickHandler((e) -> doSlice()); - sailingService.canSliceRace(selectedRaceIdentifier, new AsyncCallback() { - @Override - public void onSuccess(Boolean result) { - canSlice = Boolean.TRUE.equals(result); - updateVisibility(); - } - - @Override - public void onFailure(Throwable caught) { - canSlice = false; - updateVisibility(); + sliceButtonUi.addClickHandler((e) -> { + if (allowsEditing()) { + doSlice(); + }else { + Notification.notify(stringMessages.insufficientPermissions(), NotificationType.ERROR); } }); + updateCanSliceIfAuthorized(); final UserStatusEventHandler userStatusEventHandler = (user, preAuthenticated) -> { + updateCanSliceIfAuthorized(); updateVisibility(); }; sliceButtonUi.addAttachHandler(e -> { @@ -125,6 +122,24 @@ public class SliceRaceHandler { } }); } + + private void updateCanSliceIfAuthorized() { + if (allowsEditing()) { + sailingServiceWrite.canSliceRace(selectedRaceIdentifier, new AsyncCallback() { + @Override + public void onSuccess(Boolean result) { + canSlice = Boolean.TRUE.equals(result); + updateVisibility(); + } + + @Override + public void onFailure(Throwable caught) { + canSlice = false; + updateVisibility(); + } + }); + } + } private void updateVisibility() { sliceButtonUi.setVisible(canSlice && visibleRange != null && allowsEditing()); @@ -137,7 +152,7 @@ public class SliceRaceHandler { private void doSlice() { if (visibleRange != null) { - sailingService.prepareForSlicingOfRace(selectedRaceIdentifier, + sailingServiceWrite.prepareForSlicingOfRace(selectedRaceIdentifier, new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -147,7 +162,7 @@ public class SliceRaceHandler { @Override public void onSuccess(SliceRacePreperationDTO sliceRacePreperatioData) { new SlicedRaceNameDialog(sliceRacePreperatioData, slicedRaceName -> { - sailingService.sliceRace(selectedRaceIdentifier, slicedRaceName, visibleRange.from(), + sailingServiceWrite.sliceRace(selectedRaceIdentifier, slicedRaceName, visibleRange.from(), visibleRange.to(), new AsyncCallback() { @Override diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagButtonDialog.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagButtonDialog.java index 3437fa2e7c7..d60bfe3f84f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagButtonDialog.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TagButtonDialog.java @@ -108,7 +108,7 @@ public class TagButtonDialog extends DialogBox { * {@link TaggingPanel} which creates this {@link TagButtonDialog}. * @param footerPanel * footer panel of {@link TaggingPanel} - * @param sailingService + * @param sailingServiceWrite * Sailing Service of {@link TaggingPanel} * @param stringMessages * string messages of {@link TaggingPanel} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TaggingPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TaggingPanel.java index 975681a438c..ea84eacf3bb 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TaggingPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/raceboard/tagging/TaggingPanel.java @@ -34,6 +34,7 @@ import com.sap.sailing.domain.common.dto.TagDTO; import com.sap.sailing.gwt.ui.client.RaceTimesInfoProvider; import com.sap.sailing.gwt.ui.client.RaceTimesInfoProviderListener; import com.sap.sailing.gwt.ui.client.SailingServiceAsync; +import com.sap.sailing.gwt.ui.client.SailingServiceWriteAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.raceboard.tagging.TaggingPanelResources.TagPanelStyle; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; @@ -128,6 +129,7 @@ public class TaggingPanel extends ComponentWithoutSettings // misc. elements private final StringMessages stringMessages; private final SailingServiceAsync sailingService; + private final SailingServiceWriteAsync sailingServiceWrite; private final UserService userService; private final Timer timer; private final RaceTimesInfoProvider raceTimesInfoProvider; @@ -168,11 +170,12 @@ public class TaggingPanel extends ComponentWithoutSettings public TaggingPanel(Component parent, ComponentContext context, StringMessages stringMessages, SailingServiceAsync sailingService, UserService userService, Timer timer, RaceTimesInfoProvider raceTimesInfoProvider, TimePoint timePointToHighlight, String tagToHighlight, - StrippedLeaderboardDTOWithSecurity leaderboardDTO) { + StrippedLeaderboardDTOWithSecurity leaderboardDTO, SailingServiceWriteAsync sailingServiceWrite) { super(parent, context); this.stringMessages = stringMessages; this.sailingService = sailingService; + this.sailingServiceWrite = sailingServiceWrite; this.userService = userService; this.timer = timer; this.raceTimesInfoProvider = raceTimesInfoProvider; @@ -392,7 +395,7 @@ public class TaggingPanel extends ComponentWithoutSettings || imageHeight > MediaTagConstants.TAGGING_IMAGE.getMaxHeight()) { ArrayList tags = new ArrayList(); tags.add(MediaTagConstants.TAGGING_IMAGE); - sailingService.resizeImage(new ImageResizingTaskDTO(imageURL, new Date(), tags), + sailingServiceWrite.resizeImage(new ImageResizingTaskDTO(imageURL, new Date(), tags), new AsyncCallback>() { @Override public void onFailure(Throwable caught) { @@ -445,7 +448,7 @@ public class TaggingPanel extends ComponentWithoutSettings final String saveComment = (comment == null ? "" : comment); final TimePoint saveRaceTimePoint = (raceTimePoint == null ? new MillisecondsTimePoint(getTimerTime()) : raceTimePoint); - sailingService.addTag(leaderboardName, raceColumn.getName(), fleet.getName(), tag, saveComment, imageURL, + sailingServiceWrite.addTag(leaderboardName, raceColumn.getName(), fleet.getName(), tag, saveComment, imageURL, resizedImageURL, visibleForPublic, saveRaceTimePoint, new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -492,7 +495,7 @@ public class TaggingPanel extends ComponentWithoutSettings * when set to true, only error messages will get displayed to user */ protected void removeTag(TagDTO tag, boolean silent) { - sailingService.removeTag(leaderboardName, raceColumn.getName(), fleet.getName(), tag, + sailingServiceWrite.removeTag(leaderboardName, raceColumn.getName(), fleet.getName(), tag, new AsyncCallback() { @Override public void onFailure(Throwable caught) { @@ -535,7 +538,7 @@ public class TaggingPanel extends ComponentWithoutSettings @Override public void onSuccess(String resizedImageURL) { - sailingService.updateTag(leaderboardName, raceColumn.getName(), fleet.getName(), tagToUpdate, tag, + sailingServiceWrite.updateTag(leaderboardName, raceColumn.getName(), fleet.getName(), tagToUpdate, tag, comment, imageURL, resizedImageURL, visibleForPublic, new AsyncCallback() { @Override public void onFailure(Throwable caught) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/MediaServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/MediaServiceImpl.java index c92bba3d931..69ad0600973 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/MediaServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/MediaServiceImpl.java @@ -17,8 +17,6 @@ import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.charset.StandardCharsets; import java.nio.file.Files; -import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.logging.Level; @@ -64,10 +62,8 @@ public class MediaServiceImpl extends RemoteServiceServlet implements MediaServi private static final int METADATA_CONNECTION_TIMEOUT = 10000; - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); private ServiceTracker racingEventServiceTracker; - private static final long serialVersionUID = -8917349579281305977L; public MediaServiceImpl() { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java index 0756debdfb0..a3ed657ff24 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java @@ -12,7 +12,6 @@ import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; @@ -54,8 +53,6 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.StreamSupport; -import javax.imageio.metadata.IIOMetadata; -import javax.management.InvalidAttributeValueException; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; @@ -64,7 +61,6 @@ import javax.servlet.http.HttpServletRequest; import org.apache.commons.math.FunctionEvaluationException; import org.apache.commons.math.MaxIterationsExceededException; -import org.apache.http.client.ClientProtocolException; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authz.AuthorizationException; import org.apache.shiro.authz.UnauthorizedException; @@ -82,100 +78,35 @@ import com.sap.sailing.domain.abstractlog.AbstractLog; import com.sap.sailing.domain.abstractlog.AbstractLogEvent; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.impl.AllEventsOfTypeFinder; -import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; -import com.sap.sailing.domain.abstractlog.orc.BaseORCCertificateAssignmentAnalyzer; -import com.sap.sailing.domain.abstractlog.orc.ORCCertificateAssignmentEvent; -import com.sap.sailing.domain.abstractlog.orc.RaceLogORCCertificateAssignmentEvent; import com.sap.sailing.domain.abstractlog.orc.RaceLogORCCertificateAssignmentFinder; -import com.sap.sailing.domain.abstractlog.orc.RaceLogORCImpliedWindSourceEvent; import com.sap.sailing.domain.abstractlog.orc.RaceLogORCImpliedWindSourceFinder; import com.sap.sailing.domain.abstractlog.orc.RaceLogORCLegDataAnalyzer; -import com.sap.sailing.domain.abstractlog.orc.RaceLogORCLegDataEvent; -import com.sap.sailing.domain.abstractlog.orc.RaceLogORCLegDataEventFinder; -import com.sap.sailing.domain.abstractlog.orc.RaceLogORCScratchBoatAnalyzer; -import com.sap.sailing.domain.abstractlog.orc.RaceLogORCScratchBoatEvent; -import com.sap.sailing.domain.abstractlog.orc.RaceLogORCScratchBoatFinder; import com.sap.sailing.domain.abstractlog.orc.RegattaLogORCCertificateAssignmentFinder; -import com.sap.sailing.domain.abstractlog.orc.impl.RaceLogORCCertificateAssignmentEventImpl; import com.sap.sailing.domain.abstractlog.orc.impl.RaceLogORCImpliedWindSourceEventImpl; -import com.sap.sailing.domain.abstractlog.orc.impl.RaceLogORCLegDataEventImpl; -import com.sap.sailing.domain.abstractlog.orc.impl.RaceLogORCScratchBoatEventImpl; -import com.sap.sailing.domain.abstractlog.orc.impl.RegattaLogORCCertificateAssignmentEventImpl; import com.sap.sailing.domain.abstractlog.race.RaceLog; -import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; -import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogPathfinderEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogProtestStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; -import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.AbortingFlagFinder; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishedTimeFinder; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishingTimeFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCourseDesignFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.MarkPassingDataFinder; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult; -import com.sap.sailing.domain.abstractlog.race.analyzing.impl.TrackingTimesEventFinder; import com.sap.sailing.domain.abstractlog.race.analyzing.impl.TrackingTimesFinder; -import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogDependentStartTimeEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEndOfTrackingEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningConfirmedEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningListChangedEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFixedMarkPassingEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogGateLineOpeningTimeEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPathfinderEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogProtestStartTimeEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChangedEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogSuppressedMarkPassingsEventImpl; -import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; -import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; -import com.sap.sailing.domain.abstractlog.race.scoring.impl.RaceLogAdditionalScoringInformationEventImpl; import com.sap.sailing.domain.abstractlog.race.state.ReadonlyRaceState; import com.sap.sailing.domain.abstractlog.race.state.impl.ReadonlyRaceStateImpl; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.FlagPoleState; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.gate.ReadonlyGateStartRacingProcedure; import com.sap.sailing.domain.abstractlog.race.state.racingprocedure.line.ConfigurableStartModeFlagRacingProcedure; import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogDenoteForTrackingEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; import com.sap.sailing.domain.abstractlog.race.tracking.analyzing.impl.RaceLogTrackingStateAnalyzer; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl; -import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl; import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; -import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; -import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent; import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogRegisterCompetitorEvent; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDefineMarkEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceBoatMappingEventImpl; -import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorExpeditionExtendedMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMarkMappingEventImpl; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.BaseRegattaLogDeviceMappingFinder; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceMappingFinder; import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceMarkMappingFinder; -import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogOpenEndedDeviceMappingCloser; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.BoatClass; import com.sap.sailing.domain.base.Competitor; @@ -192,7 +123,6 @@ import com.sap.sailing.domain.base.Fleet; import com.sap.sailing.domain.base.LeaderboardGroupBase; import com.sap.sailing.domain.base.Leg; import com.sap.sailing.domain.base.Mark; -import com.sap.sailing.domain.base.Nationality; import com.sap.sailing.domain.base.PairingListLeaderboardAdapter; import com.sap.sailing.domain.base.RaceColumn; import com.sap.sailing.domain.base.RaceColumnInSeries; @@ -202,7 +132,6 @@ import com.sap.sailing.domain.base.RemoteSailingServerReference; import com.sap.sailing.domain.base.SailingServerConfiguration; import com.sap.sailing.domain.base.Series; import com.sap.sailing.domain.base.Sideline; -import com.sap.sailing.domain.base.SpeedWithBearingWithConfidence; import com.sap.sailing.domain.base.Waypoint; import com.sap.sailing.domain.base.configuration.DeviceConfiguration; import com.sap.sailing.domain.base.configuration.RacingProcedureConfiguration; @@ -217,41 +146,22 @@ import com.sap.sailing.domain.base.configuration.impl.RacingProcedureWithConfigu import com.sap.sailing.domain.base.configuration.impl.RegattaConfigurationImpl; import com.sap.sailing.domain.base.configuration.impl.SWCStartConfigurationImpl; import com.sap.sailing.domain.base.configuration.procedures.ConfigurableStartModeFlagRacingProcedureConfiguration; -import com.sap.sailing.domain.base.impl.BoatImpl; -import com.sap.sailing.domain.base.impl.CompetitorImpl; -import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; import com.sap.sailing.domain.base.impl.CourseDataImpl; -import com.sap.sailing.domain.base.impl.CourseImpl; -import com.sap.sailing.domain.base.impl.DynamicBoat; -import com.sap.sailing.domain.base.impl.DynamicCompetitorWithBoat; -import com.sap.sailing.domain.base.impl.DynamicPerson; -import com.sap.sailing.domain.base.impl.DynamicTeam; -import com.sap.sailing.domain.base.impl.EventBaseImpl; -import com.sap.sailing.domain.base.impl.PersonImpl; import com.sap.sailing.domain.base.impl.SailingServerConfigurationImpl; -import com.sap.sailing.domain.base.impl.TeamImpl; import com.sap.sailing.domain.common.CompetitorDescriptor; -import com.sap.sailing.domain.common.CompetitorRegistrationType; -import com.sap.sailing.domain.common.CourseDesignerMode; -import com.sap.sailing.domain.common.DataImportProgress; import com.sap.sailing.domain.common.DetailType; import com.sap.sailing.domain.common.DeviceIdentifier; import com.sap.sailing.domain.common.LeaderboardNameConstants; -import com.sap.sailing.domain.common.LeaderboardType; import com.sap.sailing.domain.common.LegIdentifier; import com.sap.sailing.domain.common.LegType; import com.sap.sailing.domain.common.MailInvitationType; import com.sap.sailing.domain.common.ManeuverType; -import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.NauticalSide; import com.sap.sailing.domain.common.NoWindException; import com.sap.sailing.domain.common.NotFoundException; -import com.sap.sailing.domain.common.PassingInstruction; import com.sap.sailing.domain.common.PathType; -import com.sap.sailing.domain.common.PolarSheetsXYDiagramData; import com.sap.sailing.domain.common.Position; import com.sap.sailing.domain.common.RaceFetcher; -import com.sap.sailing.domain.common.RaceIdentifier; import com.sap.sailing.domain.common.RankingMetrics; import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; import com.sap.sailing.domain.common.RegattaFetcher; @@ -262,16 +172,12 @@ import com.sap.sailing.domain.common.RegattaScoreCorrections; import com.sap.sailing.domain.common.RegattaScoreCorrections.ScoreCorrectionForCompetitorInRace; import com.sap.sailing.domain.common.RegattaScoreCorrections.ScoreCorrectionsForRace; import com.sap.sailing.domain.common.ScoreCorrectionProvider; -import com.sap.sailing.domain.common.ScoringSchemeType; -import com.sap.sailing.domain.common.ServiceException; import com.sap.sailing.domain.common.SpeedWithBearing; import com.sap.sailing.domain.common.Tack; import com.sap.sailing.domain.common.TrackedRaceStatusEnum; -import com.sap.sailing.domain.common.UnableToCloseDeviceMappingException; import com.sap.sailing.domain.common.Wind; import com.sap.sailing.domain.common.WindSource; import com.sap.sailing.domain.common.WindSourceType; -import com.sap.sailing.domain.common.abstractlog.NotRevokableException; import com.sap.sailing.domain.common.abstractlog.TimePointSpecificationFoundInLog; import com.sap.sailing.domain.common.dto.BoatClassDTO; import com.sap.sailing.domain.common.dto.BoatDTO; @@ -289,20 +195,15 @@ import com.sap.sailing.domain.common.dto.PairingListTemplateDTO; import com.sap.sailing.domain.common.dto.PersonDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTO; import com.sap.sailing.domain.common.dto.RaceColumnDTOFactory; -import com.sap.sailing.domain.common.dto.RaceColumnInSeriesDTO; import com.sap.sailing.domain.common.dto.RaceDTO; import com.sap.sailing.domain.common.dto.RaceLogTrackingInfoDTO; -import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO; import com.sap.sailing.domain.common.dto.SeriesCreationParametersDTO; import com.sap.sailing.domain.common.dto.TagDTO; import com.sap.sailing.domain.common.dto.TrackedRaceDTO; -import com.sap.sailing.domain.common.impl.DegreePosition; import com.sap.sailing.domain.common.impl.KilometersPerHourSpeedImpl; import com.sap.sailing.domain.common.impl.KnotSpeedImpl; import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; import com.sap.sailing.domain.common.impl.MeterDistance; -import com.sap.sailing.domain.common.impl.PolarSheetsXYDiagramDataImpl; -import com.sap.sailing.domain.common.impl.WindImpl; import com.sap.sailing.domain.common.impl.WindSourceImpl; import com.sap.sailing.domain.common.media.MediaTrack; import com.sap.sailing.domain.common.orc.ImpliedWindSource; @@ -315,22 +216,15 @@ import com.sap.sailing.domain.common.racelog.FlagPole; import com.sap.sailing.domain.common.racelog.Flags; import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; import com.sap.sailing.domain.common.racelog.RacingProcedureType; -import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException; import com.sap.sailing.domain.common.racelog.tracking.DoesNotHaveRegattaLogException; import com.sap.sailing.domain.common.racelog.tracking.MappableToDevice; -import com.sap.sailing.domain.common.racelog.tracking.NotDenotableForRaceLogTrackingException; -import com.sap.sailing.domain.common.racelog.tracking.NotDenotedForRaceLogTrackingException; import com.sap.sailing.domain.common.racelog.tracking.RaceLogTrackingState; import com.sap.sailing.domain.common.racelog.tracking.TransformationException; import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.domain.common.sharding.ShardingType; -import com.sap.sailing.domain.common.tagging.RaceLogNotFoundException; -import com.sap.sailing.domain.common.tagging.ServiceNotFoundException; -import com.sap.sailing.domain.common.tagging.TagAlreadyExistsException; import com.sap.sailing.domain.common.tracking.BravoFix; import com.sap.sailing.domain.common.tracking.GPSFix; import com.sap.sailing.domain.common.tracking.GPSFixMoving; -import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl; import com.sap.sailing.domain.common.tracking.impl.GPSFixMovingImpl; import com.sap.sailing.domain.common.tracking.impl.PreciseCompactGPSFixMovingImpl.PreciseCompactPosition; import com.sap.sailing.domain.common.windfinder.SpotDTO; @@ -350,7 +244,6 @@ import com.sap.sailing.domain.coursetemplate.impl.CommonMarkPropertiesImpl; import com.sap.sailing.domain.coursetemplate.impl.RepeatablePartImpl; import com.sap.sailing.domain.coursetemplate.impl.WaypointTemplateImpl; import com.sap.sailing.domain.igtimiadapter.Account; -import com.sap.sailing.domain.igtimiadapter.IgtimiConnection; import com.sap.sailing.domain.igtimiadapter.IgtimiConnectionFactory; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard; @@ -361,7 +254,6 @@ import com.sap.sailing.domain.leaderboard.RegattaLeaderboardWithEliminations; import com.sap.sailing.domain.leaderboard.ThresholdBasedResultDiscardingRule; import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuseCache; import com.sap.sailing.domain.leaderboard.caching.LiveLeaderboardUpdater; -import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; import com.sap.sailing.domain.leaderboard.meta.MetaLeaderboardColumn; import com.sap.sailing.domain.orc.ORCPerformanceCurveRankingMetric; import com.sap.sailing.domain.orc.ORCPublicCertificateDatabase; @@ -385,12 +277,10 @@ import com.sap.sailing.domain.racelogtracking.impl.SmartphoneUUIDIdentifierImpl; import com.sap.sailing.domain.ranking.RankingMetric; import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo; import com.sap.sailing.domain.regattalike.HasRegattaLike; -import com.sap.sailing.domain.regattalike.IsRegattaLike; import com.sap.sailing.domain.regattalike.LeaderboardThatHasRegattaLike; import com.sap.sailing.domain.regattalog.RegattaLogStore; import com.sap.sailing.domain.resultimport.ResultUrlProvider; import com.sap.sailing.domain.sharding.ShardingContext; -import com.sap.sailing.domain.swisstimingadapter.StartList; import com.sap.sailing.domain.swisstimingadapter.SwissTimingAdapter; import com.sap.sailing.domain.swisstimingadapter.SwissTimingAdapterFactory; import com.sap.sailing.domain.swisstimingadapter.SwissTimingArchiveConfiguration; @@ -411,8 +301,6 @@ import com.sap.sailing.domain.tracking.GPSFixTrack; import com.sap.sailing.domain.tracking.LineDetails; import com.sap.sailing.domain.tracking.Maneuver; import com.sap.sailing.domain.tracking.MarkPassing; -import com.sap.sailing.domain.tracking.RaceHandle; -import com.sap.sailing.domain.tracking.RaceTracker; import com.sap.sailing.domain.tracking.Track; import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; @@ -431,16 +319,12 @@ import com.sap.sailing.domain.tractracadapter.TracTracConnectionConstants; import com.sap.sailing.domain.windfinder.Spot; import com.sap.sailing.domain.windfinder.WindFinderTrackerFactory; import com.sap.sailing.expeditionconnector.ExpeditionDeviceConfiguration; -import com.sap.sailing.expeditionconnector.ExpeditionSensorDeviceIdentifier; import com.sap.sailing.expeditionconnector.ExpeditionTrackerFactory; import com.sap.sailing.gwt.common.client.EventWindFinderUtil; import com.sap.sailing.gwt.server.HomeServiceUtil; -import com.sap.sailing.gwt.ui.adminconsole.RaceLogSetTrackingTimesDTO; import com.sap.sailing.gwt.ui.client.SailingService; import com.sap.sailing.gwt.ui.client.shared.charts.MarkPositionService.MarkTrackDTO; -import com.sap.sailing.gwt.ui.client.shared.charts.MarkPositionService.MarkTracksDTO; import com.sap.sailing.gwt.ui.shared.AccountWithSecurityDTO; -import com.sap.sailing.gwt.ui.shared.BulkScoreCorrectionDTO; import com.sap.sailing.gwt.ui.shared.CompactBoatPositionsDTO; import com.sap.sailing.gwt.ui.shared.CompactRaceMapDataDTO; import com.sap.sailing.gwt.ui.shared.CompetitorProviderDTO; @@ -467,7 +351,6 @@ import com.sap.sailing.gwt.ui.shared.ManeuverDTO; import com.sap.sailing.gwt.ui.shared.ManeuverLossDTO; import com.sap.sailing.gwt.ui.shared.MarkDTO; import com.sap.sailing.gwt.ui.shared.MarkPassingTimesDTO; -import com.sap.sailing.gwt.ui.shared.MigrateGroupOwnerForHierarchyDTO; import com.sap.sailing.gwt.ui.shared.PathDTO; import com.sap.sailing.gwt.ui.shared.QRCodeEvent; import com.sap.sailing.gwt.ui.shared.QuickRankDTO; @@ -515,7 +398,6 @@ import com.sap.sailing.gwt.ui.shared.TracTracConfigurationWithSecurityDTO; import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDTO; import com.sap.sailing.gwt.ui.shared.TrackFileImportDeviceIdentifierDTO; import com.sap.sailing.gwt.ui.shared.TrackingConnectorInfoDTO; -import com.sap.sailing.gwt.ui.shared.TypedDeviceMappingDTO; import com.sap.sailing.gwt.ui.shared.UrlDTO; import com.sap.sailing.gwt.ui.shared.VenueDTO; import com.sap.sailing.gwt.ui.shared.WaypointDTO; @@ -535,64 +417,12 @@ import com.sap.sailing.manage2sail.RaceResultDescriptor; import com.sap.sailing.manage2sail.RegattaResultDescriptor; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; import com.sap.sailing.server.gateway.deserialization.racelog.impl.ORCCertificateJsonDeserializer; -import com.sap.sailing.server.hierarchy.SailingHierarchyOwnershipUpdater; import com.sap.sailing.server.interfaces.RacingEventService; import com.sap.sailing.server.interfaces.SimulationService; -import com.sap.sailing.server.operationaltransformation.AddColumnToLeaderboard; -import com.sap.sailing.server.operationaltransformation.AddColumnToSeries; -import com.sap.sailing.server.operationaltransformation.AddCourseAreas; import com.sap.sailing.server.operationaltransformation.AddRemoteSailingServerReference; -import com.sap.sailing.server.operationaltransformation.AddSpecificRegatta; -import com.sap.sailing.server.operationaltransformation.AllowBoatResetToDefaults; -import com.sap.sailing.server.operationaltransformation.AllowCompetitorResetToDefaults; -import com.sap.sailing.server.operationaltransformation.ConnectTrackedRaceToLeaderboardColumn; -import com.sap.sailing.server.operationaltransformation.CreateEvent; -import com.sap.sailing.server.operationaltransformation.CreateFlexibleLeaderboard; -import com.sap.sailing.server.operationaltransformation.CreateLeaderboardGroup; -import com.sap.sailing.server.operationaltransformation.CreateRegattaLeaderboard; -import com.sap.sailing.server.operationaltransformation.CreateRegattaLeaderboardWithEliminations; -import com.sap.sailing.server.operationaltransformation.DisconnectLeaderboardColumnFromTrackedRace; -import com.sap.sailing.server.operationaltransformation.MoveColumnInSeriesDown; -import com.sap.sailing.server.operationaltransformation.MoveColumnInSeriesUp; -import com.sap.sailing.server.operationaltransformation.MoveLeaderboardColumnDown; -import com.sap.sailing.server.operationaltransformation.MoveLeaderboardColumnUp; -import com.sap.sailing.server.operationaltransformation.RemoveAndUntrackRace; -import com.sap.sailing.server.operationaltransformation.RemoveColumnFromSeries; -import com.sap.sailing.server.operationaltransformation.RemoveCourseAreas; -import com.sap.sailing.server.operationaltransformation.RemoveEvent; -import com.sap.sailing.server.operationaltransformation.RemoveLeaderboard; -import com.sap.sailing.server.operationaltransformation.RemoveLeaderboardColumn; -import com.sap.sailing.server.operationaltransformation.RemoveLeaderboardGroup; -import com.sap.sailing.server.operationaltransformation.RemoveRegatta; import com.sap.sailing.server.operationaltransformation.RemoveRemoteSailingServerReference; -import com.sap.sailing.server.operationaltransformation.RemoveSeries; -import com.sap.sailing.server.operationaltransformation.RenameEvent; -import com.sap.sailing.server.operationaltransformation.RenameLeaderboard; -import com.sap.sailing.server.operationaltransformation.RenameLeaderboardColumn; -import com.sap.sailing.server.operationaltransformation.RenameLeaderboardGroup; -import com.sap.sailing.server.operationaltransformation.SetRaceIsKnownToStartUpwind; -import com.sap.sailing.server.operationaltransformation.SetSuppressedFlagForCompetitorInLeaderboard; -import com.sap.sailing.server.operationaltransformation.SetWindSourcesToExclude; -import com.sap.sailing.server.operationaltransformation.StopTrackingRace; -import com.sap.sailing.server.operationaltransformation.UpdateBoat; -import com.sap.sailing.server.operationaltransformation.UpdateCompetitor; -import com.sap.sailing.server.operationaltransformation.UpdateCompetitorDisplayNameInLeaderboard; -import com.sap.sailing.server.operationaltransformation.UpdateEliminatedCompetitorsInLeaderboard; -import com.sap.sailing.server.operationaltransformation.UpdateEvent; -import com.sap.sailing.server.operationaltransformation.UpdateIsMedalRace; -import com.sap.sailing.server.operationaltransformation.UpdateLeaderboard; -import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardCarryValue; -import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardColumnFactor; -import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardGroup; -import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardMaxPointsReason; -import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardScoreCorrection; -import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardScoreCorrectionMetadata; -import com.sap.sailing.server.operationaltransformation.UpdateRaceDelayToLive; -import com.sap.sailing.server.operationaltransformation.UpdateSeries; import com.sap.sailing.server.operationaltransformation.UpdateServerConfiguration; -import com.sap.sailing.server.operationaltransformation.UpdateSpecificRegatta; import com.sap.sailing.server.security.SailingViewerRole; -import com.sap.sailing.server.util.WaitForTrackedRaceUtil; import com.sap.sailing.shared.server.SharedSailingData; import com.sap.sailing.simulator.Path; import com.sap.sailing.simulator.PolarDiagram; @@ -601,7 +431,6 @@ import com.sap.sailing.simulator.TimedPositionWithSpeed; import com.sap.sailing.simulator.impl.PolarDiagramGPS; import com.sap.sailing.simulator.impl.SparseSimulationDataException; import com.sap.sailing.util.RegattaUtil; -import com.sap.sailing.xrr.schema.RegattaResults; import com.sap.sailing.xrr.structureimport.SeriesParameters; import com.sap.sailing.xrr.structureimport.StructureImporter; import com.sap.sailing.xrr.structureimport.buildstructure.SetRacenumberFromSeries; @@ -623,25 +452,16 @@ import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; import com.sap.sse.common.Util.Triple; import com.sap.sse.common.WithID; -import com.sap.sse.common.impl.DegreeBearingImpl; import com.sap.sse.common.impl.MillisecondsTimePoint; import com.sap.sse.common.impl.SecondsDurationImpl; import com.sap.sse.common.impl.TimeRangeImpl; -import com.sap.sse.common.mail.MailException; import com.sap.sse.common.media.MediaTagConstants; import com.sap.sse.common.media.MimeType; -import com.sap.sse.filestorage.FileStorageManagementService; -import com.sap.sse.filestorage.FileStorageService; -import com.sap.sse.filestorage.InvalidPropertiesException; -import com.sap.sse.filestorage.OperationFailedException; import com.sap.sse.gwt.client.ServerInfoDTO; import com.sap.sse.gwt.client.media.ImageDTO; import com.sap.sse.gwt.client.media.ImageResizingTaskDTO; import com.sap.sse.gwt.client.media.VideoDTO; import com.sap.sse.gwt.server.ResultCachingProxiedRemoteServiceServlet; -import com.sap.sse.gwt.server.filestorage.FileStorageServiceDTOUtils; -import com.sap.sse.gwt.shared.filestorage.FileStorageServiceDTO; -import com.sap.sse.gwt.shared.filestorage.FileStorageServicePropertyErrorsDTO; import com.sap.sse.gwt.shared.replication.ReplicaDTO; import com.sap.sse.gwt.shared.replication.ReplicationMasterDTO; import com.sap.sse.gwt.shared.replication.ReplicationStateDTO; @@ -673,7 +493,6 @@ import com.sap.sse.security.shared.impl.SecuredSecurityTypes.ServerActions; import com.sap.sse.security.shared.impl.UserGroup; import com.sap.sse.security.ui.server.SecurityDTOFactory; import com.sap.sse.security.ui.server.SecurityDTOUtil; -import com.sap.sse.security.ui.shared.SuccessInfo; import com.sap.sse.security.util.RemoteServerUtil; import com.sap.sse.shared.media.ImageDescriptor; import com.sap.sse.shared.media.MediaUtils; @@ -681,11 +500,8 @@ import com.sap.sse.shared.media.VideoDescriptor; import com.sap.sse.shared.media.impl.ImageDescriptorImpl; import com.sap.sse.shared.media.impl.VideoDescriptorImpl; import com.sap.sse.util.HttpUrlConnectionHelper; -import com.sap.sse.util.ImageConverter; -import com.sap.sse.util.ImageConverter.ImageWithMetadata; import com.sap.sse.util.ServiceTrackerFactory; import com.sap.sse.util.ThreadPoolUtil; -import com.sap.sse.util.impl.UUIDHelper; import com.sapsailing.xrr.structureimport.eventimport.RegattaJSON; @@ -693,7 +509,7 @@ import com.sapsailing.xrr.structureimport.eventimport.RegattaJSON; * The server side implementation of the RPC service. */ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet implements SailingService, RaceFetcher, RegattaFetcher { - private static final Logger logger = Logger.getLogger(SailingServiceImpl.class.getName()); + protected static final Logger logger = Logger.getLogger(SailingServiceImpl.class.getName()); private static final String STRING_MESSAGES_BASE_NAME = "stringmessages/StringMessages"; @@ -711,9 +527,9 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet private final MongoObjectFactory mongoObjectFactory; - private final ServiceTracker expeditionConnectorTracker; + protected final ServiceTracker expeditionConnectorTracker; - private final SwissTimingAdapterPersistence swissTimingAdapterPersistence; + protected final SwissTimingAdapterPersistence swissTimingAdapterPersistence; private final ServiceTracker swissTimingAdapterTracker; @@ -730,27 +546,25 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet private final FullyInitializedReplicableTracker sharedSailingDataTracker; - private final com.sap.sailing.domain.tractracadapter.persistence.MongoObjectFactory tractracMongoObjectFactory; + protected final com.sap.sailing.domain.tractracadapter.persistence.MongoObjectFactory tractracMongoObjectFactory; private final DomainObjectFactory domainObjectFactory; - private final SwissTimingFactory swissTimingFactory; + protected final SwissTimingFactory swissTimingFactory; private final com.sap.sailing.domain.tractracadapter.persistence.DomainObjectFactory tractracDomainObjectFactory; - private final com.sap.sse.common.CountryCodeFactory countryCodeFactory; - - private final Executor executor; + protected final Executor executor; - private final com.sap.sailing.domain.base.DomainFactory baseDomainFactory; + protected final com.sap.sailing.domain.base.DomainFactory baseDomainFactory; private static final int LEADERBOARD_BY_NAME_RESULTS_CACHE_BY_ID_SIZE = 100; private static final int LEADERBOARD_DIFFERENCE_CACHE_SIZE = 50; - private static final String MAILTYPE_PROPERTY = "com.sap.sailing.domain.tracking.MailInvitationType"; + protected static final String MAILTYPE_PROPERTY = "com.sap.sailing.domain.tracking.MailInvitationType"; - private ResourceBundleStringMessages serverStringMessages; + protected ResourceBundleStringMessages serverStringMessages; private final LinkedHashMap leaderboardByNameResultsCacheById; @@ -801,7 +615,6 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet .getTracTracDomainFactory()); tractracMongoObjectFactory = com.sap.sailing.domain.tractracadapter.persistence.MongoObjectFactory.INSTANCE; swissTimingFactory = SwissTimingFactory.INSTANCE; - countryCodeFactory = com.sap.sse.common.CountryCodeFactory.INSTANCE; leaderboardDifferenceCacheByIdPair = new LinkedHashMap, IncrementalLeaderboardDTO>(LEADERBOARD_DIFFERENCE_CACHE_SIZE, 0.75f, /* accessOrder */ true) { private static final long serialVersionUID = 3775119859130148488L; @Override @@ -831,6 +644,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * Stops this service and frees its resources. In particular, caching services and threads owned by this service will be * notified to stop their jobs. */ + //UNCLEAR public void stop() { quickRanksLiveCache.stop(); } @@ -855,6 +669,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet oos.defaultWriteObject(); } + //READ @Override public Iterable getScoreCorrectionProviderNames() { List result = new ArrayList(); @@ -864,6 +679,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ @Override public ScoreCorrectionProviderDTO getScoreCorrectionsOfProvider(String providerName) throws Exception { ScoreCorrectionProviderDTO result = null; @@ -876,6 +692,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + // READ private Iterable getAllScoreCorrectionProviders() { final ScoreCorrectionProvider[] services = scoreCorrectionProviderServiceTracker.getServices(new ScoreCorrectionProvider[0]); List result = new ArrayList(); @@ -887,6 +704,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private ScoreCorrectionProviderDTO convertScoreCorrectionProviderDTO(ScoreCorrectionProvider scoreCorrectionProvider) throws Exception { Map>> hasResultsForBoatClassFromDateByEventName = new HashMap>>(); @@ -901,6 +719,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return new ScoreCorrectionProviderDTO(scoreCorrectionProvider.getName(), hasResultsForBoatClassFromDateByEventName); } + //READ @Override public Iterable getCompetitorProviderNames() { List result = new ArrayList<>(); @@ -910,6 +729,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private Iterable getAllCompetitorProviders() { final CompetitorProvider[] services = competitorProviderServiceTracker.getServices(new CompetitorProvider[0]); List result = new ArrayList<>(); @@ -921,6 +741,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ @Override public CompetitorProviderDTO getCompetitorProviderDTOByName(String providerName) throws Exception { for (CompetitorProvider competitorProvider : getAllCompetitorProviders()) { @@ -932,6 +753,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return null; } + //READ @Override public List getCompetitorDescriptors(String competitorProviderName, String eventName, String regattaName) throws Exception { @@ -947,6 +769,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return Collections.emptyList(); } + //READ @Override public SerializationDummy serializationDummy(PersonDTO dummy, CountryCode ccDummy, PreciseCompactPosition preciseCompactPosition, @@ -970,6 +793,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * {@link FullLeaderboardDTO} will be computed; otherwise, an {@link IncrementalLeaderboardDTO} will be * computed as the difference between the new, resulting leaderboard and the previous leaderboard. */ + //READ @Override public IncrementalOrFullLeaderboardDTO getLeaderboardByName(final String leaderboardName, final Date date, final Collection namesOfRaceColumnsForWhichToLoadLegDetails, boolean addOverallDetails, @@ -995,23 +819,30 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ @Override public IncrementalOrFullLeaderboardDTO getLeaderboardForRace(final RegattaAndRaceIdentifier race, final String leaderboardName, final Date date, final Collection namesOfRaceColumnsForWhichToLoadLegDetails, boolean addOverallDetails, String previousLeaderboardId, boolean fillTotalPointsUncorrected) throws NoWindException, InterruptedException, ExecutionException, IllegalArgumentException { - final DynamicTrackedRace trackedRace = getService().getTrackedRace(race); - final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - if (leaderboard.getRaceColumnAndFleet(trackedRace) == null) { - // this race does not seem to be contained in the leaderboard, also check leaderboard - getSecurityService().checkCurrentUserReadPermission(leaderboard); + final DynamicTrackedRace trackedRace = getService().getExistingTrackedRace(race); + final IncrementalOrFullLeaderboardDTO result; + if (trackedRace == null) { + result = null; + } else { + final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + if (leaderboard.getRaceColumnAndFleet(trackedRace) == null) { + // this race does not seem to be contained in the leaderboard, also check leaderboard + getSecurityService().checkCurrentUserReadPermission(leaderboard); + } + getSecurityService().checkCurrentUserReadPermission(trackedRace); + result = getLeaderBoardByNameInternal(leaderboardName, date, namesOfRaceColumnsForWhichToLoadLegDetails, + addOverallDetails, previousLeaderboardId, fillTotalPointsUncorrected); } - getSecurityService().checkCurrentUserReadPermission(trackedRace); - return getLeaderBoardByNameInternal(leaderboardName, date, namesOfRaceColumnsForWhichToLoadLegDetails, - addOverallDetails, previousLeaderboardId, fillTotalPointsUncorrected); + return result; } - + //READ private IncrementalOrFullLeaderboardDTO getLeaderBoardByNameInternal(final String leaderboardName, final Date date, final Collection namesOfRaceColumnsForWhichToLoadLegDetails, boolean addOverallDetails, String previousLeaderboardId, boolean fillTotalPointsUncorrected) @@ -1097,19 +928,14 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } } + //READ @Override public List getRegattas() { return getSecurityService().mapAndFilterByReadPermissionForCurrentUser( getService().getAllRegattas(), this::convertToRegattaDTO); } - - @Override - public List getRegattasWithUpdatePermission() { - return getSecurityService().mapAndFilterByExplicitPermissionForCurrentUser( - new HasPermissions.Action[] { DefaultActions.READ, DefaultActions.UPDATE }, - getService().getAllRegattas(), this::convertToRegattaDTO); - } - + + //READ @Override public RegattaDTO getRegattaByName(String regattaName) { RegattaDTO result = null; @@ -1122,7 +948,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } return result; } - + + //?? private MarkDTO convertToMarkDTO(Mark mark, Position position) { MarkDTO markDTO; if (position != null) { @@ -1137,7 +964,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return markDTO; } - private RegattaDTO convertToRegattaDTO(Regatta regatta) { + //READ + protected RegattaDTO convertToRegattaDTO(Regatta regatta) { RegattaDTO regattaDTO = new RegattaDTO(regatta.getName(), regatta.getScoringScheme().getType()); regattaDTO.races = convertToRaceDTOs(regatta); regattaDTO.series = convertToSeriesDTOs(regatta); @@ -1161,11 +989,13 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet regattaDTO.registrationLinkSecret = regatta.getRegistrationLinkSecret(); return regattaDTO; } - + + //?? private BoatClassDTO convertToBoatClassDTO(BoatClass boatClass) { return boatClass==null?null:new BoatClassDTO(boatClass.getName(), boatClass.getDisplayName(), boatClass.getHullLength(), boatClass.getHullBeam()); } + //?? private List convertToSeriesDTOs(Regatta regatta) { List result = new ArrayList(); for (Series series : regatta.getSeries()) { @@ -1175,6 +1005,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private SeriesDTO convertToSeriesDTO(Series series) { List fleets = new ArrayList(); for (Fleet fleet : series.getFleets()) { @@ -1188,12 +1019,14 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } - private void fillRaceColumnDTO(RaceColumn raceColumn, RaceColumnDTO raceColumnDTO) { + // READ + protected void fillRaceColumnDTO(RaceColumn raceColumn, RaceColumnDTO raceColumnDTO) { raceColumnDTO.setName(raceColumn.getName()); raceColumnDTO.setMedalRace(raceColumn.isMedalRace()); raceColumnDTO.setExplicitFactor(raceColumn.getExplicitFactor()); } + //READ private List convertToRaceColumnDTOs(Iterable raceColumns) { List raceColumnDTOs = new ArrayList(); RaceColumnDTOFactory columnFactory = RaceColumnDTOFactory.INSTANCE; @@ -1208,6 +1041,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return raceColumnDTOs; } + //READ racestatecache private RaceInfoDTO createRaceInfoDTO(String seriesName, RaceColumn raceColumn, Fleet fleet, RaceLog raceLog, ReadonlyRaceState state) { RaceInfoDTO raceInfoDTO = new RaceInfoDTO(); @@ -1293,6 +1127,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return raceInfoDTO; } + //READ private void fillStartProcedureSpecifics(RaceInfoDTO raceInfoDTO, ReadonlyRaceState state) { RaceInfoExtensionDTO info = null; raceInfoDTO.startProcedure = state.getRacingProcedure().getType(); @@ -1312,6 +1147,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet raceInfoDTO.startProcedureDTO = info; } + //READ private List convertToRaceDTOs(Regatta regatta) { List result = new ArrayList(); for (RaceDefinition r : regatta.getAllRaces()) { @@ -1342,6 +1178,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * Converts the {@link Competitor} objects passed as {@code iterable} to {@link CompetitorDTO} objects. * The iteration order in the result matches that of the {@code iterable} passed. */ + //READ private List convertToCompetitorDTOs(Iterable iterable) { List result = new ArrayList<>(); for (Competitor c : iterable) { @@ -1351,7 +1188,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } - private CompetitorDTO convertToCompetitorDTO(Competitor competitor) { + //READ + protected CompetitorDTO convertToCompetitorDTO(Competitor competitor) { CompetitorDTO competitorDTO = baseDomainFactory.convertToCompetitorDTO(competitor); SecurityDTOUtil.addSecurityInformation(getSecurityService(), competitorDTO, competitor.getIdentifier()); clearNonPublicFieldsIfCurrentUserHasNoReadPermission(competitor, competitorDTO); @@ -1366,7 +1204,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } } - private CompetitorWithBoatDTO convertToCompetitorWithBoatDTO(CompetitorWithBoat competitor) { + //READ + protected CompetitorWithBoatDTO convertToCompetitorWithBoatDTO(CompetitorWithBoat competitor) { CompetitorWithBoatDTO competitorDTO = baseDomainFactory.convertToCompetitorWithBoatDTO(competitor); SecurityDTOUtil.addSecurityInformation(getSecurityService(), competitorDTO, competitor.getIdentifier()); clearNonPublicFieldsIfCurrentUserHasNoReadPermission(competitor, competitorDTO); @@ -1379,6 +1218,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * Converts the {@link Competitor} objects passed as {@code iterable} to {@link CompetitorWithBoatDTO} objects with an empty boat. * The iteration order in the result matches that of the {@code iterable} passed. */ + //READ private List convertToCompetitorAndBoatDTOs(Map competitorsAndTheirBoats) { List result = new ArrayList<>(); for (final Entry c : competitorsAndTheirBoats.entrySet()) { @@ -1395,7 +1235,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * Converts the {@link Competitor} objects passed as {@code iterable} to {@link CompetitorWithBoatDTO} objects with an empty boat. * The iteration order in the result matches that of the {@code iterable} passed. */ - private List convertToCompetitorWithBoatDTOs(Iterable iterable) { + //READ + protected List convertToCompetitorWithBoatDTOs(Iterable iterable) { List result = new ArrayList<>(); for (CompetitorWithBoat c : iterable) { CompetitorWithBoatDTO competitorDTO = baseDomainFactory.convertToCompetitorWithBoatDTO(c); @@ -1411,6 +1252,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * Converts the {@link Boat} objects passed as {@code iterable} to {@link BoatDTO} objects. * The iteration order in the result matches that of the {@code iterable} passed. */ + //READ private List convertToBoatDTOs(Iterable iterable) { List result = new ArrayList(); for (Boat b : iterable) { @@ -1421,13 +1263,15 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } - private BoatDTO convertToBoatDTO(Boat boat) { + //READ + protected BoatDTO convertToBoatDTO(Boat boat) { BoatDTO boatDTO = baseDomainFactory.convertToBoatDTO(boat); SecurityDTOUtil.addSecurityInformation(getSecurityService(), boatDTO, boat.getIdentifier()); return boatDTO; } @Override + //READ public com.sap.sse.common.Util.Pair> listTracTracRacesInEvent(String eventJsonURL, boolean listHiddenRaces) throws MalformedURLException, IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException { com.sap.sse.common.Util.Pair> raceRecords; raceRecords = getTracTracAdapter().getTracTracRaceRecords(new URL(eventJsonURL), /*loadClientParam*/ false); @@ -1445,57 +1289,13 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return new com.sap.sse.common.Util.Pair>(raceRecords.getA(), result); } + //READ private boolean hasRememberedRegatta(Serializable raceID) { return getService().getRememberedRegattaForRace(raceID) != null; } @Override - public void trackWithTracTrac(RegattaIdentifier regattaToAddTo, Iterable rrs, String liveURI, String storedURI, - String courseDesignUpdateURI, boolean trackWind, final boolean correctWindByDeclination, - final Duration offsetToStartTimeOfSimulatedRace, final boolean useInternalMarkPassingAlgorithm, - boolean useOfficialEventsToUpdateRaceLog, String tracTracUsername, String tracTracPassword) - throws Exception { - logger.info("tracWithTracTrac for regatta " + regattaToAddTo + " for race records " + rrs + " with liveURI " + liveURI - + " and storedURI " + storedURI); - for (TracTracRaceRecordDTO rr : rrs) { - try { - // reload JSON and load clientparams.php - RaceRecord record = getTracTracAdapter().getSingleTracTracRaceRecord(new URL(rr.jsonURL), rr.id, /*loadClientParams*/true); - logger.info("Loaded race " + record.getName() + " in " + record.getEventName() + " start:" + record.getRaceStartTime() + - " trackingStart:" + record.getTrackingStartTime() + " trackingEnd:" + record.getTrackingEndTime()); - // note that the live URI may be null for races that were put into replay mode - final String effectiveLiveURI; - if (!record.getRaceStatus().equals(TracTracConnectionConstants.REPLAY_STATUS)) { - if (liveURI == null || liveURI.trim().length() == 0) { - effectiveLiveURI = record.getLiveURI() == null ? null : record.getLiveURI().toString(); - } else { - effectiveLiveURI = liveURI; - } - } else { - effectiveLiveURI = null; - } - final String effectiveStoredURI; - if (storedURI == null || storedURI.trim().length() == 0) { - effectiveStoredURI = record.getStoredURI().toString(); - } else { - effectiveStoredURI = storedURI; - } - getTracTracAdapter().addTracTracRace(getService(), regattaToAddTo, - record.getParamURL(), effectiveLiveURI == null ? null : new URI(effectiveLiveURI), - new URI(effectiveStoredURI), new URI(courseDesignUpdateURI), - new MillisecondsTimePoint(record.getTrackingStartTime().asMillis()), - new MillisecondsTimePoint(record.getTrackingEndTime().asMillis()), getRaceLogStore(), - getRegattaLogStore(), RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS, - offsetToStartTimeOfSimulatedRace, useInternalMarkPassingAlgorithm, tracTracUsername, - tracTracPassword, record.getRaceStatus(), record.getRaceVisibility(), trackWind, - correctWindByDeclination, useOfficialEventsToUpdateRaceLog); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error trying to load race " + rrs+". Continuing with remaining races...", e); - } - } - } - - @Override + //READ public List getPreviousTracTracConfigurations() throws Exception { final Iterable configs = tractracDomainObjectFactory.getTracTracConfigurations(); return getSecurityService().mapAndFilterByReadPermissionForCurrentUser( @@ -1513,45 +1313,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet }); } - @Override - public void createTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI, - String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword) throws Exception { - if (existsTracTracConfigurationForCurrentUser(jsonURL)) { - throw new RuntimeException("A configuration for the current user with this json URL already exists."); - } - final String currentUserName = getSecurityService().getCurrentUser().getName(); - final TypeRelativeObjectIdentifier identifier = TracTracConfiguration.getTypeRelativeObjectIdentifier(jsonURL, currentUserName); - getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( - SecuredDomainType.TRACTRAC_ACCOUNT, - identifier, name, - () -> tractracMongoObjectFactory.createTracTracConfiguration( - getTracTracAdapter().createTracTracConfiguration(currentUserName, name, jsonURL, liveDataURI, - storedDataURI, - courseDesignUpdateURI, tracTracUsername, tracTracPassword))); - } - - @Override - public void deleteTracTracConfigurations(Collection tracTracConfigurations) { - for (TracTracConfigurationWithSecurityDTO tracTracConfiguration : tracTracConfigurations) { - getSecurityService().checkCurrentUserDeletePermission(tracTracConfiguration); - getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(tracTracConfiguration, - () -> tractracMongoObjectFactory.deleteTracTracConfiguration(tracTracConfiguration.getCreatorName(), - tracTracConfiguration.getJsonUrl())); - } - } - - @Override - public void updateTracTracConfiguration(TracTracConfigurationWithSecurityDTO tracTracConfiguration) - throws Exception { - getSecurityService().checkCurrentUserUpdatePermission(tracTracConfiguration); - tractracMongoObjectFactory.updateTracTracConfiguration( - getTracTracAdapter().createTracTracConfiguration(tracTracConfiguration.getCreatorName(), - tracTracConfiguration.getName(), tracTracConfiguration.getJsonUrl(), - tracTracConfiguration.getLiveDataURI(), tracTracConfiguration.getStoredDataURI(), - tracTracConfiguration.getCourseDesignUpdateURI(), tracTracConfiguration.getTracTracUsername(), - tracTracConfiguration.getTracTracPassword())); - } - + //READ private RaceDefinition getRaceByName(Regatta regatta, String raceName) { if (regatta != null) { return regatta.getRaceByName(raceName); @@ -1561,22 +1323,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public void stopTrackingRaces(Iterable regattaAndRaceIdentifiers) throws Exception { - for (RegattaAndRaceIdentifier regattaAndRaceIdentifier : regattaAndRaceIdentifiers) { - getSecurityService().checkCurrentUserUpdatePermission(regattaAndRaceIdentifier); - getService().apply(new StopTrackingRace(regattaAndRaceIdentifier)); - } - } - - @Override - public void removeAndUntrackRaces(Iterable regattaAndRaceIdentifiers) { - for (RegattaAndRaceIdentifier regattaAndRaceIdentifier : regattaAndRaceIdentifiers) { - getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(regattaAndRaceIdentifier, - () -> getService().apply(new RemoveAndUntrackRace(regattaAndRaceIdentifier))); - } - } - - @Override + //READ public WindInfoForRaceDTO getRawWindFixes(RegattaAndRaceIdentifier raceIdentifier, Collection windSources) { WindInfoForRaceDTO result = null; TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier); @@ -1622,6 +1369,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ protected WindDTO createWindDTO(Wind wind, WindTrack windTrack) { WindDTO windDTO = new WindDTO(); windDTO.trueWindBearingDeg = wind.getBearing().getDegrees(); @@ -1648,6 +1396,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet /** * Uses wind for both, the non-dampened and dampened fields of the {@link WindDTO} object returned */ + //READ protected WindDTO createWindDTOFromAlreadyAveraged(Wind wind, TimePoint requestTimepoint) { WindDTO windDTO = new WindDTO(); windDTO.requestTimepoint = requestTimepoint.asMillis(); @@ -1668,69 +1417,6 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return windDTO; } - /** - * Fetches the {@link WindTrack#getAveragedWind(Position, TimePoint) average wind} from all wind tracks or those identified - * by windSourceTypeNames - */ - @Override - public WindInfoForRaceDTO getAveragedWindInfo(RegattaAndRaceIdentifier raceIdentifier, Date from, long millisecondsStepWidth, - int numberOfFixes, double latDeg, double lngDeg, Collection windSourceTypeNames) - throws NoWindException { - Position position = new DegreePosition(latDeg, lngDeg); - WindInfoForRaceDTO result = null; - TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier); - getSecurityService().checkCurrentUserReadPermission(trackedRace); - if (trackedRace != null) { - result = new WindInfoForRaceDTO(); - result.raceIsKnownToStartUpwind = trackedRace.raceIsKnownToStartUpwind(); - List windSourcesToExclude = new ArrayList(); - for (WindSource windSourceToExclude : trackedRace.getWindSourcesToExclude()) { - windSourcesToExclude.add(windSourceToExclude); - } - result.windSourcesToExclude = windSourcesToExclude; - Map windTrackInfoDTOs = new HashMap(); - result.windTrackInfoByWindSource = windTrackInfoDTOs; - List windSourcesToDeliver = new ArrayList(); - Util.addAll(trackedRace.getWindSources(), windSourcesToDeliver); - windSourcesToDeliver.add(new WindSourceImpl(WindSourceType.COMBINED)); - for (WindSource windSource : windSourcesToDeliver) { - if (windSourceTypeNames == null || windSourceTypeNames.contains(windSource.getType().name())) { - TimePoint fromTimePoint = new MillisecondsTimePoint(from); - WindTrackInfoDTO windTrackInfoDTO = new WindTrackInfoDTO(); - windTrackInfoDTO.windFixes = new ArrayList(); - WindTrack windTrack = trackedRace.getOrCreateWindTrack(windSource); - windTrackInfoDTOs.put(windSource, windTrackInfoDTO); - windTrackInfoDTO.resolutionOutsideOfWhichNoFixWillBeReturned = windTrack - .getResolutionOutsideOfWhichNoFixWillBeReturned(); - windTrackInfoDTO.dampeningIntervalInMilliseconds = windTrack - .getMillisecondsOverWhichToAverageWind(); - TimePoint timePoint = fromTimePoint; - Double minWindConfidence = 2.0; - Double maxWindConfidence = -1.0; - for (int i = 0; i < numberOfFixes; i++) { - WindWithConfidence> averagedWindWithConfidence = windTrack.getAveragedWindWithConfidence(position, timePoint); - if (averagedWindWithConfidence != null) { - WindDTO windDTO = createWindDTOFromAlreadyAveraged(averagedWindWithConfidence.getObject(), timePoint); - double confidence = averagedWindWithConfidence.getConfidence(); - windDTO.confidence = confidence; - windTrackInfoDTO.windFixes.add(windDTO); - if (confidence < minWindConfidence) { - minWindConfidence = confidence; - } - if (confidence > maxWindConfidence) { - maxWindConfidence = confidence; - } - } - timePoint = new MillisecondsTimePoint(timePoint.asMillis() + millisecondsStepWidth); - } - windTrackInfoDTO.minWindConfidence = minWindConfidence; - windTrackInfoDTO.maxWindConfidence = maxWindConfidence; - } - } - } - return result; - } - /** * @param onlyUpToNewestEvent * if true, no wind data will be returned for time points later than @@ -1741,6 +1427,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * trackedRace.getTimePointOfNewestEvent()}. */ @Override + //READ public WindInfoForRaceDTO getAveragedWindInfo(RegattaAndRaceIdentifier raceIdentifier, Date from, long millisecondsStepWidth, int numberOfFixes, Collection windSourceTypeNames, boolean onlyUpToNewestEvent, boolean includeCombinedWindForAllLegMiddles) throws NoWindException { @@ -1768,6 +1455,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * if true, the result will return non-null results for calls to * {@link WindInfoForRaceDTO#getCombinedWindOnLegMiddle(int)}. */ + //READ private WindInfoForRaceDTO getAveragedWindInfo(TimePoint from, long millisecondsStepWidth, int numberOfFixes, Collection windSourceTypeNames, final TrackedRace trackedRace, boolean onlyUpToNewestEvent, boolean includeCombinedWindForAllLegMiddles) { @@ -1815,10 +1503,12 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private interface PositionAtTimeProvider { Position getPosition(TimePoint at); } + //READ private WindTrackInfoDTO createWindTrackInfoDTO(TimePoint from, long millisecondsStepWidth, int numberOfFixes, TrackedRace trackedRace, boolean onlyUpToNewestEvent, TimePoint newestEvent, WindSource windSource, PositionAtTimeProvider positionProvider) { @@ -1873,6 +1563,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * trackedRace.getTimePointOfNewestEvent()}. */ @Override + //READ public WindInfoForRaceDTO getAveragedWindInfo(RegattaAndRaceIdentifier raceIdentifier, Date from, Date to, long resolutionInMilliseconds, Collection windSourceTypeNames, boolean onlyUpToNewestEvent) { TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier); @@ -1893,6 +1584,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public boolean getPolarResults(RegattaAndRaceIdentifier raceIdentifier) { final boolean result; final TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier); @@ -1914,6 +1606,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public SimulatorResultsDTO getSimulatorResults(LegIdentifier legIdentifier) { if (!getSecurityService() .hasCurrentUserAnyPermission(SecuredDomainType.SIMULATOR.getPermission(DefaultActions.READ))) { @@ -1957,6 +1650,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private SimulatorWindDTO createSimulatorWindDTO(TimedPositionWithSpeed timedPositionWithSpeed) { Position position = timedPositionWithSpeed.getPosition(); @@ -1984,50 +1678,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public void setWind(RegattaAndRaceIdentifier raceIdentifier, WindDTO windDTO) { - DynamicTrackedRace trackedRace = (DynamicTrackedRace) getExistingTrackedRace(raceIdentifier); - if (trackedRace != null) { - getSecurityService().checkCurrentUserUpdatePermission(trackedRace); - Position p = null; - if (windDTO.position != null) { - p = windDTO.position; - } - TimePoint at = null; - if (windDTO.measureTimepoint != null) { - at = new MillisecondsTimePoint(windDTO.measureTimepoint); - } - SpeedWithBearing speedWithBearing = null; - Speed speed = null; - if (windDTO.trueWindSpeedInKnots != null) { - speed = new KnotSpeedImpl(windDTO.trueWindSpeedInKnots); - } else if (windDTO.trueWindSpeedInMetersPerSecond != null) { - speed = new KilometersPerHourSpeedImpl(windDTO.trueWindSpeedInMetersPerSecond * 3600. / 1000.); - } else if (windDTO.dampenedTrueWindSpeedInKnots != null) { - speed = new KnotSpeedImpl(windDTO.dampenedTrueWindSpeedInKnots); - } else if (windDTO.dampenedTrueWindSpeedInMetersPerSecond != null) { - speed = new KilometersPerHourSpeedImpl(windDTO.dampenedTrueWindSpeedInMetersPerSecond * 3600. / 1000.); - } - if (speed != null) { - if (windDTO.trueWindBearingDeg != null) { - speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), new DegreeBearingImpl( - windDTO.trueWindBearingDeg)); - } else if (windDTO.trueWindFromDeg != null) { - speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), new DegreeBearingImpl( - windDTO.trueWindFromDeg).reverse()); - } - } - Wind wind = new WindImpl(p, at, speedWithBearing); - Iterable webWindSources = trackedRace.getWindSources(WindSourceType.WEB); - if (Util.size(webWindSources) == 0) { - // create a new WEB wind source if not available - trackedRace.recordWind(wind, new WindSourceImpl(WindSourceType.WEB)); - } else { - trackedRace.recordWind(wind, webWindSources.iterator().next()); - } - } - } - - @Override + //READ public Map getCompetitorBoats(RegattaAndRaceIdentifier raceIdentifier) { Map result = null; TrackedRace trackedRace = getService().getExistingTrackedRace(raceIdentifier); @@ -2039,6 +1690,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public RaceboardDataDTO getRaceboardData(String regattaName, String raceName, String leaderboardName, String leaderboardGroupName, UUID eventId) { RaceboardDataDTO result = new RaceboardDataDTO(null, false, false, Collections.emptyList(), @@ -2108,6 +1760,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public CompactRaceMapDataDTO getRaceMapData(RegattaAndRaceIdentifier raceIdentifier, Date date, Map fromPerCompetitorIdAsString, Map toPerCompetitorIdAsString, boolean extrapolate, LegIdentifier simulationLegIdentifier, @@ -2147,7 +1800,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return new CompactRaceMapDataDTO(boatPositions, coursePositions, courseSidelines, quickRanks, simulationResultVersion, raceCompetitorIdsAsStrings, estimatedDuration); } - + + //READ private Duration getEstimationForTargetTime(Date time, final TrackedRace trackedRace) { Duration estimatedDuration = null; if (trackedRace != null) { @@ -2161,6 +1815,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public CompactBoatPositionsDTO getBoatPositions(RegattaAndRaceIdentifier raceIdentifier, Map fromPerCompetitorIdAsString, Map toPerCompetitorIdAsString, boolean extrapolate, DetailType detailType, String leaderboardName, String leaderboardGroupName) @@ -2191,6 +1846,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * @return a map where for each competitor participating in the race the list of GPS fixes in increasing * chronological order is provided. The last one is the last position at or before date. */ + //READ private Map> getBoatPositionsInternal(RegattaAndRaceIdentifier raceIdentifier, Map fromPerCompetitorIdAsString, Map toPerCompetitorIdAsString, boolean extrapolate, DetailType detailType, String leaderboardName, String leaderboardGroupName) @@ -2340,21 +1996,25 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private TimePoint quantifyTimePointWithResolution(TimePoint timePoint, long resolutionInMilliseconds) { return new MillisecondsTimePoint(timePoint.asMillis() / resolutionInMilliseconds * resolutionInMilliseconds); } + //READ private SpeedWithBearingDTO createSpeedWithBearingDTO(SpeedWithBearing speedWithBearing) { return new SpeedWithBearingDTO(speedWithBearing.getKnots(), speedWithBearing .getBearing().getDegrees()); } + //READ private GPSFixDTOWithSpeedWindTackAndLegType createGPSFixDTO(GPSFix fix, SpeedWithBearing speedWithBearing, WindDTO windDTO, Tack tack, LegType legType, boolean extrapolated, Double detailValue) { return new GPSFixDTOWithSpeedWindTackAndLegType(fix.getTimePoint().asDate(), fix.getPosition()==null?null:fix.getPosition(), speedWithBearing==null?null:createSpeedWithBearingDTO(speedWithBearing), windDTO, tack, legType, extrapolated, detailValue); } @Override + //READ public RaceTimesInfoDTO getRaceTimesInfo(RegattaAndRaceIdentifier raceIdentifier) { RaceTimesInfoDTO raceTimesInfo = null; TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier); @@ -2427,6 +2087,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List getRaceTimesInfos(Collection raceIdentifiers) { List raceTimesInfos = new ArrayList(); for (RegattaAndRaceIdentifier raceIdentifier : raceIdentifiers) { @@ -2441,6 +2102,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return raceTimesInfos; } + //READ private List getCourseSidelines(RegattaAndRaceIdentifier raceIdentifier, Date date) { List result = new ArrayList(); final TimePoint dateAsTimePoint; @@ -2467,6 +2129,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public CoursePositionsDTO getCoursePositions(RegattaAndRaceIdentifier raceIdentifier, Date date) { CoursePositionsDTO result = new CoursePositionsDTO(); TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier); @@ -2540,6 +2203,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public RaceCourseDTO getRaceCourse(RegattaAndRaceIdentifier raceIdentifier, Date date) { List waypointDTOs = new ArrayList(); Map controlPointCache = new HashMap<>(); @@ -2589,10 +2253,11 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } } - private interface MarkPositionFinder { + interface MarkPositionFinder { Position find(Mark mark, TimePoint at); } + //READ private ControlPointDTO convertToControlPointDTO(ControlPoint controlPoint, MarkPositionFinder positionFinder, TimePoint timePoint) { ControlPointDTO result; @@ -2611,7 +2276,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } - private ControlPoint getOrCreateControlPoint(ControlPointDTO dto) { + //READ + protected ControlPoint getOrCreateControlPoint(ControlPointDTO dto) { String idAsString = dto.getIdAsString(); if (idAsString == null) { idAsString = UUID.randomUUID().toString(); @@ -2628,36 +2294,12 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } } - /** - * Creates new ControlPoints, if nThe resulting - * list of control points is then passed to {@link Course#update(List, com.sap.sailing.domain.base.DomainFactory)} for - * the course of the race identified by raceIdentifier. - */ - @Override - public void updateRaceCourse(RegattaAndRaceIdentifier raceIdentifier, - List> courseDTO) { - TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier); - if (trackedRace != null) { - getSecurityService().checkCurrentUserUpdatePermission(trackedRace); - Course course = trackedRace.getRace().getCourse(); - List> controlPoints = new ArrayList<>(); - for (Pair waypointDTO : courseDTO) { - controlPoints.add(new Pair<>(getOrCreateControlPoint(waypointDTO.getA()), waypointDTO.getB())); - } - try { - course.update(controlPoints, course.getAssociatedRoles(), course.getOriginatingCourseTemplateIdOrNull(), - baseDomainFactory); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - /** * @param timePoint * null means "live" and is then replaced by "now" minus the tracked race's * {@link TrackedRace#getDelayToLiveInMillis() delay}. */ + //READ public QuickRanksDTO computeQuickRanks(RegattaAndRaceIdentifier raceIdentifier, TimePoint timePoint) throws NoWindException { final List result = new ArrayList<>(); @@ -2688,6 +2330,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return new QuickRanksDTO(result); } + //READ private QuickRanksDTO getQuickRanksWithoutSecuritychecks(RegattaAndRaceIdentifier raceIdentifier, Date date) throws NoWindException { final QuickRanksDTO result; if (date == null) { @@ -2699,18 +2342,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public void setRaceIsKnownToStartUpwind(RegattaAndRaceIdentifier raceIdentifier, boolean raceIsKnownToStartUpwind) { - getSecurityService().checkCurrentUserUpdatePermission(raceIdentifier); - getService().apply(new SetRaceIsKnownToStartUpwind(raceIdentifier, raceIsKnownToStartUpwind)); - } - - @Override - public void setWindSourcesToExclude(RegattaAndRaceIdentifier raceIdentifier, Iterable windSourcesToExclude) { - getSecurityService().checkCurrentUserUpdatePermission(raceIdentifier); - getService().apply(new SetWindSourcesToExclude(raceIdentifier, windSourcesToExclude)); - } - - @Override + //READ public WindInfoForRaceDTO getWindSourcesInfo(RegattaAndRaceIdentifier raceIdentifier) { getSecurityService().checkCurrentUserReadPermission(raceIdentifier); WindInfoForRaceDTO result = null; @@ -2734,44 +2366,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } - @Override - public void removeWind(RegattaAndRaceIdentifier raceIdentifier, WindDTO windDTO) { - DynamicTrackedRace trackedRace = (DynamicTrackedRace) getExistingTrackedRace(raceIdentifier); - if (trackedRace != null) { - getSecurityService().checkCurrentUserUpdatePermission(trackedRace); - Position p = null; - if (windDTO.position != null) { - p = windDTO.position; - } - TimePoint at = null; - if (windDTO.measureTimepoint != null) { - at = new MillisecondsTimePoint(windDTO.measureTimepoint); - } - SpeedWithBearing speedWithBearing = null; - Speed speed = null; - if (windDTO.trueWindSpeedInKnots != null) { - speed = new KnotSpeedImpl(windDTO.trueWindSpeedInKnots); - } else if (windDTO.trueWindSpeedInMetersPerSecond != null) { - speed = new KilometersPerHourSpeedImpl(windDTO.trueWindSpeedInMetersPerSecond * 3600. / 1000.); - } else if (windDTO.dampenedTrueWindSpeedInKnots != null) { - speed = new KnotSpeedImpl(windDTO.dampenedTrueWindSpeedInKnots); - } else if (windDTO.dampenedTrueWindSpeedInMetersPerSecond != null) { - speed = new KilometersPerHourSpeedImpl(windDTO.dampenedTrueWindSpeedInMetersPerSecond * 3600. / 1000.); - } - if (speed != null) { - if (windDTO.trueWindBearingDeg != null) { - speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), new DegreeBearingImpl( - windDTO.trueWindBearingDeg)); - } else if (windDTO.trueWindFromDeg != null) { - speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), new DegreeBearingImpl( - windDTO.trueWindFromDeg).reverse()); - } - } - Wind wind = new WindImpl(p, at, speedWithBearing); - trackedRace.removeWind(wind, trackedRace.getWindSources(WindSourceType.WEB).iterator().next()); - } - } - + //?? protected RacingEventService getService() { try { return racingEventServiceTracker.getInitializedService(0); @@ -2780,6 +2375,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } // grab the service } + //?? protected SharedSailingData getSharedSailingData() { try { return sharedSailingDataTracker.getInitializedService(0); @@ -2788,6 +2384,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } // grab the service } + //?? protected ReplicationService getReplicationService() { try { return replicationServiceTracker.waitForService(0); @@ -2796,6 +2393,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } } + //?? protected SecurityService getSecurityService() { try { return securityServiceTracker.getInitializedService(0); @@ -2805,10 +2403,12 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List getLeaderboardNames() { return getLeaderboardNamesFilteredForCurrentUser(); } + //READ private ArrayList getLeaderboardNamesFilteredForCurrentUser() { final ArrayList result = new ArrayList<>(); getSecurityService().filterObjectsWithPermissionForCurrentUser( @@ -2817,68 +2417,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public LeaderboardType getLeaderboardType(String leaderboardName) { - final LeaderboardType result; - final Leaderboard leaderboard = getService().getLeaderboards().get(leaderboardName); - if (leaderboard != null) { - getSecurityService().checkCurrentUserReadPermission(leaderboard); - result = leaderboard.getLeaderboardType(); - } else { - result = null; - } - return result; - } - - @Override - public StrippedLeaderboardDTOWithSecurity createFlexibleLeaderboard(String leaderboardName, - String leaderboardDisplayName, int[] discardThresholds, ScoringSchemeType scoringSchemeType, - Iterable courseAreaIds) { - return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( - SecuredDomainType.LEADERBOARD, Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName), - leaderboardDisplayName, new Callable() { - @Override - public StrippedLeaderboardDTOWithSecurity call() throws Exception { - return createStrippedLeaderboardDTOWithSecurity( - getService().apply(new CreateFlexibleLeaderboard(leaderboardName, - leaderboardDisplayName, discardThresholds, - baseDomainFactory.createScoringScheme(scoringSchemeType), courseAreaIds)), false, false); - } - }); - } - - @Override - public StrippedLeaderboardDTOWithSecurity createRegattaLeaderboard(RegattaName regattaIdentifier, - String leaderboardDisplayName, - int[] discardThresholds) { - return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( - SecuredDomainType.LEADERBOARD, Leaderboard.getTypeRelativeObjectIdentifier(regattaIdentifier), leaderboardDisplayName, - new Callable() { - @Override - public StrippedLeaderboardDTOWithSecurity call() throws Exception { - return createStrippedLeaderboardDTOWithSecurity(getService().apply(new CreateRegattaLeaderboard( - regattaIdentifier, leaderboardDisplayName, discardThresholds)), false, false); - } - }); - } - - @Override - public StrippedLeaderboardDTOWithSecurity createRegattaLeaderboardWithEliminations(String name, - String displayName, - String fullRegattaLeaderboardName) { - return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( - SecuredDomainType.LEADERBOARD, Leaderboard.getTypeRelativeObjectIdentifier(name), displayName, - new Callable() { - @Override - public StrippedLeaderboardDTOWithSecurity call() throws Exception { - return createStrippedLeaderboardDTOWithSecurity( - getService().apply(new CreateRegattaLeaderboardWithEliminations(name, displayName, - fullRegattaLeaderboardName)), - false, false); - } - }); - } - - @Override + //READ public List getLeaderboardsWithSecurity() { final Map leaderboards = getService().getLeaderboards(); return getSecurityService().mapAndFilterByReadPermissionForCurrentUser( @@ -2887,6 +2426,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public StrippedLeaderboardDTOWithSecurity getLeaderboardWithSecurity(String leaderboardName) { Map leaderboards = getService().getLeaderboards(); StrippedLeaderboardDTOWithSecurity result = null; @@ -2902,6 +2442,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public StrippedLeaderboardDTO getLeaderboard(String leaderboardName) { Map leaderboards = getService().getLeaderboards(); StrippedLeaderboardDTO result = null; @@ -2916,35 +2457,6 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } - @Override - public List getLeaderboardsByRaceAndRegatta(String raceName, RegattaIdentifier regattaIdentifier) { - List results = new ArrayList(); - Map leaderboards = getService().getLeaderboards(); - for (Leaderboard leaderboard : leaderboards.values()) { - if (getSecurityService().hasCurrentUserReadPermission(leaderboard)) { - if (leaderboard instanceof RegattaLeaderboard && ((RegattaLeaderboard) leaderboard).getRegatta() - .getRegattaIdentifier().equals(regattaIdentifier)) { - Iterable races = leaderboard.getRaceColumns(); - for (RaceColumn raceInLeaderboard : races) { - for (Fleet fleet : raceInLeaderboard.getFleets()) { - TrackedRace trackedRace = raceInLeaderboard.getTrackedRace(fleet); - if (getSecurityService().hasCurrentUserReadPermission(trackedRace)) { - if (trackedRace != null) { - RaceDefinition trackedRaceDef = trackedRace.getRace(); - if (trackedRaceDef.getName().equals(raceName)) { - results.add(createStrippedLeaderboardDTO(leaderboard, false, false)); - break; - } - } - } - } - } - } - } - } - return results; - } - /** * Creates a {@link LeaderboardDTO} for leaderboard and fills in the name, race master data * in the form of {@link RaceColumnDTO}s, whether or not there are {@link LeaderboardDTO#hasCarriedPoints carried points} @@ -2953,6 +2465,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * is used for {@link LeaderboardDTO#competitorDisplayNames}.
    * If withGeoLocationData is true the geographical location of all races will be determined. */ + //READ private StrippedLeaderboardDTO createStrippedLeaderboardDTO(Leaderboard leaderboard, boolean withGeoLocationData, boolean withStatisticalData) { StrippedLeaderboardDTO leaderboardDTO = new StrippedLeaderboardDTO(convertToBoatClassDTO(leaderboard.getBoatClass())); fillLeaderboardData(leaderboard, withGeoLocationData, withStatisticalData, leaderboardDTO); @@ -2968,7 +2481,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * If withGeoLocationData is true the geographical location of all races will be * determined. */ - private StrippedLeaderboardDTOWithSecurity createStrippedLeaderboardDTOWithSecurity(Leaderboard leaderboard, + //READ + protected StrippedLeaderboardDTOWithSecurity createStrippedLeaderboardDTOWithSecurity(Leaderboard leaderboard, boolean withGeoLocationData, boolean withStatisticalData) { StrippedLeaderboardDTOWithSecurity leaderboardDTO = new StrippedLeaderboardDTOWithSecurity( convertToBoatClassDTO(leaderboard.getBoatClass())); @@ -2977,6 +2491,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return leaderboardDTO; } + //READ private void fillLeaderboardData(Leaderboard leaderboard, boolean withGeoLocationData, boolean withStatisticalData, StrippedLeaderboardDTO leaderboardDTO) { TimePoint startOfLatestRace = null; @@ -3042,122 +2557,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public StrippedLeaderboardDTOWithSecurity updateLeaderboard(String leaderboardName, String newLeaderboardName, - String newLeaderboardDisplayName, int[] newDiscardingThresholds, Iterable newCourseAreaIds) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - Leaderboard updatedLeaderboard = getService().apply( - new UpdateLeaderboard(leaderboardName, newLeaderboardName, newLeaderboardDisplayName, newDiscardingThresholds, newCourseAreaIds)); - return createStrippedLeaderboardDTOWithSecurity(updatedLeaderboard, false, false); - } - - @Override - public void removeLeaderboards(Collection leaderboardNames) { - for (String leaderboardName : leaderboardNames) { - removeLeaderboard(leaderboardName); - } - } - - @Override - public void removeLeaderboard(String leaderboardName) { - Leaderboard leaderBoard = getService().getLeaderboardByName(leaderboardName); - if (leaderBoard != null) { - getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(leaderBoard, new Action() { - @Override - public void run() throws Exception { - getService().apply(new RemoveLeaderboard(leaderboardName)); - } - }); - } - } - - @Override - public void renameLeaderboard(String leaderboardName, String newLeaderboardName) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - getService().apply(new RenameLeaderboard(leaderboardName, newLeaderboardName)); - } - - @Override - public void addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - getService().apply(new AddColumnToLeaderboard(columnName, leaderboardName, medalRace)); - } - - @Override - public void addColumnsToLeaderboard(String leaderboardName, List> columnsToAdd) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - for(com.sap.sse.common.Util.Pair columnToAdd: columnsToAdd) { - getService().apply(new AddColumnToLeaderboard(columnToAdd.getA(), leaderboardName, columnToAdd.getB())); - } - } - - @Override - public void removeLeaderboardColumns(String leaderboardName, List columnsToRemove) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - for (String columnToRemove : columnsToRemove) { - getService().apply(new RemoveLeaderboardColumn(columnToRemove, leaderboardName)); - } - } - - @Override - public void removeLeaderboardColumn(String leaderboardName, String columnName) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - getService().apply(new RemoveLeaderboardColumn(columnName, leaderboardName)); - } - - @Override - public void renameLeaderboardColumn(String leaderboardName, String oldColumnName, String newColumnName) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - getService().apply(new RenameLeaderboardColumn(leaderboardName, oldColumnName, newColumnName)); - } - - @Override - public void updateLeaderboardColumnFactor(String leaderboardName, String columnName, Double newFactor) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - getService().apply(new UpdateLeaderboardColumnFactor(leaderboardName, columnName, newFactor)); - } - - @Override - public void suppressCompetitorInLeaderboard(String leaderboardName, String competitorIdAsString, boolean suppressed) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - getService().apply(new SetSuppressedFlagForCompetitorInLeaderboard(leaderboardName, competitorIdAsString, suppressed)); - } - - @Override - public boolean connectTrackedRaceToLeaderboardColumn(String leaderboardName, String raceColumnName, - String fleetName, RegattaAndRaceIdentifier raceIdentifier) { - final Subject subject = SecurityUtils.getSubject(); - subject.checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - Object principal = subject.getPrincipal(); - if (principal != null) { - logger.info(String.format("%s linked race column %s %s (%s) with tracked race %s.", principal.toString(), - leaderboardName, raceColumnName, fleetName, raceIdentifier.getRaceName())); - } else { - logger.info(String.format("Linked race column %s %s (%s) with tracked race %s.", leaderboardName, raceColumnName, fleetName, - raceIdentifier.getRaceName())); - } - return getService().apply(new ConnectTrackedRaceToLeaderboardColumn(leaderboardName, raceColumnName, fleetName, raceIdentifier)); - } - - @Override + //READ public Map getRegattaAndRaceNameOfTrackedRaceConnectedToLeaderboardColumn(String leaderboardName, String raceColumnName) { SecurityUtils.getSubject().checkPermission( SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.READ, @@ -3181,162 +2581,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName, String fleetName) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - getService().apply(new DisconnectLeaderboardColumnFromTrackedRace(leaderboardName, raceColumnName, fleetName)); - } - - @Override - public void updateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Double carriedPoints) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - getService().apply(new UpdateLeaderboardCarryValue(leaderboardName, competitorIdAsString, carriedPoints)); - } - - @Override - public com.sap.sse.common.Util.Triple updateLeaderboardMaxPointsReason(String leaderboardName, String competitorIdAsString, String raceColumnName, - MaxPointsReason maxPointsReason, Date date) throws NoWindException { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - return getService().apply( - new UpdateLeaderboardMaxPointsReason(leaderboardName, raceColumnName, competitorIdAsString, - maxPointsReason, new MillisecondsTimePoint(date))); - } - - @Override - public com.sap.sse.common.Util.Triple updateLeaderboardScoreCorrection(String leaderboardName, - String competitorIdAsString, String columnName, Double correctedScore, Date date) throws NoWindException { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - return getService().apply( - new UpdateLeaderboardScoreCorrection(leaderboardName, columnName, competitorIdAsString, correctedScore, - new MillisecondsTimePoint(date))); - } - - @Override - public void updateLeaderboardScoreCorrectionMetadata(String leaderboardName, Date timePointOfLastCorrectionValidity, String comment) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - getService().apply( - new UpdateLeaderboardScoreCorrectionMetadata(leaderboardName, - timePointOfLastCorrectionValidity == null ? null : new MillisecondsTimePoint(timePointOfLastCorrectionValidity), - comment)); - } - - @Override - public void updateLeaderboardScoreCorrectionsAndMaxPointsReasons(BulkScoreCorrectionDTO updates) throws NoWindException { - SecurityUtils.getSubject() - .checkPermission(SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier( - DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(updates.getLeaderboardName()))); - Date dateForResults = new Date(); // we don't care about the result date/time here; use current date as default - for (Map.Entry> e : updates.getScoreUpdatesForRaceColumnByCompetitorIdAsString().entrySet()) { - for (Map.Entry raceColumnNameAndCorrectedScore : e.getValue().entrySet()) { - updateLeaderboardScoreCorrection(updates.getLeaderboardName(), e.getKey(), - raceColumnNameAndCorrectedScore.getKey(), raceColumnNameAndCorrectedScore.getValue(), dateForResults); - } - } - for (Map.Entry> e : updates.getMaxPointsUpdatesForRaceColumnByCompetitorIdAsString().entrySet()) { - for (Map.Entry raceColumnNameAndNewMaxPointsReason : e.getValue().entrySet()) { - updateLeaderboardMaxPointsReason(updates.getLeaderboardName(), e.getKey(), - raceColumnNameAndNewMaxPointsReason.getKey(), raceColumnNameAndNewMaxPointsReason.getValue(), dateForResults); - } - } - } - - @Override - public void updateCompetitorDisplayNameInLeaderboard(String leaderboardName, String competitorIdAsString, String displayName) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - getService().apply(new UpdateCompetitorDisplayNameInLeaderboard(leaderboardName, competitorIdAsString, displayName)); - } - - @Override - public void moveLeaderboardColumnUp(String leaderboardName, String columnName) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - getService().apply(new MoveLeaderboardColumnUp(leaderboardName, columnName)); - } - - @Override - public void moveLeaderboardColumnDown(String leaderboardName, String columnName) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - getService().apply(new MoveLeaderboardColumnDown(leaderboardName, columnName)); - } - - @Override - public void updateIsMedalRace(String leaderboardName, String columnName, boolean isMedalRace) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); - getService().apply(new UpdateIsMedalRace(leaderboardName, columnName, isMedalRace)); - } - - @Override - public void updateRaceDelayToLive(RegattaAndRaceIdentifier regattaAndRaceIdentifier, long delayToLiveInMs) { - getSecurityService().checkCurrentUserUpdatePermission(regattaAndRaceIdentifier); - getService().apply(new UpdateRaceDelayToLive(regattaAndRaceIdentifier, delayToLiveInMs)); - } - - @Override - public void updateRacesDelayToLive(List regattaAndRaceIdentifiers, long delayToLiveInMs) { - for (RegattaAndRaceIdentifier regattaAndRaceIdentifier : regattaAndRaceIdentifiers) { - updateRaceDelayToLive(regattaAndRaceIdentifier, delayToLiveInMs); - } - } - - @Override - public boolean existsSwissTimingConfigurationForCurrentUser(String jsonUrl) - throws Exception, UnauthorizedException { - boolean found = false; - final String currentUserName = getSecurityService().getCurrentUser().getName(); - for (final SwissTimingConfigurationWithSecurityDTO dto : getPreviousSwissTimingConfigurations()) { - if (dto.getJsonUrl().equals(jsonUrl) && currentUserName.equals(dto.getCreatorName())) { - found = true; - break; - } - } - return found; - } - - @Override - public boolean existsSwissTimingArchiveConfigurationForCurrentUser(String jsonUrl) - throws Exception, UnauthorizedException { - boolean found = false; - final String currentUserName = getSecurityService().getCurrentUser().getName(); - for (final SwissTimingArchiveConfigurationWithSecurityDTO dto : getPreviousSwissTimingArchiveConfigurations()) { - if (dto.getJsonUrl().equals(jsonUrl) && currentUserName.equals(dto.getCreatorName())) { - found = true; - break; - } - } - return found; - } - - @Override - public boolean existsTracTracConfigurationForCurrentUser(String jsonUrl) throws Exception, UnauthorizedException { - boolean found = false; - final String currentUserName = getSecurityService().getCurrentUser().getName(); - for (final TracTracConfigurationWithSecurityDTO dto : getPreviousTracTracConfigurations()) { - if (dto.getJsonUrl().equals(jsonUrl) && currentUserName.equals(dto.getCreatorName())) { - found = true; - break; - } - } - return found; - } - - @Override + //READ public List getPreviousSwissTimingConfigurations() { Iterable configs = swissTimingAdapterPersistence.getSwissTimingConfigurations(); return getSecurityService().mapAndFilterByReadPermissionForCurrentUser(configs, @@ -3351,47 +2596,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public void createSwissTimingConfiguration(String configName, String jsonURL, String hostname, Integer port, - String updateURL, String updateUsername, String updatePassword) throws Exception { - if (!jsonURL.equalsIgnoreCase("test")) { - if (existsSwissTimingConfigurationForCurrentUser(jsonURL)) { - throw new RuntimeException("A Configuration for the current user with this json URL already exists."); - } - final String currentUserName = getSecurityService().getCurrentUser().getName(); - final TypeRelativeObjectIdentifier identifier = SwissTimingConfiguration.getTypeRelativeObjectIdentifier(jsonURL, currentUserName); - getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( - SecuredDomainType.SWISS_TIMING_ACCOUNT, - identifier, configName, - () -> swissTimingAdapterPersistence - .createSwissTimingConfiguration( - swissTimingFactory.createSwissTimingConfiguration(configName, - jsonURL, hostname, port, updateURL, updateUsername, updatePassword, - currentUserName))); - } - } - - @Override - public void deleteSwissTimingConfigurations( - final Collection configurations) { - for (SwissTimingConfigurationWithSecurityDTO dto : configurations) { - getSecurityService().checkCurrentUserDeletePermission(dto); - getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(dto, - () -> swissTimingAdapterPersistence.deleteSwissTimingConfiguration(dto.getCreatorName(), - dto.getJsonUrl())); - } - } - - @Override - public void updateSwissTimingConfiguration(SwissTimingConfigurationWithSecurityDTO configuration) - throws Exception { - getSecurityService().checkCurrentUserUpdatePermission(configuration); - swissTimingAdapterPersistence.updateSwissTimingConfiguration(swissTimingFactory.createSwissTimingConfiguration( - configuration.getName(), configuration.getJsonUrl(), configuration.getHostname(), - configuration.getPort(), configuration.getUpdateURL(), configuration.getUpdateUsername(), - configuration.getUpdatePassword(), configuration.getCreatorName())); - } - - @Override + //READ public SwissTimingEventRecordDTO getRacesOfSwissTimingEvent(String eventJsonURL) throws UnknownHostException, IOException, InterruptedException, ParseException { SwissTimingEventRecordDTO result = null; @@ -3423,56 +2628,25 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } - private RaceLogStore getRaceLogStore() { + //?? + protected RaceLogStore getRaceLogStore() { return MongoRaceLogStoreFactory.INSTANCE.getMongoRaceLogStore(mongoObjectFactory, domainObjectFactory); } - private RegattaLogStore getRegattaLogStore() { + //?? + protected RegattaLogStore getRegattaLogStore() { return MongoRegattaLogStoreFactory.INSTANCE.getMongoRegattaLogStore( mongoObjectFactory, domainObjectFactory); } - @Override - public void trackWithSwissTiming(RegattaIdentifier regattaToAddTo, Iterable rrs, - String hostname, int port, boolean trackWind, final boolean correctWindByDeclination, - boolean useInternalMarkPassingAlgorithm, String updateURL, String updateUsername, String updatePassword, - String eventName, String manage2SailEventUrl) throws InterruptedException, ParseException, Exception { - logger.info( - "tracWithSwissTiming for regatta " + regattaToAddTo + " for race records " + rrs - + " with hostname " + hostname + " and port " + port); - Map cachedRegattaEntriesLists = new HashMap(); - for (SwissTimingRaceRecordDTO rr : rrs) { - BoatClass boatClass = getBaseDomainFactory().getOrCreateBoatClass(rr.boatClass); - String raceDescription = rr.regattaName != null ? rr.regattaName : ""; - raceDescription += rr.seriesName != null ? "/" + rr.seriesName : ""; - raceDescription += raceDescription.length() > 0 ? "/" + rr.getName() : rr.getName(); - // try to find a cached entry list for the regatta - RegattaResults regattaResults = cachedRegattaEntriesLists.get(rr.xrrEntriesUrl); - if (regattaResults == null && rr.xrrEntriesUrl != null) { - regattaResults = getSwissTimingAdapter().readRegattaEntryListFromXrrUrl(rr.xrrEntriesUrl); - if (regattaResults != null) { - cachedRegattaEntriesLists.put(rr.xrrEntriesUrl, regattaResults); - } - } - StartList startList = null; - if (regattaResults != null) { - startList = getSwissTimingAdapter().readStartListForRace(rr.raceId, regattaResults); - } - // now read the entry list for the race from the result - getSwissTimingAdapter().addSwissTimingRace(getService(), regattaToAddTo, - rr.raceId, rr.getName(), raceDescription, boatClass, hostname, port, startList, - getRaceLogStore(), getRegattaLogStore(), - RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS, useInternalMarkPassingAlgorithm, trackWind, - correctWindByDeclination, updateURL, updateUsername, updatePassword, eventName, manage2SailEventUrl); - } - } - + //?? protected SwissTimingReplayService getSwissTimingReplayService() { return swissTimingReplayService; } @Override + //READ public List listSwissTiminigReplayRaces(String swissTimingUrl) { List replayRaces = getSwissTimingReplayService().listReplayRaces(swissTimingUrl); List result = new ArrayList(replayRaces.size()); @@ -3485,6 +2659,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public void replaySwissTimingRace(RegattaIdentifier regattaIdentifier, Iterable replayRaceDTOs, boolean trackWind, boolean correctWindByDeclination, boolean useInternalMarkPassingAlgorithm) { logger.info("replaySwissTimingRace for regatta "+regattaIdentifier+" for races "+replayRaceDTOs); @@ -3513,21 +2688,10 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } } - @Override - public String[] getCountryCodes() { - List countryCodes = new ArrayList(); - for (CountryCode cc : countryCodeFactory.getAll()) { - if (cc.getThreeLetterIOCCode() != null && !cc.getThreeLetterIOCCode().equals("")) { - countryCodes.add(cc.getThreeLetterIOCCode()); - } - } - Collections.sort(countryCodes); - return countryCodes.toArray(new String[0]); - } - /** * Finds a competitor in a sequence of competitors that has an {@link Competitor#getId()} equal to id. */ + //READ private Competitor getCompetitorByIdAsString(Iterable competitors, String idAsString) { for (Competitor c : competitors) { if (c.getId().toString().equals(idAsString)) { @@ -3537,6 +2701,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return null; } + //READ private Double getCompetitorRaceDataEntry(DetailType dataType, TrackedRace trackedRace, Competitor competitor, TimePoint timePoint, String leaderboardGroupName, String leaderboardName, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) throws NoWindException { @@ -3915,21 +3080,25 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } } + //READ private Double getBravoDoubleValue(BiFunction, TimePoint, Double> valueGetter, TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) { return getBravoValue(valueGetter, Function.identity(), trackedRace, competitor, timePoint); } + //READ private Double getBravoBearingInDegrees(BiFunction, TimePoint, Bearing> valueGetter, TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) { return getBravoValue(valueGetter, Bearing::getDegrees, trackedRace, competitor, timePoint); } + //READ private Double getBravoDistanceInMeters(BiFunction, TimePoint, Distance> valueGetter, TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) { return getBravoValue(valueGetter, Distance::getMeters, trackedRace, competitor, timePoint); } + //READ private Double getBravoValue(BiFunction, TimePoint, T> valueGetter, Function mapperToDouble, TrackedRace trackedRace, Competitor competitor, TimePoint timePoint) { @@ -3946,6 +3115,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public CompetitorsRaceDataDTO getCompetitorsRaceData(RegattaAndRaceIdentifier race, List competitors, Date from, Date to, final long stepSizeInMillis, final DetailType detailType, final String leaderboardGroupName, final String leaderboardName) throws NoWindException { CompetitorsRaceDataDTO result = null; @@ -4034,6 +3204,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List, List>> getLeaderboardDataEntriesForAllRaceColumns(String leaderboardName, Date date, DetailType detailType) throws Exception { List, List>> result = new ArrayList<>(); @@ -4087,6 +3258,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List> getLeaderboardsNamesOfMetaLeaderboard( String metaLeaderboardName) { Leaderboard leaderboard = getService().getLeaderboardByName(metaLeaderboardName); @@ -4136,6 +3308,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Map> getDouglasPoints( RegattaAndRaceIdentifier raceIdentifier, Map competitorTimeRanges, double meters) throws NoWindException { @@ -4177,6 +3350,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private GPSFixDTOWithSpeedWindTackAndLegType createDouglasPeuckerGPSFixDTO(TrackedRace trackedRace, Competitor competitor, GPSFix fix, SpeedWithBearing speedWithBearing) throws NoWindException { Tack tack = trackedRace.getTack(competitor, fix.getTimePoint()); @@ -4192,6 +3366,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Map> getManeuvers(RegattaAndRaceIdentifier raceIdentifier, Map competitorTimeRanges) throws NoWindException { final Map> result = new HashMap<>(); @@ -4229,6 +3404,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private List createManeuverDTOsForCompetitor(Iterable maneuvers, TrackedRace trackedRace, Competitor competitor) { final List result = new ArrayList(); for (Maneuver maneuver : maneuvers) { @@ -4261,6 +3437,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public RaceDefinition getRace(RegattaAndRaceIdentifier raceIdentifier) { Regatta regatta = getService().getRegattaByName(raceIdentifier.getRegattaName()); RaceDefinition race = getRaceByName(regatta, raceIdentifier.getRaceName()); @@ -4268,6 +3445,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public DynamicTrackedRace getTrackedRace(RegattaAndRaceIdentifier regattaNameAndRaceName) { Regatta regatta = getService().getRegattaByName(regattaNameAndRaceName.getRegattaName()); RaceDefinition race = getRaceByName(regatta, regattaNameAndRaceName.getRaceName()); @@ -4277,6 +3455,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public TrackedRace getExistingTrackedRace(RegattaAndRaceIdentifier regattaNameAndRaceName) { final DynamicTrackedRace existingTrackedRace = getService().getExistingTrackedRace(regattaNameAndRaceName); getSecurityService().checkCurrentUserReadPermission(existingTrackedRace); @@ -4284,6 +3463,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Regatta getRegatta(RegattaName regattaName) { final Regatta regattaByName = getService().getRegattaByName(regattaName.getRegattaName()); getSecurityService().checkCurrentUserReadPermission(regattaByName); @@ -4296,6 +3476,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * through the HTTP server. */ @Override + //?? public ServletContext getServletContext() { return new DelegatingServletContext(super.getServletContext()); } @@ -4304,12 +3485,14 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet /** * Override of function to prevent exception "Blocked request without GWT permutation header (XSRF attack?)" when testing the GWT sites */ + //?? protected void checkPermutationStrongName() throws SecurityException { //Override to prevent exception "Blocked request without GWT permutation header (XSRF attack?)" when testing the GWT sites return; } @Override + //READ public List getLeaderboardGroups(boolean withGeoLocationData) { final Map leaderboardGroups = getService().getLeaderboardGroups(); return getSecurityService().mapAndFilterByReadPermissionForCurrentUser( @@ -4318,13 +3501,15 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public LeaderboardGroupDTO getLeaderboardGroupByName(String groupName, boolean withGeoLocationData) { final LeaderboardGroup leaderboardGroupByName = getService().getLeaderboardGroupByName(groupName); getSecurityService().checkCurrentUserReadPermission(leaderboardGroupByName); return leaderboardGroupByName == null ? null : convertToLeaderboardGroupDTO(leaderboardGroupByName, withGeoLocationData, false); } - - private LeaderboardGroupDTO convertToLeaderboardGroupDTO(final LeaderboardGroup leaderboardGroup, + + //READ + protected LeaderboardGroupDTO convertToLeaderboardGroupDTO(final LeaderboardGroup leaderboardGroup, final boolean withGeoLocationData, final boolean withStatisticalData) { final LeaderboardGroupDTO groupDTO = new LeaderboardGroupDTO(leaderboardGroup.getId(), leaderboardGroup.getName(), leaderboardGroup.getDisplayName(), leaderboardGroup.getDescription()); @@ -4350,78 +3535,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet @Override - public void renameLeaderboardGroup(String oldName, String newName) { - final LeaderboardGroup leaderboardGroupByName = getService().getLeaderboardGroupByName(oldName); - getSecurityService().checkCurrentUserUpdatePermission(leaderboardGroupByName); - getService().apply(new RenameLeaderboardGroup(oldName, newName)); - } - - @Override - public void removeLeaderboardGroups(Set groupNames) { - for (String groupName : groupNames) { - removeLeaderboardGroup(groupName); - } - } - - private void removeLeaderboardGroup(String groupName) { - LeaderboardGroup group = getService().getLeaderboardGroupByName(groupName); - if (group != null) { - if (group.getOverallLeaderboard() != null) { - removeLeaderboard(group.getOverallLeaderboard().getName()); - } - - getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(group, new Action() { - @Override - public void run() throws Exception { - getService().apply(new RemoveLeaderboardGroup(groupName)); - } - }); - } - } - - @Override - public LeaderboardGroupDTO createLeaderboardGroup(String groupName, String description, - String displayName, - boolean displayGroupsInReverseOrder, - int[] overallLeaderboardDiscardThresholds, ScoringSchemeType overallLeaderboardScoringSchemeType) { - List leaderBoards = new ArrayList<>(); - - return doCreateLeaderboardGroup(groupName, description, displayName, - displayGroupsInReverseOrder, overallLeaderboardDiscardThresholds, overallLeaderboardScoringSchemeType, - leaderBoards); - } - - private LeaderboardGroupDTO doCreateLeaderboardGroup(String groupName, String description, - String displayName, boolean displayGroupsInReverseOrder, int[] overallLeaderboardDiscardThresholds, - ScoringSchemeType overallLeaderboardScoringSchemeType, List leaderBoards) { - UUID newLeaderboardGroupId = UUID.randomUUID(); - return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( - SecuredDomainType.LEADERBOARD_GROUP, LeaderboardGroupImpl.getTypeRelativeObjectIdentifier(newLeaderboardGroupId), - displayName, new Callable() { - @Override - public LeaderboardGroupDTO call() throws Exception { - CreateLeaderboardGroup createLeaderboardGroupOp = new CreateLeaderboardGroup( - newLeaderboardGroupId, groupName, description, displayName, displayGroupsInReverseOrder, - leaderBoards, overallLeaderboardDiscardThresholds, - overallLeaderboardScoringSchemeType); - return convertToLeaderboardGroupDTO(getService().apply(createLeaderboardGroupOp), false, false); - } - }); - } - - @Override - public void updateLeaderboardGroup(UUID leaderboardGroupId, String oldName, String newName, String newDescription, String newDisplayName, - List leaderboardNames, int[] overallLeaderboardDiscardThresholds, ScoringSchemeType overallLeaderboardScoringSchemeType) { - SecurityUtils.getSubject() - .checkPermission(SecuredDomainType.LEADERBOARD_GROUP.getStringPermissionForTypeRelativeIdentifier( - DefaultActions.UPDATE, - LeaderboardGroupImpl.getTypeRelativeObjectIdentifier(leaderboardGroupId))); - getService().apply( - new UpdateLeaderboardGroup(oldName, newName, newDescription, newDisplayName, - leaderboardNames, overallLeaderboardDiscardThresholds, overallLeaderboardScoringSchemeType)); - } - - @Override + //READ public ReplicationStateDTO getReplicaInfo() { getSecurityService().checkCurrentUserServerPermission(ServerActions.READ_REPLICATOR); ReplicationService service = getReplicationService(); @@ -4456,11 +3570,13 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * other {@link Replicable}s such as the {@link SecurityService} we don't care. */ @Override + //READ public String[] getReplicableIdsAsStringThatShallLeadToWarningAboutInstanceBeingReplica() { return new String[] { getService().getId().toString() }; } @Override + //READ public void startReplicatingFromMaster(String messagingHost, String masterHostName, String exchangeName, int servletPort, int messagingPort, String usernameOrNull, String passwordOrNull) throws IOException, ClassNotFoundException, InterruptedException { @@ -4482,6 +3598,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List getEvents() throws MalformedURLException { return getSecurityService().mapAndFilterByReadPermissionForCurrentUser( getService().getAllEvents(), event -> { @@ -4501,16 +3618,19 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * to http://sapsailing.com. * @throws MalformedURLException */ + //READ private URL getRequestBaseURL() throws MalformedURLException { final URL url = new URL(getThreadLocalRequest().getRequestURL().toString()); final URL baseURL = getBaseURL(url); return baseURL; } + //READ private URL getBaseURL(URL url) throws MalformedURLException { return new URL(url.getProtocol(), url.getHost(), url.getPort(), /* file */ ""); } + //READ private RemoteSailingServerReferenceDTO createRemoteSailingServerReferenceDTO( final RemoteSailingServerReference serverRef, final com.sap.sse.common.Util.Pair, Exception> eventsOrException) { @@ -4531,6 +3651,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return sailingServerDTO; } + //READ private Iterable convertToEventDTOs(Iterable events) { List result = new ArrayList<>(); for (EventBase event : events) { @@ -4541,61 +3662,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public EventDTO updateEvent(UUID eventId, String eventName, String eventDescription, Date startDate, Date endDate, - VenueDTO venue, boolean isPublic, Iterable leaderboardGroupIds, String officialWebsiteURLString, String baseURLAsString, - Map sailorsInfoWebsiteURLsByLocaleName, Iterable images, Iterable videos, - Iterable windFinderReviewedSpotCollectionIds) throws MalformedURLException, UnauthorizedException { - if (SecurityUtils.getSubject().isPermitted(SecuredDomainType.EVENT.getStringPermissionForTypeRelativeIdentifier( - DefaultActions.UPDATE, EventBaseImpl.getTypeRelativeObjectIdentifier(eventId)))) { - TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null; - TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; - URL officialWebsiteURL = officialWebsiteURLString != null ? new URL(officialWebsiteURLString) : null; - URL baseURL = baseURLAsString != null ? new URL(baseURLAsString) : null; - Map sailorsInfoWebsiteURLs = convertToLocalesAndUrls(sailorsInfoWebsiteURLsByLocaleName); - List eventImages = convertToImages(images); - List eventVideos = convertToVideos(videos); - getService().apply( - new UpdateEvent(eventId, eventName, eventDescription, startTimePoint, endTimePoint, venue.getName(), - isPublic, leaderboardGroupIds, officialWebsiteURL, baseURL, sailorsInfoWebsiteURLs, eventImages, - eventVideos, windFinderReviewedSpotCollectionIds)); - return getEventById(eventId, false); - } - throw new UnauthorizedException("You are not permitted to edit event " + eventId); - } - - @Override - public EventDTO createEvent(String eventName, String eventDescription, Date startDate, Date endDate, String venue, - boolean isPublic, List courseAreaNames, String officialWebsiteURLAsString, String baseURLAsString, - Map sailorsInfoWebsiteURLsByLocaleName, Iterable images, Iterable videos, - Iterable leaderboardGroupIds) - throws MalformedURLException, UnauthorizedException { - final UUID eventUuid = UUID.randomUUID(); - - return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( - SecuredDomainType.EVENT, EventBaseImpl.getTypeRelativeObjectIdentifier(eventUuid), - eventName, new Callable() { - @Override - public EventDTO call() throws Exception { - TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null; - TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; - URL officialWebsiteURL = officialWebsiteURLAsString != null - ? new URL(officialWebsiteURLAsString) - : null; - URL baseURL = baseURLAsString != null ? new URL(baseURLAsString) : null; - Map sailorsInfoWebsiteURLs = convertToLocalesAndUrls( - sailorsInfoWebsiteURLsByLocaleName); - List eventImages = convertToImages(images); - List eventVideos = convertToVideos(videos); - getService().apply(new CreateEvent(eventName, eventDescription, startTimePoint, endTimePoint, - venue, isPublic, eventUuid, officialWebsiteURL, baseURL, sailorsInfoWebsiteURLs, - eventImages, eventVideos, leaderboardGroupIds)); - createCourseAreas(eventUuid, courseAreaNames.toArray(new String[courseAreaNames.size()])); - return getEventById(eventUuid, false); - } - }); - } - - @Override + //READ public Pair resolveImageDimensions(String imageUrlAsString) throws Exception { final Pair imageDimensions; if (imageUrlAsString != null && !imageUrlAsString.isEmpty()) { @@ -4607,74 +3674,11 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return imageDimensions; } - @Override - public void createCourseAreas(UUID eventId, String[] courseAreaNames) { - getSecurityService().checkCurrentUserUpdatePermission(getService().getEvent(eventId)); - final UUID[] courseAreaIDs = new UUID[courseAreaNames.length]; - for (int i=0; i eventIds) throws UnauthorizedException { - for (UUID eventId : eventIds) { - removeEvent(eventId); - } - } - - @Override - public void removeEvent(UUID eventId) throws UnauthorizedException { - Event event = getService().getEvent(eventId); - if (event != null) { - getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(event, new Action() { - @Override - public void run() throws Exception { - getService().apply(new RemoveEvent(eventId)); - } - }); - } - } - - @Override - public void renameEvent(UUID eventId, String newName) throws UnauthorizedException { - if (SecurityUtils.getSubject().isPermitted(SecuredDomainType.EVENT.getStringPermissionForTypeRelativeIdentifier( - DefaultActions.UPDATE, EventBaseImpl.getTypeRelativeObjectIdentifier(eventId)))) { - getService().apply(new RenameEvent(eventId, newName)); - } else { - throw new UnauthorizedException("You are not permitted to edit event " + eventId); - } - } - - @Override - public EventDTO getEventById(UUID id, boolean withStatisticalData) throws MalformedURLException, UnauthorizedException { - EventDTO result = null; - Event event = getService().getEvent(id); - if (event != null) { - if (SecurityUtils.getSubject() - .isPermitted(SecuredDomainType.EVENT.getStringPermissionForObject(DefaultActions.READ, event))) { - result = convertToEventDTO(event, withStatisticalData); - result.setBaseURL(getEventBaseURLFromEventOrRequest(event)); - result.setIsOnRemoteServer(false); - } else { - throw new UnauthorizedException("You are not permitted to view event " + id); - } - } - return result; - - } - - private String getEventBaseURLFromEventOrRequest(Event event) throws MalformedURLException { + //READ + protected String getEventBaseURLFromEventOrRequest(Event event) throws MalformedURLException { return event.getBaseURL() == null ? getRequestBaseURL().toString() : event.getBaseURL().toString(); } - + //READ private EventBaseDTO convertToEventDTO(EventBase event) { final EventBaseDTO eventDTO; if (event == null) { @@ -4692,12 +3696,14 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return eventDTO; } + //READ private LeaderboardGroupBaseDTO convertToLeaderboardGroupBaseDTO(LeaderboardGroupBase leaderboardGroupBase) { return new LeaderboardGroupBaseDTO(leaderboardGroupBase.getId(), leaderboardGroupBase.getName(), leaderboardGroupBase.getDescription(), leaderboardGroupBase.getDisplayName(), leaderboardGroupBase.hasOverallLeaderboard()); } + //READ private void copyEventBaseFieldsToDTO(EventBase event, EventBaseDTO eventDTO) { eventDTO.venue = new VenueDTO(); eventDTO.venue.setName(event.getVenue() != null ? event.getVenue().getName() : null); @@ -4720,7 +3726,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } } - private List convertToImages(Iterable images) throws MalformedURLException { + //READ + protected List convertToImages(Iterable images) throws MalformedURLException { List eventImages = new ArrayList(); for (ImageDTO image : images) { try { @@ -4732,7 +3739,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return eventImages; } - private List convertToVideos(Iterable videos) throws MalformedURLException { + //READ + protected List convertToVideos(Iterable videos) throws MalformedURLException { List eventVideos = new ArrayList(); for (VideoDTO video : videos) { try { @@ -4744,7 +3752,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return eventVideos; } - private Map convertToLocalesAndUrls(Map sailorsInfoWebsiteURLsByLocaleName) { + //READ + protected Map convertToLocalesAndUrls(Map sailorsInfoWebsiteURLsByLocaleName) { Map eventURLs = new HashMap<>(); for (Map.Entry entry : sailorsInfoWebsiteURLsByLocaleName.entrySet()) { if (entry.getValue() != null) { @@ -4758,6 +3767,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return eventURLs; } + //READ private ImageDescriptor convertToImage(ImageDTO image) throws MalformedURLException { ImageDescriptor result = new ImageDescriptorImpl(new URL(image.getSourceRef()), new MillisecondsTimePoint(image.getCreatedAtDate())); result.setCopyright(image.getCopyright()); @@ -4792,6 +3802,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private ImageDTO convertToImageDTO(ImageDescriptor image) { ImageDTO result = new ImageDTO(image.getURL().toString(), image.getCreatedAtDate() != null ? image.getCreatedAtDate().asDate() : null); result.setCopyright(image.getCopyright()); @@ -4808,6 +3819,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private VideoDTO convertToVideoDTO(VideoDescriptor video) { VideoDTO result = new VideoDTO(video.getURL().toString(), video.getMimeType(), video.getCreatedAtDate() != null ? video.getCreatedAtDate().asDate() : null); @@ -4825,6 +3837,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private Locale toLocale(String localeName) { if(localeName == null || localeName.isEmpty()) { return null; @@ -4832,6 +3845,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return Locale.forLanguageTag(localeName); } + //READ private String toLocaleName(Locale locale) { if(locale == null) { return null; @@ -4839,7 +3853,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return locale.toString(); } - private EventDTO convertToEventDTO(Event event, boolean withStatisticalData) { + //READ + protected EventDTO convertToEventDTO(Event event, boolean withStatisticalData) { EventDTO eventDTO = new EventDTO(event.getName()); copyEventBaseFieldsToDTO(event, eventDTO); eventDTO.venue.setCourseAreas(new ArrayList()); @@ -4860,6 +3875,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return eventDTO; } + //READ private CourseAreaDTO convertToCourseAreaDTO(CourseArea courseArea) { CourseAreaDTO courseAreaDTO = new CourseAreaDTO(courseArea.getName()); courseAreaDTO.id = courseArea.getId(); @@ -4868,6 +3884,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet /** for backward compatibility with the regatta overview */ @Override + //READ public List getRegattaStructureForEvent(UUID eventId) { List raceGroups = new ArrayList(); Event event = getService().getEvent(eventId); @@ -4934,6 +3951,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * @param leaderboard The {@link Leaderboard} from which the name is be retrieved * @return the name of the regatta to be shown on the regatta overview page */ + //READ private String getRegattaNameFromLeaderboard(Leaderboard leaderboard) { String regattaName; if (leaderboard.getDisplayName() != null && !leaderboard.getDisplayName().isEmpty()) { @@ -4950,167 +3968,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public void removeRegattas(Collection selectedRegattas) { - for (RegattaIdentifier regatta : selectedRegattas) { - removeRegatta(regatta); - } - } - - @Override - public void removeRegatta(RegattaIdentifier regattaIdentifier) { - Regatta regatta = getService().getRegatta(regattaIdentifier); - if (regatta != null) { - Set objectsThatWillBeImplicitlyCleanedByRemoveRegatta = new HashSet<>(); - objectsThatWillBeImplicitlyCleanedByRemoveRegatta.add(regatta.getIdentifier()); - for (RaceDefinition race : regatta.getAllRaces()) { - TypeRelativeObjectIdentifier typeRelativeObjectIdentifier = RegattaNameAndRaceName - .getTypeRelativeObjectIdentifier(regatta.getName(), race.getName()); - QualifiedObjectIdentifier identifier = SecuredDomainType.TRACKED_RACE - .getQualifiedObjectIdentifier(typeRelativeObjectIdentifier); - objectsThatWillBeImplicitlyCleanedByRemoveRegatta.add(identifier); - } - for (Leaderboard leaderboard : getService().getLeaderboards().values()) { - if (leaderboard instanceof RegattaLeaderboard) { - RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; - if (regattaLeaderboard.getRegatta() == regatta) { - objectsThatWillBeImplicitlyCleanedByRemoveRegatta.add(regattaLeaderboard.getIdentifier()); - } - } - } - // check if we can delete everything RemoveRegatta will remove - for (QualifiedObjectIdentifier toRemovePermissionObjects : objectsThatWillBeImplicitlyCleanedByRemoveRegatta) { - getSecurityService().checkCurrentUserDeletePermission(toRemovePermissionObjects); - } - // we have all permissions, execute - getService().apply(new RemoveRegatta(regattaIdentifier)); - // cleanup the Ownership and ACLs - for (QualifiedObjectIdentifier toRemovePermissionObjects : objectsThatWillBeImplicitlyCleanedByRemoveRegatta) { - getSecurityService().deleteAllDataForRemovedObject(toRemovePermissionObjects); - } - } - } - - @Override - public void removeSeries(RegattaIdentifier identifier, String seriesName) { - Regatta regatta = getService().getRegatta(identifier); - if (regatta != null) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.REGATTA.getStringPermissionForObject(DefaultActions.UPDATE, regatta)); - } - getService().apply(new RemoveSeries(identifier, seriesName)); - } - - private RaceColumnInSeriesDTO convertToRaceColumnInSeriesDTO(RaceColumnInSeries raceColumnInSeries) { - RaceColumnInSeriesDTO raceColumnInSeriesDTO = new RaceColumnInSeriesDTO(raceColumnInSeries.getSeries().getName(), - raceColumnInSeries.getRegatta().getName()); - fillRaceColumnDTO(raceColumnInSeries, raceColumnInSeriesDTO); - return raceColumnInSeriesDTO; - } - - @Override - public void updateRegatta(RegattaIdentifier regattaName, Date startDate, Date endDate, Iterable courseAreaUuids, - RegattaConfigurationDTO configurationDTO, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes, - boolean autoRestartTrackingUponCompetitorSetChange, String registrationLinkSecret, CompetitorRegistrationType registrationType) { - Regatta regatta = getService().getRegatta(regattaName); - if (regatta != null) { - SecurityUtils.getSubject().checkPermission(SecuredDomainType.REGATTA.getStringPermissionForObject(DefaultActions.UPDATE, regatta)); - } - TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null; - TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; - getService().apply(new UpdateSpecificRegatta(regattaName, startTimePoint, endTimePoint, courseAreaUuids, - convertToRegattaConfiguration(configurationDTO), buoyZoneRadiusInHullLengths, useStartTimeInference, - controlTrackingFromStartAndFinishTimes, autoRestartTrackingUponCompetitorSetChange, registrationLinkSecret, registrationType)); - } - - @Override - public List addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, - List> columnNamesWithInsertIndex) { - Regatta regatta = getService().getRegatta(regattaIdentifier); - if (regatta != null) { - SecurityUtils.getSubject().checkPermission(SecuredDomainType.REGATTA.getStringPermissionForObject(DefaultActions.UPDATE, regatta)); - } - List result = new ArrayList(); - for (Pair columnNameAndInsertIndex : columnNamesWithInsertIndex) { - RaceColumnInSeries raceColumnInSeries = getService().apply( - new AddColumnToSeries(columnNameAndInsertIndex.getB(), regattaIdentifier, seriesName, columnNameAndInsertIndex.getA())); - if (raceColumnInSeries != null) { - result.add(convertToRaceColumnInSeriesDTO(raceColumnInSeries)); - } - } - return result; - } - - @Override - public void updateSeries(RegattaIdentifier regattaIdentifier, String seriesName, String newSeriesName, boolean isMedal, boolean isFleetsCanRunInParallel, - int[] resultDiscardingThresholds, boolean startsWithZeroScore, - boolean firstColumnIsNonDiscardableCarryForward, boolean hasSplitFleetContiguousScoring, - Integer maximumNumberOfDiscards, List fleets) { - Regatta regatta = getService().getRegatta(regattaIdentifier); - if (regatta != null) { - SecurityUtils.getSubject().checkPermission(SecuredDomainType.REGATTA.getStringPermissionForObject(DefaultActions.UPDATE, regatta)); - } - getService().apply( - new UpdateSeries(regattaIdentifier, seriesName, newSeriesName, isMedal, isFleetsCanRunInParallel, resultDiscardingThresholds, - startsWithZeroScore, firstColumnIsNonDiscardableCarryForward, hasSplitFleetContiguousScoring, - maximumNumberOfDiscards, fleets)); - } - - @Override - public void removeRaceColumnsFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, List columnNames) { - Regatta regatta = getService().getRegatta(regattaIdentifier); - if (regatta != null) { - SecurityUtils.getSubject().checkPermission(SecuredDomainType.REGATTA.getStringPermissionForObject(DefaultActions.UPDATE, regatta)); - } - for(String columnName: columnNames) { - getService().apply(new RemoveColumnFromSeries(regattaIdentifier, seriesName, columnName)); - } - } - - @Override - public void moveRaceColumnInSeriesUp(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) { - Regatta regatta = getService().getRegatta(regattaIdentifier); - if (regatta != null) { - SecurityUtils.getSubject().checkPermission(SecuredDomainType.REGATTA.getStringPermissionForObject(DefaultActions.UPDATE, regatta)); - } - getService().apply(new MoveColumnInSeriesUp(regattaIdentifier, seriesName, columnName)); - } - - @Override - public void moveRaceColumnInSeriesDown(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) { - Regatta regatta = getService().getRegatta(regattaIdentifier); - if (regatta != null) { - SecurityUtils.getSubject().checkPermission(SecuredDomainType.REGATTA.getStringPermissionForObject(DefaultActions.UPDATE, regatta)); - } - getService().apply(new MoveColumnInSeriesDown(regattaIdentifier, seriesName, columnName)); - } - - @Override - public RegattaDTO createRegatta(String regattaName, String boatClassName, - boolean canBoatsOfCompetitorsChangePerRace, CompetitorRegistrationType competitorRegistrationType, String registrationLinkSecret, - Date startDate, Date endDate, - RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal, - boolean persistent, ScoringSchemeType scoringSchemeType, Iterable courseAreaIds, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, - boolean controlTrackingFromStartAndFinishTimes, boolean autoRestartTrackingUponCompetitorSetChange, RankingMetrics rankingMetricType) { - return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( - SecuredDomainType.REGATTA, Regatta.getTypeRelativeObjectIdentifier(regattaName), - regattaName, new Callable() { - @Override - public RegattaDTO call() throws Exception { - TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null; - TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; - Regatta regatta = getService().apply(new AddSpecificRegatta(regattaName, boatClassName, - canBoatsOfCompetitorsChangePerRace, competitorRegistrationType, registrationLinkSecret, - startTimePoint, endTimePoint, UUID.randomUUID(), - seriesNamesWithFleetNamesAndFleetOrderingAndMedal, persistent, - baseDomainFactory.createScoringScheme(scoringSchemeType), courseAreaIds, - buoyZoneRadiusInHullLengths, useStartTimeInference, - controlTrackingFromStartAndFinishTimes, autoRestartTrackingUponCompetitorSetChange, rankingMetricType)); - return convertToRegattaDTO(regatta); - } - }); - } - - @Override + //READ public RegattaScoreCorrectionDTO getScoreCorrections(String scoreCorrectionProviderName, String eventName, String boatClassName, Date timePointWhenResultPublished) throws Exception { RegattaScoreCorrectionDTO result = null; @@ -5127,6 +3985,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private RegattaScoreCorrectionDTO createScoreCorrection(RegattaScoreCorrections scoreCorrections) { // Key is the race name or number as String; values are maps whose key is the sailID. LinkedHashMap> map = new LinkedHashMap>(); @@ -5140,6 +3999,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return new RegattaScoreCorrectionDTO(scoreCorrections.getProvider().getName(), map); } + //READ private ScoreCorrectionEntryDTO createScoreCorrectionEntryDTO( ScoreCorrectionForCompetitorInRace scoreCorrectionForCompetitor) { return new ScoreCorrectionEntryDTO(scoreCorrectionForCompetitor.getPoints(), @@ -5147,6 +4007,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List> getUrlResultProviderNamesAndOptionalSampleURL() { List> result = new ArrayList<>(); // In case a user may not read any result import URL, just an empty result is returned because @@ -5162,13 +4023,27 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } - private ServerInfoDTO getServerInfo() { + //READ + protected ResultUrlProvider getUrlBasedScoreCorrectionProvider(String resultProviderName) { + ResultUrlProvider result = null; + for (ScoreCorrectionProvider scp : getAllScoreCorrectionProviders()) { + if (scp instanceof ResultUrlProvider && scp.getName().equals(resultProviderName)) { + result = (ResultUrlProvider) scp; + break; + } + } + return result; + } + + //READ + protected ServerInfoDTO getServerInfo() { ServerInfoDTO result = new ServerInfoDTO(ServerInfo.getName(), ServerInfo.getBuildVersion()); SecurityDTOUtil.addSecurityInformation(getSecurityService(), result, result.getIdentifier()); return result; } @Override + //READ public ServerConfigurationDTO getServerConfiguration() { SailingServerConfiguration sailingServerConfiguration = getService().getSailingServerConfiguration(); UserGroup serverTenant = getSecurityService().getServerGroup(); @@ -5180,6 +4055,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //?? public void updateServerConfiguration(ServerConfigurationDTO serverConfiguration) { getSecurityService().checkCurrentUserServerPermission(ServerActions.CONFIGURE_LOCAL_SERVER); getService().apply(new UpdateServerConfiguration( @@ -5226,6 +4102,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //?? public List getRemoteSailingServerReferences() { List result = new ArrayList(); for (Entry, Exception>> remoteSailingServerRefAndItsCachedEvent : @@ -5239,6 +4116,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //?? public void removeSailingServers(Set namesOfSailingServersToRemove) throws Exception { getSecurityService().checkCurrentUserUpdatePermission(getServerInfo()); for (String serverName : namesOfSailingServersToRemove) { @@ -5247,6 +4125,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //?? public RemoteSailingServerReferenceDTO addRemoteSailingServerReference(RemoteSailingServerReferenceDTO sailingServer) throws MalformedURLException { getSecurityService().checkCurrentUserUpdatePermission(getServerInfo()); final String expandedURL; @@ -5263,6 +4142,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List getResultImportUrls(String resultProviderName) { final List result = new ArrayList<>(); SecurityService securityService = getSecurityService(); @@ -5278,31 +4158,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public void removeResultImportURLs(String resultProviderName, Set toRemove) throws Exception { - final RacingEventService racingEventService = getService(); - Set urlsToRemove = toRemove.stream() - .map(urlDto -> { - try { - return new URL(urlDto.getUrl()); - } catch (MalformedURLException e) { - return null; - } - }) - .filter(url -> url != null) - .collect(Collectors.toSet()); - racingEventService.removeResultImportURLs(resultProviderName, urlsToRemove); - } - - @Override - public void addResultImportUrl(String resultProviderName, UrlDTO urlDTO) throws Exception { - final RacingEventService racingEventService = getService(); - ResultUrlProvider resultUrlProvider = racingEventService.getUrlBasedScoreCorrectionProvider(resultProviderName) - .orElseThrow(() -> new IllegalStateException("ResultUrlProvider not found: " + resultProviderName)); - final URL url = resultUrlProvider.resolveUrl(urlDTO.getUrl()); - racingEventService.addResultImportUrl(resultProviderName, url); - } - - @Override + //READ public String validateResultImportUrl(String resultProviderName, UrlDTO urlDTO) { if (urlDTO == null || urlDTO.getUrl() == null || urlDTO.getUrl().isEmpty()) { return serverStringMessages.get(getClientLocale(), "pleaseEnterNonEmptyUrl"); @@ -5322,6 +4178,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List getOverallLeaderboardNamesContaining(String leaderboardName) { Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); if (leaderboard == null) { @@ -5343,6 +4200,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List getPreviousSwissTimingArchiveConfigurations() { Iterable configs = swissTimingAdapterPersistence .getSwissTimingArchiveConfigurations(); @@ -5355,57 +4213,24 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet }); } - @Override - public void createSwissTimingArchiveConfiguration(final String jsonURL) - throws Exception { - if (existsSwissTimingArchiveConfigurationForCurrentUser(jsonURL)) { - throw new RuntimeException("A configuration for the current user with this json URL already exists."); - } - final String currentUserName = getSecurityService().getCurrentUser().getName(); - final TypeRelativeObjectIdentifier identifier = SwissTimingArchiveConfiguration - .getTypeRelativeObjectIdentifier(jsonURL, currentUserName); - getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( - SecuredDomainType.SWISS_TIMING_ARCHIVE_ACCOUNT, - identifier, identifier.toString(), - () -> swissTimingAdapterPersistence.createSwissTimingArchiveConfiguration( - swissTimingFactory.createSwissTimingArchiveConfiguration(jsonURL, - currentUserName))); - } - - @Override - public void updateSwissTimingArchiveConfiguration(SwissTimingArchiveConfigurationWithSecurityDTO dto) - throws Exception { - getSecurityService().checkCurrentUserUpdatePermission(dto); - swissTimingAdapterPersistence.updateSwissTimingArchiveConfiguration( - swissTimingFactory.createSwissTimingArchiveConfiguration(dto.getJsonUrl(), dto.getCreatorName())); - } - - @Override - public void deleteSwissTimingArchiveConfigurations(Collection dtos) - throws Exception { - for (SwissTimingArchiveConfigurationWithSecurityDTO dto : dtos) { - getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(dto.getIdentifier(), - () -> swissTimingAdapterPersistence.deleteSwissTimingArchiveConfiguration(swissTimingFactory - .createSwissTimingArchiveConfiguration(dto.getJsonUrl(), dto.getCreatorName()))); - } - } - + //READ protected com.sap.sailing.domain.base.DomainFactory getBaseDomainFactory() { return baseDomainFactory; } - @Override - public List getRaceStateEntriesForLeaderboard(String leaderboardName, - boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay, Duration clientTimeZoneOffset, final List visibleRegattas) - throws NoWindException, InterruptedException, ExecutionException { + private List getRaceStateEntriesForLeaderboard(String leaderboardName, + boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay, Duration clientTimeZoneOffset, + final List visibleRegattas) throws NoWindException, InterruptedException, ExecutionException { Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); getSecurityService().checkCurrentUserReadPermission(leaderboard); - return getRaceStateEntriesForLeaderboard(leaderboard, showOnlyCurrentlyRunningRaces, showOnlyRacesOfSameDay, clientTimeZoneOffset, visibleRegattas); + return getRaceStateEntriesForLeaderboard(leaderboard, showOnlyCurrentlyRunningRaces, showOnlyRacesOfSameDay, + clientTimeZoneOffset, visibleRegattas); } /** * The client's day starts at 00:00:00Z - clientTimeZoneOffset and ends at 23:59:59Z - clientTimeZoneOffset. */ + //READ private List getRaceStateEntriesForLeaderboard(Leaderboard leaderboard, boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay, Duration clientTimeZoneOffset, final List visibleRegattas) throws NoWindException, InterruptedException, ExecutionException { @@ -5451,15 +4276,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } - private void createRegattaFromRegattaDTO(RegattaDTO regatta) { - this.createRegatta(regatta.getName(), regatta.boatClass.getName(), regatta.canBoatsOfCompetitorsChangePerRace, - regatta.competitorRegistrationType, regatta.registrationLinkSecret, regatta.startDate, regatta.endDate, - new RegattaCreationParametersDTO(getSeriesCreationParameters(regatta)), true, regatta.scoringScheme, - Util.map(regatta.courseAreas, CourseAreaDTO::getId), regatta.buoyZoneRadiusInHullLengths, - regatta.useStartTimeInference, regatta.controlTrackingFromStartAndFinishTimes, - regatta.autoRestartTrackingUponCompetitorSetChange, regatta.rankingMetricType); - } - + //READ private SeriesParameters getSeriesParameters(SeriesDTO seriesDTO) { SeriesParameters series = new SeriesParameters(false, false, false, null, seriesDTO.getMaximumNumberOfDiscards()); series.setFirstColumnIsNonDiscardableCarryForward(seriesDTO.isFirstColumnIsNonDiscardableCarryForward()); @@ -5469,7 +4286,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return series; } - private LinkedHashMap getSeriesCreationParameters(RegattaDTO regattaDTO) { + //READ + protected LinkedHashMap getSeriesCreationParameters(RegattaDTO regattaDTO) { LinkedHashMap seriesCreationParams = new LinkedHashMap(); for (SeriesDTO series : regattaDTO.series){ SeriesParameters seriesParameters = getSeriesParameters(series); @@ -5482,6 +4300,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Iterable getRegattas(String manage2SailJsonUrl) { StructureImporter structureImporter = new StructureImporter(new SetRacenumberFromSeries(), baseDomainFactory); Iterable parsedEvent = structureImporter.parseEvent(manage2SailJsonUrl); @@ -5493,79 +4312,12 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return regattaDTOs; } - /** - * Uses {@link #addRaceColumnsToSeries} which also handles replication to update the regatta identified - * by regatta's {@link RegattaDTO#getRegattaIdentifier() identifier} with the race columns - * as specified by regatta. The domain regatta object is assumed to have no races associated - * when this method is called. - */ - private void addRaceColumnsToRegattaSeries(RegattaDTO regatta) { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.REGATTA.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Regatta.getTypeRelativeObjectIdentifier(regatta.getName()))); - for (SeriesDTO series : regatta.series) { - List> raceNamesAndInsertIndex = new ArrayList<>(); - int insertIndex = 0; - for (RaceColumnDTO raceColumnInSeries : series.getRaceColumns()) { - raceNamesAndInsertIndex.add(new Pair<>(raceColumnInSeries.getName(), insertIndex)); - insertIndex++; - } - addRaceColumnsToSeries(regatta.getRegattaIdentifier(), series.getName(), raceNamesAndInsertIndex); - } - } - - @Override - public void createRegattaStructure(final Iterable regattas, - final EventDTO newEvent) throws MalformedURLException { - final List leaderboardNames = new ArrayList(); - for (RegattaDTO regatta : regattas) { - createRegattaFromRegattaDTO(regatta); - addRaceColumnsToRegattaSeries(regatta); - if (getLeaderboard(regatta.getName()) == null) { - leaderboardNames.add(regatta.getName()); - createRegattaLeaderboard(new RegattaName(regatta.getName()), regatta.boatClass.toString(), - new int[0]); - } - } - createAndAddLeaderboardGroup(newEvent, leaderboardNames); - // TODO find a way to import the competitors for the selected regattas. You'll need the regattas as Iterable - // structureImporter.setCompetitors(regattas, ""); - } - - private void createAndAddLeaderboardGroup(final EventDTO newEvent, - List leaderboardNames) throws MalformedURLException { - LeaderboardGroupDTO leaderboardGroupDTO = null; - String description = ""; - if (newEvent.getDescription() != null) { - description = newEvent.getDescription(); - } - String eventName = newEvent.getName(); - List eventLeaderboardGroupUUIDs = new ArrayList<>(); - // create Leaderboard Group - LeaderboardGroup leaderboardGroup = getService().getLeaderboardGroupByName(eventName); - if (leaderboardGroup == null) { - leaderboardGroupDTO = doCreateLeaderboardGroup(eventName, description, eventName, false, - null, null, - leaderboardNames); - eventLeaderboardGroupUUIDs.add(leaderboardGroupDTO.getId()); - } else { - updateLeaderboardGroup(leaderboardGroup.getId(), eventName, eventName, newEvent.getDescription(), eventName, leaderboardNames, null, null); - leaderboardGroupDTO = getLeaderboardGroupByName(eventName, false); - } - for (LeaderboardGroupDTO lg : newEvent.getLeaderboardGroups()) { - eventLeaderboardGroupUUIDs.add(lg.getId()); - } - updateEvent(newEvent.id, newEvent.getName(), description, newEvent.startDate, newEvent.endDate, newEvent.venue, - newEvent.isPublic, eventLeaderboardGroupUUIDs, newEvent.getOfficialWebsiteURL(), - newEvent.getBaseURL(), newEvent.getSailorsInfoWebsiteURLs(), newEvent.getImages(), newEvent.getVideos(), - newEvent.getWindFinderReviewedSpotsCollectionIds()); - } - private Triple getLeaderboardSlotKey(RegattaOverviewEntryDTO entry) { return new Triple<>(entry.leaderboardName, entry.raceInfo.raceName, entry.raceInfo.fleetName); } - + @Override + //READ public List getRaceStateEntriesForRaceGroup(UUID eventId, List visibleCourseAreaIds, List visibleRegattas, boolean showOnlyCurrentlyRunningRaces, boolean showOnlyRacesOfSameDay, Duration clientTimeZoneOffset) throws NoWindException, InterruptedException, ExecutionException { @@ -5606,6 +4358,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet /** * The client's day starts at 00:00:00Z - clientTimeZoneOffset and ends at 23:59:59Z - clientTimeZoneOffset. */ + //READ private void getRegattaOverviewEntries(boolean showOnlyRacesOfSameDay, Duration clientTimeZoneOffset, Calendar dayToCheck, Leaderboard leaderboard, String boatClassName, String regattaName, Distance buyZoneRadius, String seriesName, RaceColumn raceColumn, Map> entriesPerFleet) { @@ -5621,6 +4374,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } } + //READ private List getRegattaOverviewEntriesToBeShown(boolean showOnlyCurrentlyRunningRaces, Map> entriesPerFleet) { List result = new ArrayList(); @@ -5633,10 +4387,11 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet if (entry.raceInfo.lastStatus.equals(RaceLogRaceStatus.FINISHED)) { finishedEntries.add(entry); } else if (entry.raceInfo.lastStatus.equals(RaceLogRaceStatus.UNSCHEDULED)) { - // don't filter when the race is unscheduled and aborted before + //don't filter when the race is unscheduled and aborted before if (!entry.raceInfo.isRaceAbortedInPassBefore) { result.remove(entry); } + } } } @@ -5652,6 +4407,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private void addRegattaOverviewEntryToEntriesPerFleet(Map> entriesPerFleet, Fleet fleet, RegattaOverviewEntryDTO entry) { if (!entriesPerFleet.containsKey(fleet.getName())) { @@ -5663,6 +4419,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet /** * The client's day starts at 00:00:00Z - clientTimeZoneOffset and ends at 23:59:59Z - clientTimeZoneOffset. */ + //READ private RegattaOverviewEntryDTO createRegattaOverviewEntryDTO(Leaderboard leaderboard, String boatClassName, String regattaName, Distance buyZoneRadius, String seriesName, RaceColumn raceColumn, Fleet fleet, boolean showOnlyRacesOfSameDay, Duration clientTimeZoneOffset, Calendar dayToCheck) { @@ -5707,6 +4464,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public void stopReplicatingFromMaster() { getSecurityService().checkCurrentUserServerPermission(ServerActions.START_REPLICATION); try { @@ -5718,6 +4476,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //?? public void stopAllReplicas() { getSecurityService().checkCurrentUserServerPermission(ServerActions.REPLICATE); try { @@ -5729,6 +4488,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //?? public void stopSingleReplicaInstance(String identifier) { getSecurityService().checkCurrentUserServerPermission(ServerActions.REPLICATE); UUID uuid = UUID.fromString(identifier); @@ -5748,6 +4508,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public RaceLogDTO getRaceLog(String leaderboardName, RaceColumnDTO raceColumnDTO, FleetDTO fleet) { Leaderboard lb = getService().getLeaderboardByName(leaderboardName); getSecurityService().checkCurrentUserReadPermission(lb); @@ -5777,6 +4538,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public RegattaLogDTO getRegattaLog(String leaderboardName) throws DoesNotHaveRegattaLogException { RegattaLogDTO result = null; Leaderboard l = getService().getLeaderboardByName(leaderboardName); @@ -5804,6 +4566,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List getLeaderboardGroupNamesFromRemoteServer(String url, String username, String password) { String token = RemoteServerUtil.resolveBearerTokenForRemoteServer(url, username, password); // FIXME: Add checks here that ensure that the current use is allowed to do MDI @@ -5843,36 +4606,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public UUID importMasterData(final String urlAsString, final String[] groupNames, final boolean override, - final boolean compress, final boolean exportWind, final boolean exportDeviceConfigurations, - String targetServerUsername, String targetServerPassword, - final boolean exportTrackedRacesAndStartTracking) { - final UUID importOperationId = UUID.randomUUID(); - getSecurityService().checkCurrentUserServerPermission(ServerActions.CAN_IMPORT_MASTERDATA); - // // Create a progress indicator for as long as the server gets data from the other server. - // // As soon as the server starts the import operation, a progress object will be built on every server - Runnable masterDataImportTask = new Runnable() { - @Override - public void run() { - getService().importMasterData(urlAsString, groupNames, override, compress, exportWind, - exportDeviceConfigurations, targetServerUsername, targetServerPassword, /* targetServerBeararToken */ null, - exportTrackedRacesAndStartTracking, importOperationId); - } - }; - executor.execute(masterDataImportTask); - return importOperationId; - } - - public DataImportProgress getImportOperationProgress(UUID id) { - return getService().getDataImportLock().getProgress(id); - } - - @Override - public Integer getStructureImportOperationProgress() { - return 0; - } - - @Override + //READ public Iterable getCompetitors(boolean filterCompetitorsWithBoat, boolean filterCompetitorsWithoutBoat) { CompetitorAndBoatStore competitorStore = getService().getBaseDomainFactory().getCompetitorAndBoatStore(); @@ -5894,6 +4628,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Iterable getCompetitorsOfLeaderboard(String leaderboardName) { Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); getSecurityService().checkCurrentUserReadPermission(leaderboard); @@ -5901,6 +4636,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Map getCompetitorsAndBoatsOfRace(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { getSecurityService().checkCurrentUserReadPermission(getLeaderboardByName(leaderboardName)); @@ -5909,153 +4645,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public List addOrUpdateCompetitors(List competitors) throws URISyntaxException { - final List result = new ArrayList<>(); - for (final CompetitorDTO competitor : competitors) { - if (competitor.hasBoat()) { - final CompetitorWithBoatDTO competitorWithBoat = addOrUpdateCompetitorWithBoat((CompetitorWithBoatDTO) competitor); - SecurityDTOUtil.addSecurityInformation(getSecurityService(), competitorWithBoat, - competitorWithBoat.getIdentifier()); - result.add(competitorWithBoat); - } else { - final CompetitorDTO competitorWithoutBoat = addOrUpdateCompetitorWithoutBoat(competitor); - SecurityDTOUtil.addSecurityInformation(getSecurityService(), competitorWithoutBoat, - competitorWithoutBoat.getIdentifier()); - result.add(competitorWithoutBoat); - } - } - return result; - } - - private CompetitorWithBoat addOrUpdateCompetitorWithBoatInternal(CompetitorWithBoatDTO competitor) throws URISyntaxException { - final CompetitorWithBoat result; - CompetitorWithBoat existingCompetitor = getService().getCompetitorAndBoatStore().getExistingCompetitorWithBoatByIdAsString(competitor.getIdAsString()); - Nationality nationality = (competitor.getThreeLetterIocCountryCode() == null || competitor.getThreeLetterIocCountryCode().isEmpty()) ? null : - getBaseDomainFactory().getOrCreateNationality(competitor.getThreeLetterIocCountryCode()); - if (competitor.getIdAsString() == null || competitor.getIdAsString().isEmpty() || existingCompetitor == null) { - // new competitor - final UUID competitorUUID = UUID.randomUUID(); - final DynamicPerson sailor = new PersonImpl(competitor.getName(), nationality, null, null); - final DynamicTeam team = new TeamImpl(competitor.getName() + " team", Collections.singleton(sailor), null); - // new boat - final DynamicBoat boat = (DynamicBoat) addOrUpdateBoatInternal(competitor.getBoat()); - result = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( - SecuredDomainType.COMPETITOR, CompetitorImpl.getTypeRelativeObjectIdentifier(competitorUUID), - competitor.getName(), ()->getBaseDomainFactory().getCompetitorAndBoatStore().getOrCreateCompetitorWithBoat( - competitorUUID, competitor.getName(), competitor.getShortName(), - competitor.getColor(), competitor.getEmail(), - competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), - team, competitor.getTimeOnTimeFactor(), - competitor.getTimeOnDistanceAllowancePerNauticalMile(), competitor.getSearchTag(), - boat, /* storePersistently */ true)); - } else { - SecurityUtils.getSubject().checkPermission(SecuredDomainType.COMPETITOR.getStringPermissionForTypeRelativeIdentifier( - DefaultActions.UPDATE, CompetitorImpl.getTypeRelativeObjectIdentifier(competitor.getId()))); - Competitor updatedCompetitor = getService().apply( - new UpdateCompetitor(competitor.getIdAsString(), competitor.getName(), competitor.getShortName(), - competitor.getColor(), competitor.getEmail(), nationality, - competitor.getImageURL() == null ? null : new URI(competitor.getImageURL()), - competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), - competitor.getTimeOnTimeFactor(), - competitor.getTimeOnDistanceAllowancePerNauticalMile(), - competitor.getSearchTag())); - DynamicBoat updatedBoat = (DynamicBoat) addOrUpdateBoatInternal(competitor.getBoat()); - result = new CompetitorWithBoatImpl(updatedCompetitor, updatedBoat); - } - return result; - } - - - private Competitor addOrUpdateCompetitorWithoutBoatInternal(CompetitorDTO competitor) throws URISyntaxException { - final Competitor result; - Competitor existingCompetitor = getService().getCompetitorAndBoatStore() - .getExistingCompetitorByIdAsString(competitor.getIdAsString()); - Nationality nationality = (competitor.getThreeLetterIocCountryCode() == null - || competitor.getThreeLetterIocCountryCode().isEmpty()) ? null - : getBaseDomainFactory().getOrCreateNationality(competitor.getThreeLetterIocCountryCode()); - if (competitor.getIdAsString() == null || competitor.getIdAsString().isEmpty() || existingCompetitor == null) { - // new competitor - UUID competitorUUID = UUID.randomUUID(); - DynamicPerson sailor = new PersonImpl(competitor.getName(), nationality, null, null); - DynamicTeam team = new TeamImpl(competitor.getName() + " team", Collections.singleton(sailor), null); - result = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( - SecuredDomainType.COMPETITOR, CompetitorImpl.getTypeRelativeObjectIdentifier(competitorUUID), - competitor.getName(), ()->getBaseDomainFactory().getOrCreateCompetitor(competitorUUID, competitor.getName(), - competitor.getShortName(), competitor.getColor(), competitor.getEmail(), - competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), - team, competitor.getTimeOnTimeFactor(), - competitor.getTimeOnDistanceAllowancePerNauticalMile(), competitor.getSearchTag(), /* storePersistently */ true)); - } else { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.COMPETITOR.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - CompetitorImpl.getTypeRelativeObjectIdentifier(competitor.getId()))); - result = getService().apply(new UpdateCompetitor(competitor.getIdAsString(), competitor.getName(), - competitor.getShortName(), competitor.getColor(), competitor.getEmail(), nationality, - competitor.getImageURL() == null ? null : new URI(competitor.getImageURL()), - competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), - competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(), - competitor.getSearchTag())); - } - return result; - } - - @Override - public CompetitorDTO addOrUpdateCompetitorWithoutBoat(CompetitorDTO competitorDTO) throws URISyntaxException { - Competitor competitor = addOrUpdateCompetitorWithoutBoatInternal(competitorDTO); - return convertToCompetitorDTO(competitor); - } - - @Override - public CompetitorWithBoatDTO addOrUpdateCompetitorWithBoat(CompetitorWithBoatDTO competitorDTO) throws URISyntaxException { - CompetitorWithBoat competitor = addOrUpdateCompetitorWithBoatInternal(competitorDTO); - return convertToCompetitorWithBoatDTO(competitor); - } - - @Override - public List addCompetitors(List competitorDescriptors, String searchTag) throws URISyntaxException { - List competitorsForSaving = new ArrayList<>(); - for (final CompetitorDescriptor competitorDescriptor : competitorDescriptors) { - final Action action = ()->competitorsForSaving.add(getService().convertCompetitorDescriptorToCompetitorWithBoat(competitorDescriptor, searchTag)); - final Boat existingBoat = getService().getCompetitorAndBoatStore().getExistingBoatById(competitorDescriptor.getBoatUUID()); - final Action actionIncludingBoatSecurityCheck; - if (existingBoat == null) { - actionIncludingBoatSecurityCheck = ()->getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( - SecuredDomainType.BOAT, BoatImpl.getTypeRelativeObjectIdentifier(competitorDescriptor.getBoatUUID()), competitorDescriptor.getBoatName(), - action); - } else { - actionIncludingBoatSecurityCheck = action; - } - final Competitor existingCompetitor = getService().getCompetitorAndBoatStore().getExistingCompetitorById(competitorDescriptor.getCompetitorUUID()); - final Action actionIncludingCompetitorAndBoatSecurityCheck; - if (existingCompetitor == null) { - actionIncludingCompetitorAndBoatSecurityCheck = ()->getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( - SecuredDomainType.COMPETITOR, - CompetitorImpl.getTypeRelativeObjectIdentifier(competitorDescriptor.getCompetitorUUID()), competitorDescriptor.getName(), - actionIncludingBoatSecurityCheck); - } else { - actionIncludingCompetitorAndBoatSecurityCheck = actionIncludingBoatSecurityCheck; - } - try { - actionIncludingCompetitorAndBoatSecurityCheck.run(); - } catch (Exception e) { - throw new RuntimeException(e); // this can onlyhave been a RuntimeException in the first place because nothing of the above throws a checked one - } - } - getBaseDomainFactory().getCompetitorAndBoatStore().addNewCompetitorsWithBoat(competitorsForSaving); - return convertToCompetitorWithBoatDTOs(competitorsForSaving); - } - - @Override - public void allowCompetitorResetToDefaults(Iterable competitors) { - List competitorIdsAsStrings = new ArrayList(); - for (CompetitorDTO competitor : competitors) { - getSecurityService().checkCurrentUserUpdatePermission(competitor); - competitorIdsAsStrings.add(competitor.getIdAsString()); - } - getService().apply(new AllowCompetitorResetToDefaults(competitorIdsAsStrings)); - } - - @Override + //READ public Iterable getAllBoats() { final HasPermissions.Action[] requiredActionsForRead = SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS; Iterable result = getSecurityService().mapAndFilterByAnyExplicitPermissionForCurrentUser( @@ -6066,6 +4656,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Iterable getStandaloneBoats() { List result = new ArrayList<>(); getSecurityService().filterObjectsWithAnyPermissionForCurrentUser( @@ -6076,91 +4667,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public BoatDTO addOrUpdateBoat(BoatDTO boat) { - return convertToBoatDTO(addOrUpdateBoatInternal(boat)); - } - - private Boat addOrUpdateBoatInternal(BoatDTO boat) { - Boat existingBoat = getService().getCompetitorAndBoatStore().getExistingBoatByIdAsString(boat.getIdAsString()); - final Boat result; - if (boat.getIdAsString() == null || boat.getIdAsString().isEmpty() || existingBoat == null) { - // new boat - UUID boatUUID = UUID.randomUUID(); - BoatClass boatClass = getBaseDomainFactory().getOrCreateBoatClass(boat.getBoatClass().getName()); - result = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( - SecuredDomainType.BOAT, BoatImpl.getTypeRelativeObjectIdentifier(boatUUID), boat.getName(), - () -> getBaseDomainFactory().getOrCreateBoat(boatUUID, boat.getName(), boatClass, boat.getSailId(), boat.getColor(), /* storePersistently */ true)); - } else { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.BOAT.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - BoatImpl.getTypeRelativeObjectIdentifier(boat.getId()))); - result = getService() - .apply(new UpdateBoat(boat.getIdAsString(), boat.getName(), boat.getColor(), boat.getSailId())); - } - return result; - } - - @Override - public void allowBoatResetToDefaults(Iterable boats) { - List boatIdsAsStrings = new ArrayList(); - for (BoatDTO boat : boats) { - getSecurityService().checkCurrentUserUpdatePermission(boat); - boatIdsAsStrings.add(boat.getIdAsString()); - } - getService().apply(new AllowBoatResetToDefaults(boatIdsAsStrings)); - } - - @Override - public boolean linkBoatToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, - String competitorIdAsString, String boatIdAsString) throws NotFoundException { - final Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - getSecurityService().checkCurrentUserUpdatePermission(leaderboard); - boolean result = false; - Boat existingBoat = getService().getCompetitorAndBoatStore().getExistingBoatByIdAsString(boatIdAsString); - Competitor existingCompetitor = getService().getCompetitorAndBoatStore().getExistingCompetitorByIdAsString(competitorIdAsString); - RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); - if (raceLog != null && existingCompetitor != null && existingBoat != null) { - raceLog.add(new RaceLogRegisterCompetitorEventImpl(MillisecondsTimePoint.now(), - getService().getServerAuthor(), raceLog.getCurrentPassId(), existingCompetitor, existingBoat)); - result = true; - } - return result; - } - - @Override - public boolean unlinkBoatFromCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, - String competitorIdAsString) throws NotFoundException { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); - final boolean result; - final Competitor existingCompetitor = getService().getCompetitorAndBoatStore().getExistingCompetitorByIdAsString(competitorIdAsString); - final RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); - if (raceLog != null && existingCompetitor != null) { - final List linkEventsToRevoke = new ArrayList<>(); - raceLog.lockForRead(); - try { - for (RaceLogEvent event : raceLog.getUnrevokedEventsDescending()) { - if (event instanceof RaceLogRegisterCompetitorEvent) { - linkEventsToRevoke.add((RaceLogRegisterCompetitorEvent) event); - } - } - } finally { - raceLog.unlockAfterRead(); - } - try { - for (RaceLogRegisterCompetitorEvent eventToRevoke : linkEventsToRevoke) { - raceLog.revokeEvent(getService().getServerAuthor(), eventToRevoke, "unlink competitor from boat"); - } - } catch (NotRevokableException e) { - logger.log(Level.WARNING, "Could not unlink competitor from boat by adding RevokeEvent", e); - } - result = true; - } else { - result = false; - } - return result; - } - - @Override + //READ public BoatDTO getBoatLinkedToCompetitorForRace(String leaderboardName, String raceColumnName, String fleetName, String competitorIdAsString) throws NotFoundException { BoatDTO result = null; @@ -6178,6 +4685,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List getDeviceConfigurations() { List configs = new ArrayList(); for (DeviceConfiguration config : getService().getAllDeviceConfigurations()) { @@ -6189,13 +4697,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public DeviceConfigurationDTO getDeviceConfiguration(UUID id) { - DeviceConfiguration configuration = getService().getDeviceConfigurationById(id); - getSecurityService().checkCurrentUserReadPermission(configuration); - return configuration == null ? null : convertToDeviceConfigurationDTO(configuration); - } - - @Override + //READ public void createOrUpdateDeviceConfiguration(DeviceConfigurationDTO configurationDTO) { if (getService().getDeviceConfigurationById(configurationDTO.id) == null) { final DeviceConfiguration configuration = convertToDeviceConfiguration(configurationDTO); @@ -6214,27 +4716,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } } - @Override - public boolean removeDeviceConfiguration(UUID deviceConfigurationId) { - final DeviceConfiguration configuration = getService().getDeviceConfigurationById(deviceConfigurationId); - getSecurityService().checkCurrentUserDeletePermission(configuration); - getService().removeDeviceConfiguration(deviceConfigurationId); - return true; - } - - private DeviceConfigurationDTO convertToDeviceConfigurationDTO(DeviceConfiguration configuration) { - DeviceConfigurationDTO dto = new DeviceConfigurationDTO(); - dto.id = configuration.getId(); - dto.name = configuration.getName(); - dto.allowedCourseAreaNames = configuration.getAllowedCourseAreaNames(); - dto.resultsMailRecipient = configuration.getResultsMailRecipient(); - dto.byNameDesignerCourseNames = configuration.getByNameCourseDesignerCourseNames(); - if (configuration.getRegattaConfiguration() != null) { - dto.regattaConfiguration = convertToRegattaConfigurationDTO(configuration.getRegattaConfiguration()); - } - return dto; - } - + //READ private DeviceConfigurationWithSecurityDTO convertToDeviceConfigurationWithSecurityDTO( DeviceConfiguration configuration) { DeviceConfigurationWithSecurityDTO dto = new DeviceConfigurationWithSecurityDTO(configuration.getIdentifier()); @@ -6250,6 +4732,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return dto; } + ///READ private DeviceConfigurationDTO.RegattaConfigurationDTO convertToRegattaConfigurationDTO( RegattaConfiguration configuration) { if (configuration == null) { @@ -6292,16 +4775,19 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return dto; } + //READ private void copyBasicRacingProcedureProperties(RacingProcedureConfiguration configuration, final RacingProcedureConfigurationDTO racingProcedureConfigurationDTO) { racingProcedureConfigurationDTO.classFlag = configuration.getClassFlag(); racingProcedureConfigurationDTO.hasIndividualRecall = configuration.hasIndividualRecall(); racingProcedureConfigurationDTO.isResultEntryEnabled = configuration.isResultEntryEnabled(); } + //READ private void copyRacingProcedureWithConfigurableStartModeFlagProperties(ConfigurableStartModeFlagRacingProcedureConfiguration configuration, final RacingProcedureWithConfigurableStartModeFlagConfigurationDTO racingProcedureConfigurationDTO) { racingProcedureConfigurationDTO.startModeFlags = configuration.getStartModeFlags(); } + //READ private DeviceConfigurationImpl convertToDeviceConfiguration(DeviceConfigurationDTO dto) { DeviceConfigurationImpl configuration = new DeviceConfigurationImpl(convertToRegattaConfiguration(dto.regattaConfiguration), dto.id, dto.name); configuration.setAllowedCourseAreaNames(dto.allowedCourseAreaNames); @@ -6310,7 +4796,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return configuration; } - private RegattaConfiguration convertToRegattaConfiguration(RegattaConfigurationDTO dto) { + //READ + protected RegattaConfiguration convertToRegattaConfiguration(RegattaConfigurationDTO dto) { if (dto == null) { return null; } @@ -6355,6 +4842,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return configuration; } + //READ private void applyGeneralRacingProcedureConfigProperties(RacingProcedureConfigurationDTO racingProcedureConfigurationDTO, RacingProcedureConfigurationImpl config) { config.setClassFlag(racingProcedureConfigurationDTO.classFlag); @@ -6362,6 +4850,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet config.setResultEntryEnabled(racingProcedureConfigurationDTO.isResultEntryEnabled); } + //READ private void applyRacingProcedureWithConfigurableStartModeFlagConfigProperties( RacingProcedureWithConfigurableStartModeFlagConfigurationDTO racingProcedureConfigurationDTO, RacingProcedureWithConfigurableStartModeFlagConfigurationImpl config) { @@ -6369,6 +4858,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public boolean setStartTimeAndProcedure(RaceLogSetStartTimeAndProcedureDTO dto) throws NotFoundException { getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(dto.leaderboardName)); TimePoint newStartTime = getService().setStartTimeAndProcedure(dto.leaderboardName, dto.raceColumnName, @@ -6379,6 +4869,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Pair setFinishingAndEndTime(RaceLogSetFinishingAndFinishTimeDTO dto) throws NotFoundException { getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(dto.leaderboardName)); @@ -6397,63 +4888,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public void setTrackingTimes(RaceLogSetTrackingTimesDTO dto) throws NotFoundException { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(dto.leaderboardName)); - RaceLog raceLog = getRaceLog(dto.leaderboardName, dto.raceColumnName, dto.fleetName); - // the tracking start/end time events are not revoked; updates with null as TimePoint may be added instead - final LogEventAuthorImpl author = new LogEventAuthorImpl(dto.authorName, dto.authorPriority); - if (!Util.equalsWithNull(dto.newStartOfTracking, dto.currentStartOfTracking)) { - if (dto.newStartOfTracking != null) { - raceLog.add(new RaceLogStartOfTrackingEventImpl(dto.newStartOfTracking.getTimePoint(), - author, raceLog.getCurrentPassId())); - } else { - final Pair trackingTimesEvents = new TrackingTimesEventFinder(raceLog).analyze(); - // we assume to find a valid "set start of tracking time" event that matches the old start of tracking time; - // if the time doesn't match dto.currentStartOfTracking, the revocation is rejected with an exception; - // the result of trying to revoke is returned otherwise, and it may not be the result intended in case - // the author's priority was lower than that of the author of the event that is to be revoked. - if (trackingTimesEvents == null || trackingTimesEvents.getA() == null || - !Util.equalsWithNull(trackingTimesEvents.getA().getLogicalTimePoint(), dto.currentStartOfTracking==null?null:dto.currentStartOfTracking.getTimePoint())) { - throw new NotFoundException("Old start of tracking time in the race log ("+ - (trackingTimesEvents==null||trackingTimesEvents.getA()==null?"unset":trackingTimesEvents.getA().getLogicalTimePoint())+ - ") does not match start of tracking time at transaction start ("+dto.currentStartOfTracking==null?null:dto.currentStartOfTracking.getTimePoint()+")"); - } else { - try { - raceLog.revokeEvent(author, trackingTimesEvents.getA(), "resetting tracking start time"); - } catch (NotRevokableException e) { - logger.log(Level.WARNING, "Internal error: event "+trackingTimesEvents.getA()+" was expected to be revokable", e); - } - } - } - } - if (!Util.equalsWithNull(dto.newEndOfTracking, dto.currentEndOfTracking)) { - if (dto.newEndOfTracking != null) { - raceLog.add(new RaceLogEndOfTrackingEventImpl( - dto.newEndOfTracking.getTimePoint(), author, - raceLog.getCurrentPassId())); - } else { - final Pair trackingTimesEvents = new TrackingTimesEventFinder(raceLog).analyze(); - // we assume to find a valid "set start of tracking time" event that matches the old start of tracking time; - // if the time doesn't match dto.currentStartOfTracking, the revocation is rejected with an exception; - // the result of trying to revoke is returned otherwise, and it may not be the result intended in case - // the author's priority was lower than that of the author of the event that is to be revoked. - if (trackingTimesEvents == null || trackingTimesEvents.getB() == null || - !Util.equalsWithNull(trackingTimesEvents.getB().getLogicalTimePoint(), dto.currentEndOfTracking==null?null:dto.currentEndOfTracking.getTimePoint())) { - throw new NotFoundException("Old end of tracking time in the race log ("+ - (trackingTimesEvents==null||trackingTimesEvents.getB()==null?"unset":trackingTimesEvents.getB().getLogicalTimePoint())+ - ") does not match end of tracking time at transaction start ("+dto.currentEndOfTracking==null?null:dto.currentEndOfTracking.getTimePoint()+")"); - } else { - try { - raceLog.revokeEvent(author, trackingTimesEvents.getB(), "resetting tracking end time"); - } catch (NotRevokableException e) { - logger.log(Level.WARNING, "Internal error: event "+trackingTimesEvents.getB()+" was expected to be revokable", e); - } - } - } - } - } - - @Override + //READ public Pair getTrackingTimes(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { getSecurityService().checkCurrentUserReadPermission(getLeaderboardByName(leaderboardName)); final Pair times; @@ -6467,6 +4902,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public com.sap.sse.common.Util.Triple getStartTimeAndProcedure( String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { getSecurityService().checkCurrentUserReadPermission(getLeaderboardByName(leaderboardName)); @@ -6479,6 +4915,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet @Override + //READ public com.sap.sse.common.Util.Triple getFinishingAndFinishTime(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { getSecurityService().checkCurrentUserReadPermission(getLeaderboardByName(leaderboardName)); @@ -6491,17 +4928,13 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public Iterable getAllIgtimiAccountEmailAddresses() { - return getSecurityService().mapAndFilterByReadPermissionForCurrentUser( - getIgtimiConnectionFactory().getAllAccounts(), acc -> acc.getUser().getEmail()); - } - - @Override + //READ public Iterable getAllIgtimiAccountsWithSecurity() { return getSecurityService().mapAndFilterByReadPermissionForCurrentUser( getIgtimiConnectionFactory().getAllAccounts(), this::toSecuredIgtimiAccountDTO); } + //READ private AccountWithSecurityDTO toSecuredIgtimiAccountDTO(final Account igtimiAccount) { final com.sap.sailing.domain.igtimiadapter.User user = igtimiAccount.getUser(); final String email = user.getEmail(); @@ -6512,97 +4945,28 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return securedAccount; } - private IgtimiConnectionFactory getIgtimiConnectionFactory() { + //?? + protected IgtimiConnectionFactory getIgtimiConnectionFactory() { return igtimiAdapterTracker.getService(); } - + //?? protected RaceLogTrackingAdapterFactory getRaceLogTrackingAdapterFactory() { return raceLogTrackingAdapterTracker.getService(); } + //?? protected RaceLogTrackingAdapter getRaceLogTrackingAdapter() { return getRaceLogTrackingAdapterFactory().getAdapter(getBaseDomainFactory()); } @Override + //READ public String getIgtimiAuthorizationUrl(String redirectProtocol, String redirectHostname, String redirectPort) throws MalformedURLException, UnsupportedEncodingException { return getIgtimiConnectionFactory().getAuthorizationUrl(redirectProtocol, redirectHostname, redirectPort); } - @Override - public boolean authorizeAccessToIgtimiUser(String eMailAddress, String password) throws Exception { - final Account existingAccount = getIgtimiConnectionFactory().getExistingAccountByEmail(eMailAddress); - final Account account; - if (existingAccount == null) { - final String creatorName = getSecurityService().getCurrentUser().getName(); - account = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( - SecuredDomainType.IGTIMI_ACCOUNT, - Account.getTypeRelativeObjectIdentifier(eMailAddress, creatorName), - eMailAddress, - () -> getIgtimiConnectionFactory().createAccountToAccessUserData(creatorName, eMailAddress, password)); - } else { - logger.warning("Igtimi account "+eMailAddress+" already exists."); - account = null; // account with that e-mail already exists - } - return account != null; - } - - @Override - public void removeIgtimiAccount(String eMailOfAccountToRemove) { - final Account existingAccount = getIgtimiConnectionFactory().getExistingAccountByEmail(eMailOfAccountToRemove); - if (existingAccount != null) { - getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(existingAccount, () -> { - getIgtimiConnectionFactory().removeAccount(existingAccount); - }); - } - } - - @Override - public Map importWindFromIgtimi(List selectedRaces, boolean correctByDeclination) throws IllegalStateException, - ClientProtocolException, IOException, org.json.simple.parser.ParseException { - final IgtimiConnectionFactory igtimiConnectionFactory = getIgtimiConnectionFactory(); - final List trackedRaces = new ArrayList<>(); - if (selectedRaces != null && !selectedRaces.isEmpty()) { - for (RaceDTO raceDTO : selectedRaces) { - DynamicTrackedRace trackedRace = getTrackedRace(raceDTO.getRaceIdentifier()); - // In case the user selected a distinct set of races, we want the call to completely fail if - // tracking wind isn't allowed for at least one race - getSecurityService().checkCurrentUserUpdatePermission(trackedRace); - trackedRaces.add(trackedRace); - } - } else { - for (DynamicTrackedRace race : getAllTrackedRaces()) { - // In case the user likes to track wind for all races, we silently filter for the ones - // for which the user has sufficient permissions - if (getSecurityService().hasCurrentUserUpdatePermission(race)) { - trackedRaces.add(race); - } - } - } - Map numberOfWindFixesImportedPerRace = new HashMap(); - for (Account account : igtimiConnectionFactory.getAllAccounts()) { - // filter account based on used permissions to read account: - if (getSecurityService().hasCurrentUserReadPermission(account)) { - IgtimiConnection conn = igtimiConnectionFactory.connect(account); - Map resultsForAccounts = conn.importWindIntoRace(trackedRaces, correctByDeclination); - for (Entry resultForAccount : resultsForAccounts.entrySet()) { - RegattaAndRaceIdentifier key = resultForAccount.getKey().getRaceIdentifier(); - Integer i = numberOfWindFixesImportedPerRace.get(key); - if (i == null) { - i = 0; - } - numberOfWindFixesImportedPerRace.put(key, i+resultForAccount.getValue()); - } - } - } - for (final TrackedRace trackedRace : trackedRaces) { - // update polar sheets: - getService().getPolarDataService().insertExistingFixes(trackedRace); - } - return numberOfWindFixesImportedPerRace; - } - - private Set getAllTrackedRaces() { + //READ + protected Set getAllTrackedRaces() { Set result = new HashSet(); Iterable allRegattas = getService().getAllRegattas(); for (Regatta regatta : allRegattas) { @@ -6622,49 +4986,17 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } - @Override - public Boolean denoteForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName) - throws NotFoundException, NotDenotableForRaceLogTrackingException { - Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - getSecurityService().checkCurrentUserUpdatePermission(leaderboard); - RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); - Fleet fleet = getFleetByName(raceColumn, fleetName); - return getRaceLogTrackingAdapter().denoteRaceForRaceLogTracking(getService(), leaderboard, raceColumn, fleet, - null); - } - - @Override - public void removeDenotationForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName) - throws NotFoundException { - Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - getSecurityService().checkCurrentUserUpdatePermission(leaderboard); - RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); - getRaceLogTrackingAdapter().removeDenotationForRaceLogTracking(getService(), raceLog); - } - - @Override - public void denoteForRaceLogTracking(String leaderboardName) throws Exception { - Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - getSecurityService().checkCurrentUserUpdatePermission(leaderboard); - denoteForRaceLogTracking(leaderboardName, /* race name prefix */ null); - } - - @Override - public void denoteForRaceLogTracking(String leaderboardName, String prefix) throws Exception { - Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - getSecurityService().checkCurrentUserUpdatePermission(leaderboard); - getRaceLogTrackingAdapter().denoteAllRacesForRaceLogTracking(getService(), leaderboard, prefix); - } - /** * @param triple * leaderboard and racecolumn and fleet names */ - private RaceLog getRaceLog(com.sap.sse.common.Util.Triple triple) throws NotFoundException { + //READ + protected RaceLog getRaceLog(com.sap.sse.common.Util.Triple triple) throws NotFoundException { return getRaceLog(triple.getA(), triple.getB(), triple.getC()); } - private RegattaLog getRegattaLogInternal(String leaderboardName) throws DoesNotHaveRegattaLogException { + //READ + protected RegattaLog getRegattaLogInternal(String leaderboardName) throws DoesNotHaveRegattaLogException { Leaderboard l = getService().getLeaderboardByName(leaderboardName); if (! (l instanceof HasRegattaLike)) { throw new DoesNotHaveRegattaLogException(); @@ -6672,137 +5004,30 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return ((HasRegattaLike) l).getRegattaLike().getRegattaLog(); } - private RaceLog getRaceLog(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { + //READ + protected RaceLog getRaceLog(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); Fleet fleet = getFleetByName(raceColumn, fleetName); return raceColumn.getRaceLog(fleet); } - private Competitor getCompetitor(CompetitorDTO dto) { + //READ + protected Competitor getCompetitor(CompetitorDTO dto) { return getService().getCompetitorAndBoatStore().getExistingCompetitorByIdAsString(dto.getIdAsString()); } - private CompetitorWithBoat getCompetitor(CompetitorWithBoatDTO dto) { + //READ + protected CompetitorWithBoat getCompetitor(CompetitorWithBoatDTO dto) { return getService().getCompetitorAndBoatStore().getExistingCompetitorWithBoatByIdAsString(dto.getIdAsString()); } - private Boat getBoat(BoatDTO dto) { + //READ + protected Boat getBoat(BoatDTO dto) { return getService().getCompetitorAndBoatStore().getExistingBoatByIdAsString(dto.getIdAsString()); } - @Override - public void setCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName, - Map competitorAndBoatDTOs) - throws CompetitorRegistrationOnRaceLogDisabledException, NotFoundException { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); - RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); - Fleet fleet = getFleetByName(raceColumn, fleetName); - - Map competitorToBoatMappingsToRegister = new HashMap<>(); - for (Entry competitorAndBoatEntry : competitorAndBoatDTOs.entrySet()) { - competitorToBoatMappingsToRegister.put(getCompetitor(competitorAndBoatEntry.getKey()), getBoat(competitorAndBoatEntry.getValue())); - } - - final Iterable competitorRegistrationsToRemove = filterCompetitorDuplicates(competitorToBoatMappingsToRegister, raceColumn.getCompetitorsRegisteredInRacelog(fleet)); - raceColumn.deregisterCompetitors(competitorRegistrationsToRemove, fleet); - // we assume that the competitors id of type Competitor here, so we need to find the corresponding boat - for (final Entry competitorAndBoatToRegister : competitorToBoatMappingsToRegister.entrySet()) { - raceColumn.registerCompetitor(competitorAndBoatToRegister.getKey(), competitorAndBoatToRegister.getValue(), fleet); - } - } - - @Override - public void setCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName, - Set competitorDTOs) throws CompetitorRegistrationOnRaceLogDisabledException, NotFoundException { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); - - RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); - Fleet fleet = getFleetByName(raceColumn, fleetName); - - Map competitorsToRegister = new HashMap<>(); - for (CompetitorWithBoatDTO dto : competitorDTOs) { - competitorsToRegister.put(getCompetitor(dto), getBoat(dto.getBoat())); - } - - Map competitorsRegisteredInRaceLog = new HashMap<>(); - for (final Entry e : raceColumn.getCompetitorsRegisteredInRacelog(fleet).entrySet()) { - competitorsRegisteredInRaceLog.put((CompetitorWithBoat) e.getKey(), e.getValue()); - } - final Iterable competitorSetToRemove = filterCompetitorDuplicates(competitorsToRegister, competitorsRegisteredInRaceLog); - raceColumn.deregisterCompetitors(competitorSetToRemove, fleet); - // we assume that the competitors id of type Competitor here, so we need to find the corresponding boat - for (CompetitorWithBoat competitorToRegister : competitorsToRegister.keySet()) { - if (competitorToRegister.hasBoat()) { - raceColumn.registerCompetitor(competitorToRegister, fleet); - } else { - logger.warning("The competitor "+competitorToRegister.getName()+" does not have a boat associated but should have; "+ - "competitor is not registered for race log of race "+raceColumnName+" in leaderboard "+leaderboardName+" for fleet "+fleetName); - } - } - } - - @Override - public void setCompetitorRegistrationsInRegattaLog(String leaderboardName, Set competitorDTOs) - throws DoesNotHaveRegattaLogException, NotFoundException { - Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - getSecurityService().checkCurrentUserUpdatePermission(leaderboard); - if (!(leaderboard instanceof HasRegattaLike)){ - throw new DoesNotHaveRegattaLogException(); - } - Map competitorsToRegister = new HashMap<>(); - for (CompetitorDTO dto : competitorDTOs) { - competitorsToRegister.put(getCompetitor(dto), /* boat doesn't matter here */ null); - } - HasRegattaLike hasRegattaLike = (HasRegattaLike) leaderboard; - Map competitorsAlreadyRegistered = new HashMap<>(); - for (final Competitor c : leaderboard.getAllCompetitors()) { - competitorsAlreadyRegistered.put(c, /* boat doesn't matter here */ null); - } - final Iterable competitorSetToRemove = filterCompetitorDuplicates(competitorsToRegister, competitorsAlreadyRegistered); - hasRegattaLike.deregisterCompetitors(competitorSetToRemove); - hasRegattaLike.registerCompetitors(competitorsToRegister.keySet()); - } - - /** - * Removes competitors already registered to the same boats (those in {@code competitorsRegistered}) from {@code competitorsToRegister} to avoid - * registering them again and then returns those competitors that need to be de-registered. Those to de-register includes those registered but - * to a different boat, and those will be left in the {@code competitorToBoatMappingsToRegister} map. - * - * @param competitorToBoatMappingsToRegister will be modified by removing all competitors in {@code competitorsRegistered} - * @param competitorToBoatMappingsRegistered the competitors already registered; those will be removed from {@code competitorsToRegister} - * @return the competitors to de-register because they were in {@code competitorsRegistered} but are not in {@code competitorsToRegister} - */ - private Iterable filterCompetitorDuplicates( - Map competitorToBoatMappingsToRegister, - Map competitorToBoatMappingsRegistered) { - final Set competitorsToUnregister = new HashSet<>(); - Util.addAll(competitorToBoatMappingsRegistered.keySet(), competitorsToUnregister); - for (final Entry e : competitorToBoatMappingsRegistered.entrySet()) { - CompetitorType competitor = e.getKey(); - if (competitorToBoatMappingsToRegister.containsKey(competitor)) { // is competitor to be registered? - final Boat boatOfCompetitorToRegister = competitorToBoatMappingsToRegister.get(competitor); - final Boat boatOfRegisteredCompetitor = e.getValue(); - if (boatOfCompetitorToRegister == boatOfRegisteredCompetitor) { - // User wants to map competitor to boat, and that mapping already exists; neither add nor remove this registration but leave as is: - competitorToBoatMappingsToRegister.remove(competitor); - competitorsToUnregister.remove(competitor); - } - } - } - return competitorsToUnregister; - } - - private HashSet filterBoatDuplicates(Set boatsToRegister, HashSet boatSetToRemove) { - for (Iterator iterator = boatSetToRemove.iterator(); iterator.hasNext();) { - Boat boat = iterator.next(); - if (boatsToRegister.remove(boat)) { - iterator.remove(); - } - } - return boatSetToRemove; - } - - private Mark convertToMark(MarkDTO dto, boolean resolve) { + //READ + protected Mark convertToMark(MarkDTO dto, boolean resolve) { Mark result = null; if (resolve) { Mark existing = baseDomainFactory.getExistingMarkByIdAsString(dto.getIdAsString()); @@ -6824,72 +5049,13 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * If the mark has been pinged through the {@link RegattaLog} but no {@link TrackedRace} exists that has loaded that ping, * the ping won't be visible to this API. */ + //READ private MarkDTO convertToMarkDTO(LeaderboardThatHasRegattaLike leaderboard, Mark mark) { final TimePoint now = MillisecondsTimePoint.now(); final Position lastPos = getService().getMarkPosition(mark, leaderboard, now); return convertToMarkDTO(mark, lastPos); } - @Override - public void addMarkToRegattaLog(String leaderboardName, MarkDTO markDTO) throws DoesNotHaveRegattaLogException { - getSecurityService().checkCurrentUserUpdatePermission(getService().getLeaderboardByName(leaderboardName)); - Mark mark = convertToMark(markDTO, false); - - RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); - RegattaLogDefineMarkEventImpl event = new RegattaLogDefineMarkEventImpl(MillisecondsTimePoint.now(), - getService().getServerAuthor(), MillisecondsTimePoint.now(), UUID.randomUUID(), mark); - regattaLog.add(event); - } - - @Override - public void revokeMarkDefinitionEventInRegattaLog(String leaderboardName, MarkDTO markDTO) - throws DoesNotHaveRegattaLogException, NotFoundException { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); - RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); - final List regattaLogDefineMarkEvents = new AllEventsOfTypeFinder<>(regattaLog, /* only unrevoked */ true, RegattaLogDefineMarkEvent.class).analyze(); - RegattaLogDefineMarkEvent eventToRevoke = null; - for (RegattaLogEvent event : regattaLogDefineMarkEvents) { - RegattaLogDefineMarkEvent defineMarkEvent = (RegattaLogDefineMarkEvent) event; - if (defineMarkEvent.getMark().getId().toString().equals(markDTO.getIdAsString())){ - eventToRevoke = defineMarkEvent; - break; - } - } - regattaLog.revokeDefineMarkEventAndRelatedDeviceMappings(eventToRevoke, getService().getServerAuthor(), logger); - } - - @Override - public void addCourseDefinitionToRaceLog(String leaderboardName, String raceColumnName, String fleetName, - List> courseDTO, int priority) throws NotFoundException { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); - RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); - String courseName = "Course of " + raceColumnName; - if (!LeaderboardNameConstants.DEFAULT_FLEET_NAME.equals(fleetName)) { - courseName += " - " + fleetName; - } - CourseBase lastPublishedCourse = new LastPublishedCourseDesignFinder(raceLog, /* onlyCoursesWithValidWaypointList */ false).analyze(); - if (lastPublishedCourse == null) { - lastPublishedCourse = new CourseDataImpl(courseName); - } - - List> controlPoints = new ArrayList<>(); - for (Pair waypointDTO : courseDTO) { - controlPoints.add(new Pair<>(getOrCreateControlPoint(waypointDTO.getA()), waypointDTO.getB())); - } - Course course = new CourseImpl(courseName, lastPublishedCourse.getWaypoints()); - - try { - course.update(controlPoints, lastPublishedCourse.getAssociatedRoles(), - lastPublishedCourse.getOriginatingCourseTemplateIdOrNull(), baseDomainFactory); - } catch (Exception e) { - throw new RuntimeException(e); - } - RaceLogEvent event = new RaceLogCourseDesignChangedEventImpl(MillisecondsTimePoint.now(), - new LogEventAuthorImpl(getService().getServerAuthor().getName(), priority), - raceLog.getCurrentPassId(), course, CourseDesignerMode.ADMIN_CONSOLE); - raceLog.add(event); - } - /** * @param trackedRace * if null, no position data will be attached to the {@link MarkDTO}s @@ -6898,6 +5064,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * the mark positions and attach to the {@link MarkDTO}s. If null, the current time point * will be used as default. */ + //READ private WaypointDTO convertToWaypointDTO(Waypoint waypoint, Map controlPointCache, MarkPositionFinder positionFinder, TimePoint timePoint) { ControlPointDTO cp = controlPointCache.get(waypoint.getControlPoint().getId()); if (cp == null) { @@ -6917,6 +5084,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * the mark positions and attach to the {@link MarkDTO}s. If null, the current time point * will be used as default. */ + //READ private RaceCourseDTO convertToRaceCourseDTO(CourseBase course, MarkPositionFinder positionFinder, TimePoint timePoint) { final RaceCourseDTO result; if (course != null) { @@ -6933,6 +5101,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public RaceCourseDTO getLastCourseDefinitionInRaceLog(final String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { final RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); getSecurityService().checkCurrentUserReadPermission(getLeaderboardByName(leaderboardName)); @@ -6949,51 +5118,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet }, /* timePoint */ MillisecondsTimePoint.now()); } - @Override - public void pingMark(String leaderboardName, - MarkDTO markDTO, TimePoint timePoint, Position positionDTO) - throws DoesNotHaveRegattaLogException, NotFoundException { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); - final RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); - final Mark mark = convertToMark(markDTO, true); - final TimePoint time = timePoint == null ? MillisecondsTimePoint.now() : timePoint; - final Position position = positionDTO; - final GPSFix fix = new GPSFixImpl(position, time); - getRaceLogTrackingAdapter().pingMark(regattaLog, mark, fix, getService()); - } - - @Override - public void copyCourseToOtherRaceLogs(com.sap.sse.common.Util.Triple fromTriple, - Set> toTriples, int priority) throws NotFoundException { - getSecurityService().checkCurrentUserReadPermission(getLeaderboardByName(fromTriple.getA())); - for (com.sap.sse.common.Util.Triple toTriple : toTriples) { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(toTriple.getA())); - } - RaceLog fromRaceLog = getRaceLog(fromTriple); - Set toRaceLogs = new HashSet<>(); - for (com.sap.sse.common.Util.Triple toTriple : toTriples) { - toRaceLogs.add(getRaceLog(toTriple)); - } - getRaceLogTrackingAdapter().copyCourse(fromRaceLog, toRaceLogs, baseDomainFactory, getService(), priority); - } - - @Override - public void copyCompetitorsToOtherRaceLogs(com.sap.sse.common.Util.Triple fromTriple, - Set> toTriples) throws NotFoundException { - getSecurityService().checkCurrentUserReadPermission(getLeaderboardByName(fromTriple.getA())); - for (com.sap.sse.common.Util.Triple toTriple : toTriples) { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(toTriple.getA())); - } - final RaceColumn raceColumn = getRaceColumn(fromTriple.getA(), fromTriple.getB()); - final Set> toRaces = new HashSet<>(); - for (com.sap.sse.common.Util.Triple toTriple : toTriples) { - final RaceColumn toRaceColumn = getRaceColumn(toTriple.getA(), toTriple.getB()); - final Fleet toFleet = getFleetByName(toRaceColumn, toTriple.getC()); - toRaces.add(new Pair<>(toRaceColumn, toFleet)); - } - getRaceLogTrackingAdapter().copyCompetitors(raceColumn, getFleetByName(raceColumn, fromTriple.getC()), toRaces); - } - + //READ private TypeBasedServiceFinder getDeviceIdentifierStringSerializerHandlerFinder( boolean withFallback) { TypeBasedServiceFinderFactory factory = getService().getTypeBasedServiceFinderFactory(); @@ -7004,6 +5129,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return finder; } + //READ private DeviceIdentifier deserializeDeviceIdentifier(String type, String deviceId) throws NoCorrespondingServiceRegisteredException, TransformationException { DeviceIdentifierStringSerializationHandler handler = @@ -7011,11 +5137,13 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return handler.deserialize(deviceId, type, deviceId); } + //READ private String serializeDeviceIdentifier(DeviceIdentifier deviceId) throws TransformationException { return getDeviceIdentifierStringSerializerHandlerFinder(true).findService( deviceId.getIdentifierType()).serialize(deviceId).getB(); } + //READ private DeviceMappingDTO convertToDeviceMappingDTO(DeviceMapping mapping) throws TransformationException { final Map lastFixes = getService().getSensorFixStore().getFixLastReceived(Collections.singleton(mapping.getDevice())); final Timed lastFix; @@ -7059,7 +5187,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet deviceId), from, to, item, originalRaceLogEventUUIDs, lastFix==null?null:lastFix.getTimePoint()); } - private List> getLogHierarchy(String leaderboardName, String raceColumnName, + //READ + protected List> getLogHierarchy(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { List> result = new ArrayList<>(); RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); @@ -7075,6 +5204,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private List getDeviceMappings(RegattaLog regattaLog) throws TransformationException { List result = new ArrayList(); @@ -7088,66 +5218,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public void addDeviceMappingToRegattaLog(String leaderboardName, - DeviceMappingDTO dto) throws NoCorrespondingServiceRegisteredException, TransformationException, DoesNotHaveRegattaLogException { - SecurityUtils.getSubject().checkPermission(SecuredDomainType.REGATTA.getStringPermissionForObject( - DefaultActions.UPDATE, getService().getRegattaByName(leaderboardName))); - RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); - DeviceMapping mapping = convertToDeviceMapping(dto); - TimePoint now = MillisecondsTimePoint.now(); - RegattaLogEvent event = null; - TimePoint from = mapping.getTimeRange().hasOpenBeginning() ? null : mapping.getTimeRange().from(); - TimePoint to = mapping.getTimeRange().hasOpenEnd() ? null : mapping.getTimeRange().to(); - if (mapping.getMappedTo() instanceof Mark) { - Mark mark = (Mark) mapping.getMappedTo(); - event = new RegattaLogDeviceMarkMappingEventImpl(now, now, getService().getServerAuthor(), UUID.randomUUID(), - mark, mapping.getDevice(), from, to); - } else if (mapping.getMappedTo() instanceof Competitor) { - Competitor competitor = (Competitor) mapping.getMappedTo(); - if (mapping.getDevice().getIdentifierType().equals(ExpeditionSensorDeviceIdentifier.TYPE)) { - event = new RegattaLogDeviceCompetitorExpeditionExtendedMappingEventImpl( - now, now, getService().getServerAuthor(), UUID.randomUUID(), - competitor, mapping.getDevice(), from, to); - } else { - event = new RegattaLogDeviceCompetitorMappingEventImpl(now, now, getService().getServerAuthor(), UUID.randomUUID(), - competitor, mapping.getDevice(), from, to); - } - } else if (mapping.getMappedTo() instanceof Boat) { - final Boat boat = (Boat) mapping.getMappedTo(); - event = new RegattaLogDeviceBoatMappingEventImpl(now, now, getService().getServerAuthor(), UUID.randomUUID(), - boat, mapping.getDevice(), from, to); - } else { - throw new RuntimeException("Can only map devices to competitors, boats or marks"); - } - regattaLog.add(event); - } - - @Override - public void addTypedDeviceMappingToRegattaLog(String leaderboardName, TypedDeviceMappingDTO dto) - throws NoCorrespondingServiceRegisteredException, TransformationException, DoesNotHaveRegattaLogException, - NotFoundException { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); - RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); - DeviceMapping mapping = convertToDeviceMapping(dto); - TimePoint now = MillisecondsTimePoint.now(); - RegattaLogEvent event = null; - TimePoint from = mapping.getTimeRange().hasOpenBeginning() ? null : mapping.getTimeRange().from(); - TimePoint to = mapping.getTimeRange().hasOpenEnd() ? null : mapping.getTimeRange().to(); - if (dto.mappedTo instanceof CompetitorWithBoatDTO) { - DoubleVectorFixImporter importer = getRegisteredImporter(DoubleVectorFixImporter.class, dto.dataType); - event = importer.createEvent(now, now, getService().getServerAuthor(), UUID.randomUUID(), - getCompetitor((CompetitorWithBoatDTO) dto.mappedTo), mapping.getDevice(), from, to); - } else if (dto.mappedTo instanceof BoatDTO) { - DoubleVectorFixImporter importer = getRegisteredImporter(DoubleVectorFixImporter.class, dto.dataType); - event = importer.createEvent(now, now, getService().getServerAuthor(), UUID.randomUUID(), - getBoat((BoatDTO) dto.mappedTo), mapping.getDevice(), from, to); - } else { - throw new RuntimeException("Can only map devices to a competitor or boat"); - } - regattaLog.add(event); - } - - @Override + //READ public List getDeserializableDeviceIdentifierTypes() { List result = new ArrayList(); for (ServiceReference reference : @@ -7157,7 +5228,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } - private DeviceMapping convertToDeviceMapping(DeviceMappingDTO dto) + //READ + protected DeviceMapping convertToDeviceMapping(DeviceMappingDTO dto) throws NoCorrespondingServiceRegisteredException, TransformationException { DeviceIdentifier device = deserializeDeviceIdentifier(dto.deviceIdentifier.deviceType, dto.deviceIdentifier.deviceId); TimePoint from = dto.from == null ? null : new MillisecondsTimePoint(dto.from); @@ -7181,107 +5253,19 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } } - private void closeOpenEndedDeviceMapping(RegattaLog regattaLog, DeviceMappingDTO mappingDTO, Date closingTimePoint) throws TransformationException, UnableToCloseDeviceMappingException { - boolean successfullyClosed = false; - List closingEvents = null; - regattaLog.lockForRead(); - try { - RegattaLogEvent event = regattaLog.getEventById(mappingDTO.originalRaceLogEventIds.get(0)); - if (event != null) { - successfullyClosed = true; - DeviceMapping mapping = convertToDeviceMapping(mappingDTO); - closingEvents = new RegattaLogOpenEndedDeviceMappingCloser(regattaLog, mapping, getService().getServerAuthor(), - new MillisecondsTimePoint(closingTimePoint)).analyze(); - } - } finally { - regattaLog.unlockAfterRead(); - } - // important: read lock must be release before write lock is obtained in add(...); see bug 3774 - if (successfullyClosed) { - for (RegattaLogEvent closingEvent : closingEvents) { - regattaLog.add(closingEvent); - } - } else { - throw new UnableToCloseDeviceMappingException(); - } - } - - @Override - public void revokeRaceAndRegattaLogEvents(String leaderboardName, String raceColumnName, String fleetName, - List eventIds) throws NotRevokableException, NotFoundException { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); - List> logs = getLogHierarchy(leaderboardName, raceColumnName, fleetName); - revokeEventsFromLogs(logs, eventIds); - } - - @Override - public void revokeRaceAndRegattaLogEvents(String leaderboardName, - List eventIds) throws NotRevokableException, DoesNotHaveRegattaLogException, NotFoundException { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); - List> logs = getLogHierarchy(leaderboardName); - revokeEventsFromLogs(logs, eventIds); - } - - private void revokeEventsFromLogs(List> logs, List eventIds) throws NotRevokableException{ - boolean eventRevoked = false; - for (Serializable idToRevoke : eventIds) { - eventRevoked = false; - for (AbstractLog abstractLog : logs) { - eventRevoked = revokeEvent(eventRevoked, idToRevoke, abstractLog); - } - if (!eventRevoked){ - logger.warning("Could not revoke event with id "+idToRevoke); - } - } - } - - private , VisitorT> boolean revokeEvent(boolean eventRevoked, Serializable idToRevoke, AbstractLog abstractLog) - throws NotRevokableException { - final EventT event; - abstractLog.lockForRead(); - try { - event = abstractLog.getEventById(idToRevoke); - } finally { - abstractLog.unlockAfterRead(); - } - if (event != null) { - abstractLog.revokeEvent(getService().getServerAuthor(), event, "revoke triggered by GWT user action"); - eventRevoked = true; - } - return eventRevoked; - } - - @Override - public void startRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName, final boolean trackWind, final boolean correctWindByDeclination) - throws NotDenotedForRaceLogTrackingException, Exception { - // no permission checks needed here, since they already exist in PermissionAwareRaceTrackingHandler - Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - Fleet fleet = raceColumn.getFleetByName(fleetName); - getRaceLogTrackingAdapter().startTracking(getService(), leaderboard, raceColumn, fleet, trackWind, correctWindByDeclination, - getService().getPermissionAwareRaceTrackingHandler()); - } - - @Override - public void startRaceLogTracking(List> leaderboardRaceColumnFleetNames, - final boolean trackWind, final boolean correctWindByDeclination) - throws NotDenotedForRaceLogTrackingException, Exception { - for (final Triple leaderboardRaceColumnFleetName : leaderboardRaceColumnFleetNames) { - startRaceLogTracking(leaderboardRaceColumnFleetName.getA(), leaderboardRaceColumnFleetName.getB(), - leaderboardRaceColumnFleetName.getC(), trackWind, correctWindByDeclination); - } - } - @Override + //READ public Collection getGPSFixImporterTypes() { return getRegisteredImporterTypes(GPSFixImporter.class); } @Override + //READ public Collection getSensorDataImporterTypes() { return getRegisteredImporterTypes(DoubleVectorFixImporter.class); } + //READ private Collection getRegisteredImporterTypes(Class referenceClass) { Set result = new HashSet<>(); for (ServiceReference reference : getRegisteredServiceReferences(referenceClass)) { @@ -7290,7 +5274,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } - private S getRegisteredImporter(Class referenceClass, String type) + //READ + protected S getRegisteredImporter(Class referenceClass, String type) throws NoCorrespondingServiceRegisteredException { for (ServiceReference reference : getRegisteredServiceReferences(referenceClass)) { S importer = Activator.getDefault().getService(reference); @@ -7301,6 +5286,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet throw new NoCorrespondingServiceRegisteredException("No importer service found!", type, referenceClass.getName()); } + //READ private Collection> getRegisteredServiceReferences(Class referenceClass) { try { return Activator.getDefault().getServiceReferences(referenceClass, null); @@ -7311,6 +5297,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List getTrackFileImportDeviceIds(List uuids) throws NoCorrespondingServiceRegisteredException, TransformationException { try { @@ -7333,17 +5320,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public RaceDTO setStartTimeReceivedForRace(RaceIdentifier raceIdentifier, Date newStartTimeReceived) { - RegattaNameAndRaceName regattaAndRaceIdentifier = new RegattaNameAndRaceName(raceIdentifier.getRegattaName(), - raceIdentifier.getRaceName()); - DynamicTrackedRace trackedRace = getService().getTrackedRace(regattaAndRaceIdentifier); - getSecurityService().checkCurrentUserUpdatePermission(trackedRace); - trackedRace.setStartTimeReceived( - newStartTimeReceived == null ? null : new MillisecondsTimePoint(newStartTimeReceived)); - return baseDomainFactory.createRaceDTO(getService(), false, regattaAndRaceIdentifier, trackedRace); - } - - @Override + //READ public ArrayList getEventsForLeaderboard(String leaderboardName) { Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); HashMap events = new HashMap<>(); @@ -7360,6 +5337,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Map getCompetitorRaceLogMarkPassingData(String leaderboardName, String raceColumnName, String fleetName, CompetitorDTO competitor) throws NotFoundException { Map result = new HashMap<>(); @@ -7380,94 +5358,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public void updateFixedMarkPassing(String leaderboardName, String raceColumnName, String fleetName, Integer indexOfWaypoint, - Date dateOfMarkPassing, CompetitorDTO competitorDTO) throws NotFoundException { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); - final RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); - final Competitor competitor = getCompetitor(competitorDTO); - RaceLogFixedMarkPassingEvent oldFixedMarkPassingEvent = null; - raceLog.lockForRead(); - try { - for (RaceLogEvent event : raceLog.getUnrevokedEvents()) { - if (event instanceof RaceLogFixedMarkPassingEventImpl && event.getInvolvedCompetitors().contains(competitor)) { - RaceLogFixedMarkPassingEvent fixedEvent = (RaceLogFixedMarkPassingEvent) event; - if (Util.equalsWithNull(fixedEvent.getZeroBasedIndexOfPassedWaypoint(), indexOfWaypoint)) { - oldFixedMarkPassingEvent = fixedEvent; - } - } - } - } finally { - raceLog.unlockAfterRead(); - } - if (oldFixedMarkPassingEvent != null) { - try { - raceLog.revokeEvent(getService().getServerAuthor(), oldFixedMarkPassingEvent); - } catch (NotRevokableException e) { - e.printStackTrace(); - } - } - if (dateOfMarkPassing != null) { - raceLog.add(new RaceLogFixedMarkPassingEventImpl(MillisecondsTimePoint.now(), getService() - .getServerAuthor(), competitor, raceLog.getCurrentPassId(), - new MillisecondsTimePoint(dateOfMarkPassing), indexOfWaypoint)); - } - } - - @Override - public void updateSuppressedMarkPassings(String leaderboardName, String raceColumnName, String fleetName, - Integer newZeroBasedIndexOfSuppressedMarkPassing, CompetitorDTO competitorDTO) throws NotFoundException { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); - RaceLogSuppressedMarkPassingsEvent oldSuppressedMarkPassingEvent = null; - final RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); - final Competitor competitor = getCompetitor(competitorDTO); - raceLog.lockForRead(); - try { - final NavigableSet unrevokedEvents = raceLog.getUnrevokedEvents(); - for (RaceLogEvent event : unrevokedEvents) { - if (event instanceof RaceLogSuppressedMarkPassingsEvent && event.getInvolvedCompetitors().contains(competitor)) { - oldSuppressedMarkPassingEvent = (RaceLogSuppressedMarkPassingsEvent) event; - break; - } - } - } finally { - raceLog.unlockAfterRead(); - } - final boolean create; - final boolean revoke; - if (oldSuppressedMarkPassingEvent == null) { - if (newZeroBasedIndexOfSuppressedMarkPassing == null) { - create = false; - revoke = false; - } else { - create = true; - revoke = false; - } - } else { - if (newZeroBasedIndexOfSuppressedMarkPassing == null) { - revoke = true; - create = false; - } else { - boolean equal = Util.equalsWithNull(newZeroBasedIndexOfSuppressedMarkPassing, - oldSuppressedMarkPassingEvent.getZeroBasedIndexOfFirstSuppressedWaypoint()); - create = !equal; - revoke = !equal; - } - } - if (revoke) { - try { - raceLog.revokeEvent(getService().getServerAuthor(), oldSuppressedMarkPassingEvent); - } catch (NotRevokableException e) { - logger.log(Level.SEVERE, "Unable to revoke event "+oldSuppressedMarkPassingEvent, e); - } - } - if (create) { - raceLog.add(new RaceLogSuppressedMarkPassingsEventImpl(MillisecondsTimePoint.now(), getService() - .getServerAuthor(), competitor, raceLog.getCurrentPassId(), - newZeroBasedIndexOfSuppressedMarkPassing)); - } - } - - @Override + //READ public Map getCompetitorMarkPassings(RegattaAndRaceIdentifier race, CompetitorDTO competitorDTO, boolean waitForCalculations) { Map result = new HashMap<>(); final TrackedRace trackedRace = getExistingTrackedRace(race); @@ -7486,163 +5377,16 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } - @Override - public PolarSheetsXYDiagramData createXYDiagramForBoatClass(String boatClassName) { - BoatClass boatClass = getService().getBaseDomainFactory().getOrCreateBoatClass(boatClassName); - Map, List>> regressionSpeedDataLists = new HashMap<>(); - for (LegType legType : new LegType[] { LegType.UPWIND, LegType.DOWNWIND }) { - for (Tack tack : new Tack[] { Tack.PORT, Tack.STARBOARD }) { - regressionSpeedDataLists.put(new Pair(legType, tack), - new ArrayList>()); - } - } - for (double windInKnots = 0.1; windInKnots < 30; windInKnots = windInKnots + 0.1) { - for (LegType legType : new LegType[] { LegType.UPWIND, LegType.DOWNWIND }) { - for (Tack tack : new Tack[] { Tack.PORT, Tack.STARBOARD }) { - try { - SpeedWithBearingWithConfidence averageUpwindStarboardRegression = getService() - .getPolarDataService().getAverageSpeedWithBearing(boatClass, - new KnotSpeedImpl(windInKnots), legType, tack); - - regressionSpeedDataLists.get(new Pair(legType, tack)).add( - new Pair(windInKnots, averageUpwindStarboardRegression.getObject() - .getKnots())); - } catch (NotEnoughDataHasBeenAddedException e) { - // Do not add a point to the result - } - } - } - } - - PolarSheetsXYDiagramData data = new PolarSheetsXYDiagramDataImpl(regressionSpeedDataLists); - - return data; - } - - private FileStorageService getFileStorageService(String name) { - if (name == null || name.equals("")) { - return null; - } - return getService().getFileStorageManagementService().getFileStorageService(name); - } - - private Locale getLocale(String localeInfoName) { + protected Locale getLocale(String localeInfoName) { return ResourceBundleStringMessages.Util.getLocaleFor(localeInfoName); } - @Override - public FileStorageServiceDTO[] getAvailableFileStorageServices(String localeInfoName) { - List serviceDtos = new ArrayList<>(); - final FileStorageManagementService fileStorageManagementService = getService().getFileStorageManagementService(); - if (fileStorageManagementService != null) { - for (FileStorageService s : fileStorageManagementService.getAvailableFileStorageServices()) { - serviceDtos.add(FileStorageServiceDTOUtils.convert(s, getLocale(localeInfoName))); - } - } - return serviceDtos.toArray(new FileStorageServiceDTO[0]); - } - - @Override - public void setFileStorageServiceProperties(String serviceName, Map properties) { - getSecurityService().checkCurrentUserUpdatePermission(getServerInfo()); - for (Entry p : properties.entrySet()) { - try { - getService().getFileStorageManagementService() - .setFileStorageServiceProperty(getFileStorageService(serviceName), p.getKey(), p.getValue()); - } catch (NoCorrespondingServiceRegisteredException | IllegalArgumentException e) { - //ignore, doing refresh afterwards anyways - } - } - } - - @Override - public FileStorageServicePropertyErrorsDTO testFileStorageServiceProperties(String serviceName, String localeInfoName) throws IOException { - try { - if (serviceName == null) { - serviceName = getActiveFileStorageServiceName(); - } - FileStorageService service = getFileStorageService(serviceName); - if (service != null) { - service.testProperties(); - } - } catch (InvalidPropertiesException e) { - return FileStorageServiceDTOUtils.convert(e, getLocale(localeInfoName)); - } - return null; - } - - @Override - public void setActiveFileStorageService(String serviceName, String localeInfoName) { - getSecurityService().checkCurrentUserUpdatePermission(getServerInfo()); - getService().getFileStorageManagementService().setActiveFileStorageService(getFileStorageService(serviceName)); - } - - @Override - public String getActiveFileStorageServiceName() { - try { - final FileStorageService activeFileStorageService = getService().getFileStorageManagementService().getActiveFileStorageService(); - return activeFileStorageService == null ? null : activeFileStorageService.getName(); - } catch (NoCorrespondingServiceRegisteredException e) { - return null; - } - } - - @Override - public void inviteCompetitorsForTrackingViaEmail(String serverUrlWithoutTrailingSlash, EventDTO eventDto, - String leaderboardName, Collection competitorDtos, String iOSAppUrl, String androidAppUrl, - String localeInfoName) throws MailException { - Event event = getService().getEvent(eventDto.id); - getSecurityService().checkCurrentUserReadPermission(event); - Set competitors = new HashSet<>(); - for (CompetitorDTO c : competitorDtos) { - competitors.add(getCompetitor(c)); - } - Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - getSecurityService().checkCurrentUserUpdatePermission(leaderboard); - Regatta regatta = getService().getRegattaByName(leaderboardName); - getSecurityService().checkCurrentUserUpdatePermission(regatta); - getRaceLogTrackingAdapter().inviteCompetitorsForTrackingViaEmail(event, leaderboard, regatta, - serverUrlWithoutTrailingSlash, - competitors, iOSAppUrl, androidAppUrl, getLocale(localeInfoName), getMailType()); - } - - @Override - public void inviteBuoyTenderViaEmail(String serverUrlWithoutTrailingSlash, EventDTO eventDto, - String leaderboardName, String emails, String iOSAppUrl, String androidAppUrl, String localeInfoName) - throws MailException { - Event event = getService().getEvent(eventDto.id); - getSecurityService().checkCurrentUserReadPermission(event); - Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - getSecurityService().checkCurrentUserReadPermission(leaderboard); - Regatta regatta = getService().getRegattaByName(leaderboardName); - getSecurityService().checkCurrentUserUpdatePermission(regatta); - MailInvitationType type = MailInvitationType - .valueOf(System.getProperty(MAILTYPE_PROPERTY, MailInvitationType.SailInsight1.name())); - getRaceLogTrackingAdapter().inviteBuoyTenderViaEmail(event, leaderboard, regatta, serverUrlWithoutTrailingSlash, - emails, iOSAppUrl, androidAppUrl, getLocale(localeInfoName), type); - } - - @Override - public ArrayList getLeaderboardGroupsByEventId(UUID id) { - Event event = getService().getEvent(id); - if (event == null) { - throw new RuntimeException("Event not found"); - } - - ArrayList result = new ArrayList<>(); - for (LeaderboardGroup lg : event.getLeaderboardGroups()) { - if (getSecurityService().hasCurrentUserReadPermission(lg)) { - result.add(convertToLeaderboardGroupDTO(lg, /* withGeoLocationData */false, true)); - } - } - return result; - } - /** * Gets all Marks defined in the RegattaLog and the trackedRace * @throws DoesNotHaveRegattaLogException */ @Override + //READ public Iterable getMarksInRegattaLog(String leaderboardName) throws DoesNotHaveRegattaLogException { final Leaderboard l = getService().getLeaderboardByName(leaderboardName); getSecurityService().checkCurrentUserReadPermission(l); @@ -7660,21 +5404,13 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return markDTOs; } - @Override - public void closeOpenEndedDeviceMapping(String leaderboardName, DeviceMappingDTO mappingDTO, Date closingTimePoint) - throws TransformationException, DoesNotHaveRegattaLogException, UnableToCloseDeviceMappingException, - NotFoundException { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); - RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); - closeOpenEndedDeviceMapping(regattaLog, mappingDTO, closingTimePoint); - } - /** * Gets all the logs corresponding to a leaderboard. This includes all the RaceLogs of the leaderBoard's raceColumns * @param leaderboardName * @return */ - private List> getLogHierarchy(String leaderboardName) { + //READ + protected List> getLogHierarchy(String leaderboardName) { final List> result; Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); if (leaderboard == null) { @@ -7694,6 +5430,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ public boolean doesRegattaLogContainCompetitors(String leaderboardName) throws DoesNotHaveRegattaLogException, NotFoundException { getSecurityService().checkCurrentUserReadPermission(getLeaderboardByName(leaderboardName)); @@ -7704,6 +5441,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public RegattaAndRaceIdentifier getRaceIdentifier(String regattaLikeName, String raceColumnName, String fleetName) { RegattaAndRaceIdentifier result = null; final Leaderboard leaderboard = getService().getLeaderboardByName(regattaLikeName); @@ -7725,6 +5463,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Collection getCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { getSecurityService().checkCurrentUserReadPermission(getLeaderboardByName(leaderboardName)); @@ -7734,6 +5473,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Collection getCompetitorRegistrationsForLeaderboard(String leaderboardName) throws NotFoundException { Leaderboard leaderboard = getLeaderboardByName(leaderboardName); getSecurityService().checkCurrentUserReadPermission(leaderboard); @@ -7741,6 +5481,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Collection getCompetitorRegistrationsInRegattaLog(String leaderboardName) throws DoesNotHaveRegattaLogException, NotFoundException { Leaderboard leaderboard = getLeaderboardByName(leaderboardName); getSecurityService().checkCurrentUserReadPermission(leaderboard); @@ -7752,6 +5493,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List getCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { getSecurityService().checkCurrentUserReadPermission(getLeaderboardByName(leaderboardName)); @@ -7761,6 +5503,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Map getCompetitorAndBoatRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { getSecurityService().checkCurrentUserReadPermission(getLeaderboardByName(leaderboardName)); @@ -7771,6 +5514,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Collection getBoatRegistrationsInRegattaLog(String leaderboardName) throws DoesNotHaveRegattaLogException, NotFoundException { Leaderboard leaderboard = getLeaderboardByName(leaderboardName); getSecurityService().checkCurrentUserReadPermission(leaderboard); @@ -7782,32 +5526,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public void setBoatRegistrationsInRegattaLog(String leaderboardName, Set boatDTOs) - throws DoesNotHaveRegattaLogException, NotFoundException { - Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - getSecurityService().checkCurrentUserUpdatePermission(leaderboard); - if (!(leaderboard instanceof HasRegattaLike)){ - throw new DoesNotHaveRegattaLogException(); - } - - Set boatsToRegister = new HashSet(); - for (BoatDTO dto : boatDTOs) { - final Boat boat = getBoat(dto); - getSecurityService().checkCurrentUserReadPermission(boat); - boatsToRegister.add(boat); - } - - HasRegattaLike hasRegattaLike = (HasRegattaLike) leaderboard; - Iterable boatsToRemove = leaderboard.getAllBoats(); - HashSet boatSetToRemove = new HashSet<>(); - Util.addAll(boatsToRemove, boatSetToRemove); - filterBoatDuplicates(boatsToRegister, boatSetToRemove); - - hasRegattaLike.deregisterBoats(boatSetToRemove); - hasRegattaLike.registerBoats(boatsToRegister); - } - - @Override + //READ public Collection getBoatRegistrationsForLeaderboard(String leaderboardName) throws NotFoundException { Leaderboard leaderboard = getLeaderboardByName(leaderboardName); getSecurityService().checkCurrentUserReadPermission(leaderboard); @@ -7815,6 +5534,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Collection getBoatRegistrationsForRegatta(RegattaIdentifier regattaIdentifier) throws NotFoundException { final Regatta regatta = (Regatta) regattaIdentifier.getRegatta(getService()); if (regatta == null) { @@ -7825,6 +5545,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Boolean areCompetitorRegistrationsEnabledForRace(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); @@ -7832,7 +5553,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return raceColumn.isCompetitorRegistrationInRacelogEnabled(fleet); } - private Fleet getFleetByName(RaceColumn raceColumn, String fleetName) throws NotFoundException{ + //READ + protected Fleet getFleetByName(RaceColumn raceColumn, String fleetName) throws NotFoundException{ Fleet fleet = raceColumn.getFleetByName(fleetName); if (fleet == null){ throw new NotFoundException("fleet with name "+fleetName+" not found"); @@ -7840,7 +5562,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return fleet; } - private Leaderboard getLeaderboardByName(String leaderboardName) throws NotFoundException{ + //READ + protected Leaderboard getLeaderboardByName(String leaderboardName) throws NotFoundException{ Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); if (leaderboard == null){ throw new NotFoundException("Leaderboard with name "+leaderboardName+" not found"); @@ -7848,7 +5571,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return leaderboard; } - private RaceColumn getRaceColumn(String leaderboardName, String raceColumnName) throws NotFoundException{ + //READ + protected RaceColumn getRaceColumn(String leaderboardName, String raceColumnName) throws NotFoundException{ Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); if (leaderboard == null){ throw new NotFoundException("leaderboard with name "+leaderboardName+" not found"); @@ -7861,24 +5585,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public void disableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) throws NotRevokableException, NotFoundException { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); - if (areCompetitorRegistrationsEnabledForRace(leaderboardName, raceColumnName, fleetName)) { - RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); - raceColumn.disableCompetitorRegistrationOnRaceLog(getFleetByName(raceColumn, fleetName)); - } - } - - @Override - public void enableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) throws IllegalArgumentException, NotFoundException { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); - if (!areCompetitorRegistrationsEnabledForRace(leaderboardName, raceColumnName, fleetName)){ - RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); - raceColumn.enableCompetitorRegistrationOnRaceLog(getFleetByName(raceColumn, fleetName)); - } - } - - @Override + //READ public Pair checkIfMarksAreUsedInOtherRaceLogs(String leaderboardName, String raceColumnName, String fleetName, Set marksToRemove) throws NotFoundException { Set markIds = new HashSet(); @@ -7918,6 +5625,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List getDeviceMappings(String leaderboardName) throws DoesNotHaveRegattaLogException, TransformationException, NotFoundException { getSecurityService().checkCurrentUserReadPermission(getLeaderboardByName(leaderboardName)); @@ -7926,6 +5634,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Iterable getMarksInTrackedRace(String leaderboardName, String raceColumnName, String fleetName) { final List marks = new ArrayList<>(); final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); @@ -7944,16 +5653,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return marks; } - @Override - public MarkTracksDTO getMarkTracks(String leaderboardName, String raceColumnName, String fleetName) { - final List markTracks = new ArrayList<>(); - for (final MarkDTO mark : getMarksInTrackedRace(leaderboardName, raceColumnName, fleetName)) { - MarkTrackDTO markTrackDTO = getMarkTrack(leaderboardName, raceColumnName, fleetName, mark.getIdAsString()); - markTracks.add(markTrackDTO); - } - return new MarkTracksDTO(markTracks); - } - + //READ private MarkTrackDTO getMarkTrack(Leaderboard leaderboard, RaceColumn raceColumn, Fleet fleet, String markIdAsString) { getSecurityService().checkCurrentUserReadPermission(leaderboard); @@ -8007,6 +5707,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public MarkTrackDTO getMarkTrack(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString) { final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); if (leaderboard != null) { @@ -8025,6 +5726,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * Uses all fixed from {@code track} with the outliers removed, {@link #convertToGPSFixDTO(GPSFix) converts} each * of them to a {@link GPSFixDTO} and adds them to the resulting list. */ + //READ private Iterable convertToGPSFixDTOTrack(Track track) { final List result = new ArrayList<>(); track.lockForRead(); @@ -8038,6 +5740,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private GPSFixDTO convertToGPSFixDTO(GPSFix fix) { final GPSFixDTO result; if (fix == null) { @@ -8049,6 +5752,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public boolean canRemoveMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, GPSFixDTO fix) { boolean result = false; @@ -8077,75 +5781,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public void removeMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, GPSFixDTO fix) throws NotRevokableException { - final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - getSecurityService().checkCurrentUserUpdatePermission(leaderboard); - if (leaderboard != null) { - final RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - if (raceColumn != null) { - final TimePoint fixTimePoint = new MillisecondsTimePoint(fix.timepoint); - final RegattaLog regattaLog = raceColumn.getRegattaLog(); - final BaseRegattaLogDeviceMappingFinder mappingFinder = new RegattaLogDeviceMarkMappingFinder(regattaLog); - final Fleet fleet = raceColumn.getFleetByName(fleetName); - if (fleet != null) { - for (final Mark mark : raceColumn.getAvailableMarks(fleet)) { - if (mark.getId().toString().equals(markIdAsString)) { - mappingFinder.removeTimePointFromMapping(mark, fixTimePoint); - } - } - } - } - } - } - - @Override - public void addMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, GPSFixDTO newFix) { - final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - if (leaderboard != null) { - final RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - if (raceColumn != null) { - final RegattaLog regattaLog = raceColumn.getRegattaLog(); - final Fleet fleet = raceColumn.getFleetByName(fleetName); - if (fleet != null) { - for (final Mark mark : raceColumn.getAvailableMarks(fleet)) { - if (mark.getId().toString().equals(markIdAsString)) { - getRaceLogTrackingAdapter().pingMark(regattaLog, mark, - new GPSFixImpl(newFix.position, new MillisecondsTimePoint(newFix.timepoint)), - getService()); - } - } - } - } - } - } - - @Override - public void editMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, - GPSFixDTO oldFix, Position newPosition) throws NotRevokableException { - final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - getSecurityService().checkCurrentUserUpdatePermission(leaderboard); - if (leaderboard != null) { - final RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); - if (raceColumn != null) { - final RegattaLog regattaLog = raceColumn.getRegattaLog(); - final BaseRegattaLogDeviceMappingFinder mappingFinder = new RegattaLogDeviceMarkMappingFinder( - regattaLog); - final Fleet fleet = raceColumn.getFleetByName(fleetName); - if (fleet != null) { - final TimePoint fixTimePoint = new MillisecondsTimePoint(oldFix.timepoint); - for (final Mark mark : raceColumn.getAvailableMarks(fleet)) { - if (mark.getId().toString().equals(markIdAsString)) { - mappingFinder.removeTimePointFromMapping(mark, fixTimePoint); - getRaceLogTrackingAdapter().pingMark(regattaLog, mark, - new GPSFixImpl(newPosition, fixTimePoint), getService()); - } - } - } - } - } - } - - @Override + //READ public Map, Pair> getTrackingTimes( Collection> leaderboardRaceColumnFleetNames) { Map, Pair> trackingTimes = new HashMap<>(); @@ -8161,6 +5797,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Collection getEliminatedCompetitors(String leaderboardName) { final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); getSecurityService().checkCurrentUserReadPermission(leaderboard); @@ -8172,18 +5809,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public void setEliminatedCompetitors(String leaderboardName, Set newEliminatedCompetitorDTOs) - throws NotFoundException { - getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); - Set newEliminatedCompetitors = new HashSet<>(); - for (final CompetitorDTO cDTO : newEliminatedCompetitorDTOs) { - final Competitor competitor = getCompetitor(cDTO); - newEliminatedCompetitors.add(competitor); - } - getService().apply(new UpdateEliminatedCompetitorsInLeaderboard(leaderboardName, newEliminatedCompetitors)); - } - - @Override + //READ public Iterable determineDetailTypesForCompetitorChart(String leaderboardGroupName, RegattaAndRaceIdentifier identifier) { final LinkedHashSet availableDetailTypes = new LinkedHashSet<>(); availableDetailTypes.addAll(DetailType.getAutoplayDetailTypesForChart()); @@ -8233,15 +5859,15 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List getExpeditionDeviceConfigurations() { final List result = new ArrayList<>(); final ExpeditionTrackerFactory expeditionConnector = expeditionConnectorTracker.getService(); final Subject subject = SecurityUtils.getSubject(); if (expeditionConnector != null) { for (final ExpeditionDeviceConfiguration config : expeditionConnector.getDeviceConfigurations()) { - if (subject.isPermitted( - SecuredDomainType.EXPEDITION_DEVICE_CONFIGURATION.getStringPermissionForTypeRelativeIdentifier( - DefaultActions.READ, config.getTypeRelativeObjectIdentifier(ServerInfo.getName())))) { + if (subject.isPermitted(config.getIdentifier().getStringPermission(DefaultActions.READ))) { + SecurityDTOUtil.addSecurityInformation(getSecurityService(), config, config.getIdentifier()); result.add(config); } } @@ -8250,37 +5876,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public void addOrReplaceExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration deviceConfiguration) { - getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError(SecuredDomainType.EXPEDITION_DEVICE_CONFIGURATION, - new TypeRelativeObjectIdentifier(ServerInfo.getName(), deviceConfiguration.getName()), - /* display name */ ServerInfo.getName() + "/" + deviceConfiguration.getName(), - () -> { - // TODO consider replication - final ExpeditionTrackerFactory expeditionConnector = expeditionConnectorTracker.getService(); - if (expeditionConnector != null) { - expeditionConnector.addOrReplaceDeviceConfiguration(deviceConfiguration); - } - }); - } - - @Override - public void removeExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration deviceConfiguration) { - QualifiedObjectIdentifier identifier = deviceConfiguration.getType().getQualifiedObjectIdentifier(deviceConfiguration.getTypeRelativeObjectIdentifier(ServerInfo.getName())); - getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(identifier, - new Callable() { - @Override - public Void call() throws Exception { - // TODO consider replication - final ExpeditionTrackerFactory expeditionConnector = expeditionConnectorTracker.getService(); - if (expeditionConnector != null) { - expeditionConnector.removeDeviceConfiguration(deviceConfiguration); - } - return null; - } - }); - } - - @Override + //READ public PairingListTemplateDTO calculatePairingListTemplate(final int flightCount, final int groupCount, final int competitorCount, final int flightMultiplier, final int tolerance) { PairingListTemplate template = getService().createPairingListTemplate(flightCount, groupCount, competitorCount, @@ -8290,6 +5886,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public PairingListDTO getPairingListFromTemplate(final String leaderboardName, final int flightMultiplier, final Iterable selectedRaceColumnNames, PairingListTemplateDTO templateDTO) throws NotFoundException, PairingListCreationException { @@ -8337,6 +5934,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public PairingListDTO getPairingListFromRaceLogs(final String leaderboardName) throws NotFoundException { Leaderboard leaderboard = getLeaderboardByName(leaderboardName); getSecurityService().checkCurrentUserReadPermission(leaderboard); @@ -8370,48 +5968,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return new PairingListDTO(result, raceColumnNames); } - @Override - public void fillRaceLogsFromPairingListTemplate(final String leaderboardName, final int flightMultiplier, - final Iterable selectedFlightNames, final PairingListDTO pairingListDTO) - throws NotFoundException, CompetitorRegistrationOnRaceLogDisabledException { - Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - getSecurityService().checkCurrentUserUpdatePermission(leaderboard); - int flightCount = 0; - int groupCount = 0; - for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { - if (Util.contains(selectedFlightNames, raceColumn.getName())) { - groupCount = 0; - for (Fleet fleet : raceColumn.getFleets()) { - raceColumn.enableCompetitorRegistrationOnRaceLog(fleet); - Map competitors = new HashMap<>(); - List> competitorsFromPairingList = pairingListDTO.getPairingList() - .get(flightCount).get(groupCount); - for (Pair competitorAndBoatPair : competitorsFromPairingList) { - if (competitorAndBoatPair.getA() != null && competitorAndBoatPair.getA().getName() != null) { - competitors.put(competitorAndBoatPair.getA(), competitorAndBoatPair.getB()); - } - } - this.setCompetitorRegistrationsInRaceLog(leaderboard.getName(), raceColumn.getName(), - fleet.getName(), competitors); - groupCount++; - } - flightCount++; - } else { - for (Fleet fleet : raceColumn.getFleets()) { - this.setCompetitorRegistrationsInRaceLog(leaderboard.getName(), raceColumn.getName(), - fleet.getName(), new HashSet()); - } - } - } - if (leaderboard instanceof LeaderboardThatHasRegattaLike && flightMultiplier > 1) { - final IsRegattaLike regattaLike = ((LeaderboardThatHasRegattaLike) leaderboard).getRegattaLike(); - logger.info("Updating regatta "+regattaLike.getRegattaLikeIdentifier().getName()+ - ", setting flag that fleets can run in parallel because a pairing list with flight multiplier "+ - flightMultiplier+" has been used."); - regattaLike.setFleetsCanRunInParallelToTrue(); - } - } - + //READ public List getRaceDisplayNamesFromLeaderboard(String leaderboardName,List raceColumnNames) throws NotFoundException { Leaderboard leaderboard = this.getLeaderboardByName(leaderboardName); getSecurityService().checkCurrentUserReadPermission(leaderboard); @@ -8467,6 +6024,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Iterable getAvailableDetailTypesForLeaderboard(String leaderboardName, RegattaAndRaceIdentifier raceIdentifierOrNull) { final Set allowed = new HashSet<>(); allowed.addAll(DetailType.getAllNonRestrictedDetailTypes()); @@ -8526,6 +6084,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return allowed; } + //READ public SpotDTO getWindFinderSpot(String spotId) throws MalformedURLException, IOException, org.json.simple.parser.ParseException, InterruptedException, ExecutionException { final SpotDTO result; final WindFinderTrackerFactory windFinderTrackerFactory = windFinderTrackerFactoryServiceTracker.getService(); @@ -8542,27 +6101,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } - @Override - public boolean canSliceRace(RegattaAndRaceIdentifier raceIdentifier) { - final Regatta regatta = getService().getRegattaByName(raceIdentifier.getRegattaName()); - final Leaderboard regattaLeaderboard = getService().getLeaderboardByName(raceIdentifier.getRegattaName()); - final DynamicTrackedRace trackedRace = getService().getTrackedRace(raceIdentifier); - getSecurityService().checkCurrentUserUpdatePermission(raceIdentifier); - getSecurityService().checkCurrentUserUpdatePermission(regattaLeaderboard); - getSecurityService().checkCurrentUserUpdatePermission(regatta); - - final boolean result; - if (regatta == null || !(regattaLeaderboard instanceof RegattaLeaderboard) || trackedRace == null - || trackedRace.getStartOfTracking() == null || !isSmartphoneTrackingEnabled(trackedRace)) { - result = false; - } else { - final Pair raceColumnAndFleetOfRaceToSlice = regattaLeaderboard.getRaceColumnAndFleet(trackedRace); - result = (raceColumnAndFleetOfRaceToSlice != null); // is the TrackedRace associated to the given RegattaLeaderboard? - } - return result; - } - - private boolean isSmartphoneTrackingEnabled(DynamicTrackedRace trackedRace) { + //READ + protected boolean isSmartphoneTrackingEnabled(DynamicTrackedRace trackedRace) { boolean result = false; for (RaceLog raceLog : trackedRace.getAttachedRaceLogs()) { RaceLogTrackingState raceLogTrackingState = new RaceLogTrackingStateAnalyzer(raceLog).analyze(); @@ -8575,6 +6115,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public SliceRacePreperationDTO prepareForSlicingOfRace(final RegattaAndRaceIdentifier raceIdentifier) { getSecurityService().checkCurrentUserReadPermission(raceIdentifier); final Leaderboard regattaLeaderboard = getService().getLeaderboardByName(raceIdentifier.getRegattaName()); @@ -8598,315 +6139,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public RegattaAndRaceIdentifier sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName, - TimePoint sliceFrom, TimePoint sliceTo) throws ServiceException { - SecurityUtils.getSubject().checkPermission( - SecuredDomainType.REGATTA.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, - Regatta.getTypeRelativeObjectIdentifier(raceIdentifier.getRegattaName()))); - SecurityUtils.getSubject() - .checkPermission(SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier( - DefaultActions.UPDATE, - Leaderboard.getTypeRelativeObjectIdentifier(raceIdentifier.getRegattaName()))); - final Locale locale = getClientLocale(); - if (!canSliceRace(raceIdentifier)) { - throw new ServiceException(serverStringMessages.get(locale, "slicingCannotSliceRace")); - } - final String trackedRaceName = newRaceColumnName; - final RegattaIdentifier regattaIdentifier = new RegattaName(raceIdentifier.getRegattaName()); - final Regatta regatta = getService().getRegatta(regattaIdentifier); - final Leaderboard regattaLeaderboard = getService().getLeaderboardByName(regatta.getName()); - if (regattaLeaderboard == null) { - throw new IllegalArgumentException("Cannot slice a race for which no regatta leaderboard exists"); - } - if (regatta.getRaceColumnByName(newRaceColumnName) != null) { - throw new ServiceException(serverStringMessages.get(locale, "slicingRaceColumnAlreadyUsedThe")); - } - final DynamicTrackedRace trackedRaceToSlice = getService().getTrackedRace(raceIdentifier); - final TimePoint startOfTrackingOfRaceToSlice = trackedRaceToSlice.getStartOfTracking(); - final TimePoint endOfTrackingOfRaceToSlice = trackedRaceToSlice.getEndOfTracking(); - if (sliceFrom == null || sliceTo == null || startOfTrackingOfRaceToSlice.after(sliceFrom) - || (endOfTrackingOfRaceToSlice != null && endOfTrackingOfRaceToSlice.before(sliceTo))) { - throw new ServiceException(serverStringMessages.get(locale, "slicingTimeRangeOutOfBounds")); - } - final Pair raceColumnAndFleetOfRaceToSlice = regatta.getRaceColumnAndFleet(trackedRaceToSlice); - // RaceColumns in a RegattaLeaderboard are always RaceColumnInSeries instances - final RaceColumnInSeries raceColumnOfRaceToSlice = (RaceColumnInSeries) raceColumnAndFleetOfRaceToSlice.getA(); - final Fleet fleet = raceColumnAndFleetOfRaceToSlice.getB(); - final Series series = raceColumnOfRaceToSlice.getSeries(); - final RaceLog raceLogOfRaceToSlice = raceColumnOfRaceToSlice.getRaceLog(fleet); - final RaceColumn raceColumn = getService().apply(new AddColumnToSeries(regattaIdentifier, series.getName(), newRaceColumnName)); - final RaceLog raceLog = raceColumn.getRaceLog(fleet); - final AbstractLogEventAuthor author = getService().getServerAuthor(); - final TimePoint startOfTracking = sliceFrom; - final TimePoint endOfTracking = sliceTo; - raceLog.add(new RaceLogStartOfTrackingEventImpl(startOfTracking, author, raceLog.getCurrentPassId())); - raceLog.add(new RaceLogEndOfTrackingEventImpl(endOfTracking, author, raceLog.getCurrentPassId())); - final TimeRange timeRange = new TimeRangeImpl(sliceFrom, sliceTo); - final StartTimeFinderResult startTimeFinderResult = new StartTimeFinder(getService(), raceLogOfRaceToSlice).analyze(); - final TimePoint startTime = startTimeFinderResult.getStartTime(); - final boolean hasStartTime = startTime != null && timeRange.includes(startTime); - final boolean dependentStartTime = startTimeFinderResult.isDependentStartTime(); - final boolean hasFinishingTime; - final boolean hasFinishedTime; - if (hasStartTime) { - final TimePoint finishingTime = new FinishingTimeFinder(raceLog).analyze(); - hasFinishingTime = finishingTime != null && timeRange.includes(finishingTime); - if (hasFinishingTime) { - final TimePoint finishedTime = new FinishedTimeFinder(raceLog).analyze(); - hasFinishedTime = finishedTime != null && timeRange.includes(finishedTime); - } else { - hasFinishedTime = false; - } - } else { - hasFinishingTime = false; - hasFinishedTime = false; - } - - // Only wind fixes in the new tracking interval as well as the best fallback fixes are added to the new RaceLog - final LogEventTimeRangeWithFallbackFilter windFixEvents = new LogEventTimeRangeWithFallbackFilter<>( - timeRange); - raceLogOfRaceToSlice.lockForRead(); - try { - for (RaceLogEvent raceLogEvent : raceLogOfRaceToSlice.getUnrevokedEvents()) { - raceLogEvent.accept(new BaseRaceLogEventVisitor() { - @Override - public void visit(RaceLogDependentStartTimeEvent event) { - if (dependentStartTime && isLatestPass(event)) { - raceLog.add(new RaceLogDependentStartTimeEventImpl(event.getCreatedAt(), - event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), - raceLog.getCurrentPassId(), event.getDependentOnRaceIdentifier(), - event.getStartTimeDifference(), event.getNextStatus(), event.getCourseAreaId())); - } - } - - @Override - public void visit(RaceLogStartTimeEvent event) { - if (!dependentStartTime && isLatestPass(event)) { - raceLog.add(new RaceLogStartTimeEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), - event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), event.getStartTime(), - event.getNextStatus(), event.getCourseAreaId())); - } - } - - @Override - public void visit(RaceLogRegisterCompetitorEvent event) { - raceLog.add(new RaceLogRegisterCompetitorEventImpl(event.getCreatedAt(), - event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), - raceLog.getCurrentPassId(), event.getCompetitor(), event.getBoat())); - } - - @Override - public void visit(RaceLogWindFixEvent event) { - windFixEvents.addEvent(event); - } - - @Override - public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) { - raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(event.getCreatedAt(), event.getAuthor(), - event.getLogicalTimePoint(), UUID.randomUUID(), raceLog.getCurrentPassId())); - } - - @Override - public void visit(RaceLogCourseDesignChangedEvent event) { - raceLog.add(new RaceLogCourseDesignChangedEventImpl(event.getCreatedAt(), - event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), - raceLog.getCurrentPassId(), event.getCourseDesign(), event.getCourseDesignerMode())); - } - - @Override - public void visit(RaceLogFlagEvent event) { - if (hasStartTime && isLatestPass(event) && !event.getLogicalTimePoint().after(sliceTo)) { - raceLog.add(new RaceLogFlagEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), - event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), event.getUpperFlag(), - event.getLowerFlag(), event.isDisplayed())); - } - } - - @Override - public void visit(RaceLogStartProcedureChangedEvent event) { - if (hasStartTime && isLatestPass(event)) { - raceLog.add(new RaceLogStartProcedureChangedEventImpl(event.getCreatedAt(), - event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), - raceLog.getCurrentPassId(), event.getStartProcedureType())); - } - } - - @Override - public void visit(RaceLogFinishPositioningConfirmedEvent event) { - if (hasFinishedTime && isLatestPass(event)) { - raceLog.add(new RaceLogFinishPositioningConfirmedEventImpl(event.getCreatedAt(), - event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), - raceLog.getCurrentPassId(), event.getPositionedCompetitorsIDsNamesMaxPointsReasons())); - } - } - - @Override - public void visit(RaceLogFinishPositioningListChangedEvent event) { - if (hasFinishedTime && isLatestPass(event)) { - raceLog.add(new RaceLogFinishPositioningListChangedEventImpl(event.getCreatedAt(), - event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), - raceLog.getCurrentPassId(), event.getPositionedCompetitorsIDsNamesMaxPointsReasons())); - } - } - - @Override - public void visit(RaceLogFixedMarkPassingEvent event) { - if (hasStartTime && isLatestPass(event) && timeRange.includes(event.getTimePointOfFixedPassing())) { - raceLog.add(new RaceLogFixedMarkPassingEventImpl(event.getCreatedAt(), - event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), - event.getInvolvedCompetitors(), raceLog.getCurrentPassId(), - event.getTimePointOfFixedPassing(), event.getZeroBasedIndexOfPassedWaypoint())); - } - } - - @Override - public void visit(RaceLogSuppressedMarkPassingsEvent event) { - if (hasStartTime && isLatestPass(event) && timeRange.includes(event.getLogicalTimePoint())) { - raceLog.add(new RaceLogSuppressedMarkPassingsEventImpl(event.getCreatedAt(), - event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), - event.getInvolvedCompetitors(), raceLog.getCurrentPassId(), - event.getZeroBasedIndexOfFirstSuppressedWaypoint())); - } - } - - @Override - public void visit(RaceLogProtestStartTimeEvent event) { - if (hasFinishedTime && isLatestPass(event)) { - raceLog.add(new RaceLogProtestStartTimeEventImpl(event.getCreatedAt(), - event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), - raceLog.getCurrentPassId(), event.getProtestTime())); - } - } - - @Override - public void visit(RaceLogAdditionalScoringInformationEvent event) { - if (hasFinishedTime && isLatestPass(event)) { - raceLog.add(new RaceLogAdditionalScoringInformationEventImpl(event.getCreatedAt(), - event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), - raceLog.getCurrentPassId(), event.getType())); - } - } - - @Override - public void visit(RaceLogPathfinderEvent event) { - if (hasStartTime && isLatestPass(event)) { - raceLog.add(new RaceLogPathfinderEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), - event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), - event.getPathfinderId())); - } - } - - @Override - public void visit(RaceLogGateLineOpeningTimeEvent event) { - if (hasStartTime && isLatestPass(event)) { - raceLog.add(new RaceLogGateLineOpeningTimeEventImpl(event.getCreatedAt(), - event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), - raceLog.getCurrentPassId(), event.getGateLineOpeningTimes().getGateLaunchStopTime(), - event.getGateLineOpeningTimes().getGolfDownTime())); - } - } - - @Override - public void visit(RaceLogRaceStatusEvent event) { - if (isLatestPass(event) && !(event instanceof RaceLogDependentStartTimeEvent) - && !(event instanceof RaceLogStartTimeEvent)) { - if ((hasStartTime - && event.getNextStatus().getOrderNumber() <= RaceLogRaceStatus.RUNNING.getOrderNumber()) - || (hasFinishingTime && event.getNextStatus() == RaceLogRaceStatus.FINISHING) - || (hasFinishedTime && event.getNextStatus() == RaceLogRaceStatus.FINISHED)) { - raceLog.add(new RaceLogRaceStatusEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), - event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), - event.getNextStatus())); - } - } - } - - @Override - public void visit(RaceLogORCImpliedWindSourceEvent event) { - raceLog.add(new RaceLogORCImpliedWindSourceEventImpl(event.getCreatedAt(), - event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), - raceLog.getCurrentPassId(), event.getImpliedWindSource())); - } - - @Override - public void visit(RaceLogORCCertificateAssignmentEvent event) { - raceLog.add(new RaceLogORCCertificateAssignmentEventImpl(event.getCreatedAt(), - event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), - raceLog.getCurrentPassId(), event.getCertificate(), event.getBoatId())); - } - - @Override - public void visit(RaceLogORCScratchBoatEvent event) { - raceLog.add(new RaceLogORCScratchBoatEventImpl(event.getCreatedAt(), - event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), - raceLog.getCurrentPassId(), event.getCompetitor())); - } - - private boolean isLatestPass(RaceLogEvent event) { - return event.getPassId() == raceLogOfRaceToSlice.getCurrentPassId(); - } - }); - } - } finally { - raceLogOfRaceToSlice.unlockAfterRead(); - } - windFixEvents.getFilteredEvents() - .forEach(event -> raceLog.add(new RaceLogWindFixEventImpl(event.getCreatedAt(), - event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), - event.getWindFix(), event.isMagnetic()))); - final TimePoint startTrackingTimePoint = MillisecondsTimePoint.now(); - // this ensures that the events consistently have different timepoints to ensure a consistent result of the state analysis - // that's why we can't just call adapter.denoteRaceForRaceLogTracking - final TimePoint denotationTimePoint = startTrackingTimePoint.minus(1); - raceLog.add(new RaceLogDenoteForTrackingEventImpl(denotationTimePoint, - author, raceLog.getCurrentPassId(), trackedRaceName, regatta.getBoatClass(), UUID.randomUUID())); - raceLog.add(new RaceLogStartTrackingEventImpl(startTrackingTimePoint, author, raceLog.getCurrentPassId())); - try { - final RaceHandle raceHandle = getRaceLogTrackingAdapter().startTracking(getService(), regattaLeaderboard, - raceColumn, fleet, /* trackWind */ true, /* correctWindDirectionByMagneticDeclination */ true, - getService().getPermissionAwareRaceTrackingHandler()); - - // wait for the RaceDefinition to be created - raceHandle.getRace(); - - final DynamicTrackedRace trackedRace = WaitForTrackedRaceUtil.waitForTrackedRace(raceColumn, fleet, 10); - if (trackedRace == null) { - throw new ServiceException(serverStringMessages.get(locale, "slicingCouldNotObtainRace")); - } - for (WindSource windSourceToCopy : trackedRaceToSlice.getWindSources()) { - if (windSourceToCopy.canBeStored()) { - final WindTrack windTrackToCopyFrom = trackedRaceToSlice.getOrCreateWindTrack(windSourceToCopy); - windTrackToCopyFrom.lockForRead(); - try { - for (Wind windToCopy : windTrackToCopyFrom.getFixes(startOfTracking, true, endOfTracking, true)) { - trackedRace.recordWind(windToCopy, windSourceToCopy); - } - } finally { - windTrackToCopyFrom.unlockAfterRead(); - } - } - } - - final Iterable mediaTracksForOriginalRace = getService().getMediaTracksForRace(raceIdentifier); - for (MediaTrack mediaTrack : mediaTracksForOriginalRace) { - if (mediaTrack.overlapsWith(sliceFrom, sliceTo)) { - final Set assignedRaces = new HashSet<>(mediaTrack.assignedRaces); - assignedRaces.add(trackedRace.getRaceIdentifier()); - // we can't just use the original instance and add the Race due to the fact that this leads to - // assignedRaces being empty afterwards. - final MediaTrack mediaTrackToSave = new MediaTrack(mediaTrack.dbId, mediaTrack.title, - mediaTrack.url, mediaTrack.startTime, mediaTrack.duration, mediaTrack.mimeType, - assignedRaces); - getService().mediaTrackAssignedRacesChanged(mediaTrackToSave); - } - } - return trackedRace.getRaceIdentifier(); - } catch (Exception e) { - throw new ServiceException(serverStringMessages.get(locale, "slicingError")); - } - } - - @Override + //READ public Boolean checkIfRaceIsTracking(RegattaAndRaceIdentifier race) { getSecurityService().checkCurrentUserReadPermission(race); boolean result = false; @@ -8921,6 +6154,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { ShardingType identifiedShardingType = null; try { @@ -8935,49 +6169,6 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } } - @Override - public Set resizeImage(final ImageResizingTaskDTO resizingTask) throws Exception { - if (resizingTask.getResizingTask() == null || resizingTask.getResizingTask().size() == 0) { - throw new InvalidAttributeValueException("Resizing Task can not be null or empty"); - } - final ImageConverter converter = new ImageConverter(); - // calculating the fileType of the image by its uri - final String sourceRef = resizingTask.getImage().getSourceRef(); - final String fileType = sourceRef.substring(sourceRef.lastIndexOf(".") + 1); - final ImageWithMetadata imageAndMetadata = converter - .loadImage(HttpUrlConnectionHelper.redirectConnection(new URL(sourceRef)).getInputStream(), fileType); - final List resizedImages = converter.convertImage(imageAndMetadata.getImage(), - resizingTask.getResizingTask()); - final List sourceRefs = storeImages(resizedImages, fileType, imageAndMetadata.getMetadata()); - // if an error occures while storing the files, all already stored files are removed before throwing an - // exception - if (sourceRefs == null || sourceRefs.size() < resizingTask.getResizingTask().size()) { - for (String alreadyStoredFileRef : sourceRefs) { - try { - getService().getFileStorageManagementService().getActiveFileStorageService() - .removeFile(new URI(alreadyStoredFileRef)); - } catch (Exception e) { - } - // Exception occured while trying to revert changes after exception - // This only keeps some trash on the FileStorage - } - throw new Exception("Error occured while storing images on the FileStorage"); - } - final Set resizedImagesAsDTOs = createImageDTOsFromURLsAndResizingTask(sourceRefs, resizingTask, - resizedImages); - for (String tag : resizingTask.getImage().getTags()) { - final MediaTagConstants predefinedTag = MediaTagConstants.fromName(tag); - if (predefinedTag != null && !resizingTask.getResizingTask().contains(predefinedTag)) { - final ImageDTO image = resizingTask.getImage(); - for (MediaTagConstants tagConstant : resizingTask.getResizingTask()) { - image.getTags().remove(tagConstant.getName()); - } - resizedImagesAsDTOs.add(image); - } - } - return resizedImagesAsDTOs; - } - /** * Takes a list of source URLs, the resizing task and the sizes of the resized images to create a ImageDTO for every * resized image @@ -8992,7 +6183,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet * the BufferedImages, used to get their width and height * @returns a List of ImageDTOs that contains an ImageDTO per resized image */ - private Set createImageDTOsFromURLsAndResizingTask(final List sourceRefs, + //READ + protected Set createImageDTOsFromURLsAndResizingTask(final List sourceRefs, final ImageResizingTaskDTO resizingTask, final List images) { final Set imageDTOs = new HashSet(); for (int i = 0; i < sourceRefs.size(); i++) { @@ -9008,143 +6200,8 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return imageDTOs; } - /** - * Stores a list of BufferedImages and returns a list of URLs as Strings under which the BufferedImages are stored - * - * @author Robin Fleige (D067799) - * - * @param resizedImages - * the BufferedImages that will be stored - * @param fileType - * the format of the image, for example "png", "jpeg" or "jpg" - * @param metadata - * the metadata of the original image - * @returns a list of URLs as Strings under which the BufferedImages are stored - */ - private List storeImages(final List resizedImages, final String fileType, - final IIOMetadata metadata) { - final List sourceRefs = new ArrayList<>(); - - try { - for (final BufferedImage resizedImage : resizedImages) { - final InputStream fileStorageStream = new ImageConverter().imageWithMetadataToInputStream(resizedImage, - metadata, fileType); - sourceRefs.add(getService().getFileStorageManagementService().getActiveFileStorageService() - .storeFile(fileStorageStream, "." + fileType, new Long(fileStorageStream.available())) - .toString()); - } - } catch (NoCorrespondingServiceRegisteredException | IOException | OperationFailedException - | InvalidPropertiesException e) { - logger.log(Level.SEVERE, "Could not store file. Cause: " + e.getMessage()); - } - return sourceRefs; - } - - @Override - public SuccessInfo addTag(String leaderboardName, String raceColumnName, String fleetName, String tag, - String comment, String imageURL, String resizedImageURL, boolean visibleForPublic, - TimePoint raceTimepoint) { - SuccessInfo successInfo = new SuccessInfo(true, null, null, null); - try { - getService().getTaggingService().addTag(leaderboardName, raceColumnName, fleetName, tag, comment, imageURL, - resizedImageURL, visibleForPublic, raceTimepoint); - } catch (AuthorizationException e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "missingAuthorization"), - null, null); - } catch (IllegalArgumentException e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "invalidParameters"), null, - null); - } catch (RaceLogNotFoundException e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "raceLogNotFound"), null, - null); - } catch (ServiceNotFoundException e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "securityServiceNotFound"), - null, null); - } catch (TagAlreadyExistsException e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagAlreadyExists"), null, - null); - } catch (Exception e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "unknownError"), null, - null); - } - return successInfo; - } - - @Override - public SuccessInfo removeTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag) { - SuccessInfo successInfo = new SuccessInfo(true, null, null, null); - try { - getService().getTaggingService().removeTag(leaderboardName, raceColumnName, fleetName, tag); - } catch (AuthorizationException e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "missingAuthorization"), - null, null); - } catch (IllegalArgumentException e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "invalidParameters"), null, - null); - } catch (NotRevokableException e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagNotRevokable"), null, - null); - } catch (RaceLogNotFoundException e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "raceLogNotFound"), null, - null); - } catch (Exception e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "unknownError"), null, - null); - } - return successInfo; - } - - @Override - public SuccessInfo updateTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tagToUpdate, - String tag, String comment, String imageURL, String resizedImageURL, boolean visibleForPublic) { - SuccessInfo successInfo = new SuccessInfo(true, null, null, null); - try { - getService().getTaggingService().updateTag(leaderboardName, raceColumnName, fleetName, tagToUpdate, tag, - comment, imageURL, resizedImageURL, visibleForPublic); - } catch (AuthorizationException e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "missingAuthorization"), - null, null); - } catch (IllegalArgumentException e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "invalidParameters"), null, - null); - } catch (NotRevokableException e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagNotRevokable"), null, - null); - } catch (RaceLogNotFoundException e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "raceLogNotFound"), null, - null); - } catch (TagAlreadyExistsException e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagAlreadyExists"), null, - null); - } catch (Exception e) { - successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "unknownError"), null, - null); - } - return successInfo; - } - - @Override - public List getAllTags(String leaderboardName, String raceColumnName, String fleetName) { - List result = new ArrayList(); - result.addAll(getPublicTags(leaderboardName, raceColumnName, fleetName)); - result.addAll(getPrivateTags(leaderboardName, raceColumnName, fleetName)); - return result; - } - - @Override - public List getPublicTags(String leaderboardName, String raceColumnName, String fleetName) { - List result = new ArrayList(); - try { - result.addAll(getService().getTaggingService().getPublicTags(leaderboardName, raceColumnName, fleetName, null, false)); - } catch (Exception e) { - logger.log(Level.WARNING, "Problem obtaining public tags for leaderboard "+leaderboardName+", race column "+raceColumnName+ - ", fleet "+fleetName, e); - // do nothing as method will always return at least an empty list - } - return result; - } - @Override + //READ public List getPrivateTags(String leaderboardName, String raceColumnName, String fleetName) { List result = new ArrayList(); try { @@ -9158,6 +6215,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public RaceTimesInfoDTO getRaceTimesInfoIncludingTags(RegattaAndRaceIdentifier raceIdentifier, TimePoint searchSince) { RaceTimesInfoDTO raceTimesInfo = getRaceTimesInfo(raceIdentifier); @@ -9166,6 +6224,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List getRaceTimesInfosIncludingTags(Collection raceIdentifiers, Map searchSinceMap) { List raceTimesInfos = new ArrayList(); @@ -9180,12 +6239,14 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public MailInvitationType getMailType() { MailInvitationType type = MailInvitationType .valueOf(System.getProperty(MAILTYPE_PROPERTY, MailInvitationType.SailInsight3.name())); return type; } + //READ public String openRegattaRegistrationQrCode(String url) { String result = ""; try (DataInputStream imageIs = new DataInputStream(QRCodeGenerationUtil.create(url, 600, "H"))) { @@ -9198,16 +6259,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } - @Override - public List getPossibleTennants() { - // FIXME this is most likely greatly oversimplified and needs to be improved - ArrayList tenants = new ArrayList<>(); - for (UserGroup group : getSecurityService().getCurrentUser().getUserGroups()) { - tenants.add(group.getName()); - } - return tenants; - } - + //READ private Boolean isSelfServiceServer() { final AccessControlListAnnotation serverAclOrNull = getSecurityService().getAccessControlList(getServerInfo().getIdentifier()); final Boolean result; @@ -9225,6 +6277,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private Boolean isPublicServer() { final Boolean result; final RoleDefinition viewerRole = getSecurityService() @@ -9239,46 +6292,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public void updateGroupOwnerForEventHierarchy(UUID eventId, - MigrateGroupOwnerForHierarchyDTO migrateGroupOwnerForHierarchyDTO) { - Event event = getService().getEvent(eventId); - if (event != null) { - createOwnershipUpdater(migrateGroupOwnerForHierarchyDTO).updateGroupOwnershipForEventHierarchy(event); - } - } - - private SailingHierarchyOwnershipUpdater createOwnershipUpdater( - MigrateGroupOwnerForHierarchyDTO migrateGroupOwnerForHierarchyDTO) { - return SailingHierarchyOwnershipUpdater.createOwnershipUpdater( - migrateGroupOwnerForHierarchyDTO.isCreateNewGroup(), - migrateGroupOwnerForHierarchyDTO.getExistingUserGroupIdOrNull(), - migrateGroupOwnerForHierarchyDTO.getGroupName(), migrateGroupOwnerForHierarchyDTO.isUpdateCompetitors(), - migrateGroupOwnerForHierarchyDTO.isUpdateBoats(), - migrateGroupOwnerForHierarchyDTO.isCopyMembersAndRoles(), getService()); - } - - @Override - public void updateGroupOwnerForLeaderboardGroupHierarchy(UUID leaderboardGroupId, - MigrateGroupOwnerForHierarchyDTO migrateGroupOwnerForHierarchyDTO) { - LeaderboardGroup leaderboardGroup = getService().getLeaderboardGroupByID(leaderboardGroupId); - if (leaderboardGroup != null) { - createOwnershipUpdater(migrateGroupOwnerForHierarchyDTO) - .updateGroupOwnershipForLeaderboardGroupHierarchy(leaderboardGroup); - } - } - - @Override - public String getSecretForRegattaByName(String regattaName) { - String result = ""; - Regatta regatta = getService().getRegattaByName(regattaName); - if (regatta != null) { - getSecurityService().checkCurrentUserUpdatePermission(regatta); - result = regatta.getRegistrationLinkSecret(); - } - return result; - } - - @Override + //READ public BoatDTO getBoat(UUID boatId, String regattaName, String regattaRegistrationLinkSecret) { BoatDTO result = null; Leaderboard leaderboard = getService().getLeaderboardByName(regattaName); @@ -9301,6 +6315,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public MarkDTO getMark(UUID markId, String regattaName, String regattaRegistrationLinkSecret) { MarkDTO result = null; Leaderboard leaderboard = getService().getLeaderboardByName(regattaName); @@ -9323,6 +6338,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public QRCodeEvent getEvent(UUID eventId, String regattaName, String regattaRegistrationLinkSecret) { QRCodeEvent result = null; Event event = getService().getEvent(eventId); @@ -9344,6 +6360,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public CompetitorDTO getCompetitor(UUID competitorId, String regattaName, String regattaRegistrationLinkSecret) { CompetitorDTO result = null; Leaderboard leaderboard = getService().getLeaderboardByName(regattaName); @@ -9366,11 +6383,13 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public boolean getTrackedRaceIsUsingMarkPassingCalculator(RegattaAndRaceIdentifier regattaNameAndRaceName) { return getExistingTrackedRace(regattaNameAndRaceName).isUsingMarkPassingCalculator(); } @Override + //READ public ORCPerformanceCurveLegImpl[] getLegGeometry(String leaderboardName, String raceColumnName, String fleetName, int[] zeroBasedLegIndices, ORCPerformanceCurveLegTypes[] legTypes) { assert zeroBasedLegIndices.length == legTypes.length; @@ -9397,6 +6416,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public ORCPerformanceCurveLegImpl[] getLegGeometry(RegattaAndRaceIdentifier regattaNameAndRaceName, int[] zeroBasedLegIndices, ORCPerformanceCurveLegTypes[] legTypes) { final LeaderboardDTOCalculationReuseCache cache = new LeaderboardDTOCalculationReuseCache(MillisecondsTimePoint.now()); @@ -9409,6 +6429,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private ORCPerformanceCurveLegImpl getLegGeometry(int zeroBasedLegIndex, ORCPerformanceCurveLegTypes legType, final TrackedRace trackedRace, WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache) { final ORCPerformanceCurveLegImpl result; @@ -9431,6 +6452,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Map getORCPerformanceCurveLegInfo(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { final Leaderboard leaderboard = getLeaderboardByName(leaderboardName); @@ -9438,6 +6460,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return getORCPerformanceCurveLegInfo(Collections.singleton(getRaceLog(leaderboardName, raceColumnName, fleetName))); } + //READ private Map getORCPerformanceCurveLegInfo(Iterable raceLogs) { final Map result = new HashMap<>(); for (final RaceLog raceLog : raceLogs) { @@ -9453,57 +6476,13 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Map getORCPerformanceCurveLegInfo(RegattaAndRaceIdentifier raceIdentifier) { return getORCPerformanceCurveLegInfo(getTrackedRace(raceIdentifier).getAttachedRaceLogs()); } @Override - public void setORCPerformanceCurveLegInfo(RegattaAndRaceIdentifier raceIdentifier, - Map legInfo) throws NotRevokableException { - final TrackedRace existingTrackedRace = getExistingTrackedRace(raceIdentifier); - getService().getSecurityService().checkCurrentUserUpdatePermission(existingTrackedRace); - setORCPerformanceCurveInfo(existingTrackedRace.getAttachedRaceLogs().iterator().next(), legInfo); - } - - private void setORCPerformanceCurveInfo(RaceLog raceLog, Map legInfo) throws NotRevokableException { - final AbstractLogEventAuthor author = getService().getServerAuthor(); - for (final Entry e : new RaceLogORCLegDataEventFinder(raceLog).analyze().entrySet()) { - assert e.getValue() != null; - final ORCPerformanceCurveLeg leg = RaceLogORCLegDataAnalyzer.createORCPerformanceCurveLeg(e.getValue()); - final ORCPerformanceCurveLegImpl desiredLeg = legInfo.get(e.getKey()); - final boolean explicitRevoke = legInfo.containsKey(e.getKey()) && legInfo.get(e.getKey()) == null; - if (Util.equalsWithNull(desiredLeg, leg)) { - assert desiredLeg != null; - // we already have what the client wants, namely either nothing found and an explicitRevoke was requested, - // or the desiredLeg matched with what the log has; remove the request from the legInfo, meaning it has been handled: - legInfo.remove(e.getKey()); - } else { - // either we have an explicitRevoke and found a leg setting in the race log that therefore needs to be revoked, - // or the leg event found in the log does not match the desiredLeg for this index. - raceLog.revokeEvent(author, e.getValue()); - // In case an explicit revoke was what was requested, we have handled the request: - if (explicitRevoke) { - legInfo.remove(e.getKey()); - } - } - } - // for the remaining legInfo entries we now have to create race log events: - final TimePoint now = MillisecondsTimePoint.now(); - for (final Entry e : legInfo.entrySet()) { - if (e.getValue() != null) { - raceLog.add(new RaceLogORCLegDataEventImpl(now, now, author, UUID.randomUUID(), /* pPassId */ 0, e.getKey(), - e.getValue().getTwa(), e.getValue().getLength(), e.getValue().getType())); - } - } - } - - @Override - public void setORCPerformanceCurveLegInfo(String leaderboardName, String raceColumnName, String fleetName, - Map legInfo) throws NotFoundException, NotRevokableException { - setORCPerformanceCurveInfo(getRaceLog(leaderboardName, raceColumnName, fleetName), legInfo); - } - - @Override + //READ public Collection getORCCertificates(String json) throws org.json.simple.parser.ParseException, JsonDeserializationException { final JSONObject jsonObject = (JSONObject) new JSONParser().parse(json); final JSONArray certificates = (JSONArray) jsonObject.get(ORCCertificateUploadConstants.CERTIFICATES); @@ -9517,6 +6496,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Map getORCCertificateAssignmentsByBoatIdAsString(RegattaIdentifier regattaIdentifier) throws NotFoundException { final Regatta regatta = (Regatta) regattaIdentifier.getRegatta(getService()); if (regatta == null) { @@ -9535,48 +6515,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override - public Map getORCCertificateAssignmentsByBoatIdAsString( - RegattaAndRaceIdentifier raceIdentifier) throws NotFoundException { - final TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier); - if (trackedRace == null) { - throw new NotFoundException("Tracked race named "+raceIdentifier+" not found"); - } - getService().getSecurityService().checkCurrentUserReadPermission(trackedRace); - final Map result = new HashMap<>(); - final Map boatsById = new HashMap<>(); - for (final Boat boat : trackedRace.getRace().getBoats()) { - boatsById.put(boat.getId(), boat); - } - for (final RaceLog raceLog : trackedRace.getAttachedRaceLogs()) { - for (final Entry e : new RaceLogORCCertificateAssignmentFinder(raceLog, boatsById).analyze().entrySet()) { - result.put(e.getKey().getId().toString(), e.getValue()); - } - } - return result; - } - - @Override - public Map getORCCertificateAssignmentsByBoatIdAsString(String leaderboardName) throws NotFoundException { - final Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - if (leaderboard instanceof LeaderboardThatHasRegattaLike) { - getService().getSecurityService().checkCurrentUserReadPermission(leaderboard); - final Map result = new HashMap<>(); - final Map boatsById = new HashMap<>(); - for (final Boat boat : leaderboard.getAllBoats()) { - boatsById.put(boat.getId(), boat); - } - for (final Entry e : new RegattaLogORCCertificateAssignmentFinder( - ((LeaderboardThatHasRegattaLike) leaderboard).getRegattaLike().getRegattaLog(), boatsById).analyze().entrySet()) { - result.put(e.getKey().getId().toString(), e.getValue()); - } - return result; - } else { - throw new IllegalArgumentException("Leaderboard must be of type "+LeaderboardThatHasRegattaLike.class.getSimpleName()+ - ", but leaderboard "+leaderboardName+" is of type "+leaderboard.getClass().getSimpleName()); - } - } - - @Override + //READ public Map getORCCertificateAssignmentsByBoatIdAsString(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { final RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); @@ -9593,205 +6532,15 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } - private Triple createCertificateAssignmentsForRace(String regattaName, String raceName, - Map certificatesForBoatIdsAsString) throws IOException, NotFoundException { - final RegattaAndRaceIdentifier raceIdentifier = new RegattaNameAndRaceName(regattaName, raceName); - final TrackedRace trackedRace = getService().getTrackedRace(raceIdentifier); - if (trackedRace == null) { - throw new NotFoundException("Regatta named "+regattaName+" not found"); - } else { - getService().getSecurityService().checkCurrentUserUpdatePermission(trackedRace); - final RaceLog raceLog = trackedRace.getAttachedRaceLogs().iterator().next(); - final LogEventConstructor logEventConstructor = createRaceLogEventConstructor(); - return createCertificateAssignments(raceLog, logEventConstructor, certificatesForBoatIdsAsString); - } - } - - private Triple createCertificateAssignmentsForLeaderboard(String leaderboardName, - Map certificatesForBoatIdsAsString) throws IOException, NotFoundException { - final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); - if (leaderboard == null) { - throw new NotFoundException("Leaderboard named "+leaderboardName+" not found"); - } else if (!(leaderboard instanceof LeaderboardThatHasRegattaLike)) { - throw new NotFoundException("Leaderboard named "+leaderboardName+" has no regatta log"); - } else { - getService().getSecurityService().checkCurrentUserUpdatePermission(leaderboard); - final RegattaLog regattaLog = ((LeaderboardThatHasRegattaLike) leaderboard).getRegattaLike().getRegattaLog(); - final LogEventConstructor logEventConstructor = createRegattaLogEventConstructor(); - return createCertificateAssignments(regattaLog, logEventConstructor, certificatesForBoatIdsAsString); - } - } - - private Triple createCertificateAssignmentsForRaceLog(String leaderboardName, String raceColumnName, String fleetName, - Map certificatesForBoatIdsAsString) throws IOException, NotFoundException { - final Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - getService().getSecurityService().checkCurrentUserUpdatePermission(leaderboard); - final RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); - final LogEventConstructor logEventConstructor = createRaceLogEventConstructor(); - return createCertificateAssignments(raceLog, logEventConstructor, certificatesForBoatIdsAsString); - } - - private Triple createCertificateAssignmentsForRegatta(RegattaIdentifier regattaIdentifier, - Map certificatesForBoatIdsAsString) throws IOException, NotFoundException { - final Regatta regatta = (Regatta) regattaIdentifier.getRegatta(getService()); - if (regatta == null) { - throw new NotFoundException("Regatta named "+regattaIdentifier+" not found"); - } else { - getService().getSecurityService().checkCurrentUserUpdatePermission(regatta); - final RegattaLog regattaLog = regatta.getRegattaLog(); - final LogEventConstructor logEventConstructor = createRegattaLogEventConstructor(); - return createCertificateAssignments(regattaLog, logEventConstructor, certificatesForBoatIdsAsString); - } - } - - private LogEventConstructor createRegattaLogEventConstructor() { - final LogEventConstructor logEventConstructor = (TimePoint createdAt, TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Serializable pId, ORCCertificate certificate, Boat boat)->new RegattaLogORCCertificateAssignmentEventImpl( - createdAt, logicalTimePoint, author, pId, certificate, boat); - return logEventConstructor; - } - @FunctionalInterface - private static interface LogEventConstructor, VisitorT> { + public + //?? + static interface LogEventConstructor, VisitorT> { LogEventT create(TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, ORCCertificate certificate, Boat boat); } - /** - * @return the number of certificate assignments inserted into (not replaced in) the log in the first component of - * the triple returned; this may be fewer than requested because redundant assignments are ignored; the number - * of assignments replaced in the log in the second component of the triple. The third element of the triple - * is the number of assignments effectively revoked (not including those replaced). - */ - private , VisitorT, LogEventT extends AbstractLogEvent, - AssignmentEventT extends ORCCertificateAssignmentEvent> Triple createCertificateAssignments( - LogT logToAddTo, LogEventConstructor logEventConstructor, - Map certificatesForBoatIdsAsString) throws IOException { - int insertedCount = 0; - int replacedCount = 0; - int removedCount = 0; - final BaseORCCertificateAssignmentAnalyzer analyzerForPreviousAssignments = - new BaseORCCertificateAssignmentAnalyzer<>(logToAddTo); - final Map validCertificateAssignmentsInLogByBoatId = analyzerForPreviousAssignments.analyze(); - final TimePoint now = MillisecondsTimePoint.now(); - final CompetitorAndBoatStore boatStore = getService().getCompetitorAndBoatStore(); - final AbstractLogEventAuthor serverAuthor = getService().getServerAuthor(); - for (final Entry mapping : certificatesForBoatIdsAsString.entrySet()) { - final Serializable boatId = UUIDHelper.tryUuidConversion(mapping.getKey()); - final AssignmentEventT previouslyValidAssignmentEventForBoat = validCertificateAssignmentsInLogByBoatId.remove(boatId); - final ORCCertificate certificate = mapping.getValue(); - final Boat boat = boatStore.getExistingBoatById(boatId); - if (boat != null) { - final boolean addEvent; - if (previouslyValidAssignmentEventForBoat != null) { - if (!previouslyValidAssignmentEventForBoat.getCertificate().getId().equals(certificate.getId())) { - // revoke the previously valid event because it has a different certificate - logger.info("Replacing certificate "+previouslyValidAssignmentEventForBoat.getCertificate()+ - " for boat "+boat+" by "+certificate); - replacedCount++; - addEvent = true; - try { - @SuppressWarnings("unchecked") - final LogEventT previouslyValidAssignmentEventForBoatAsLogEventT = (LogEventT) previouslyValidAssignmentEventForBoat; - logToAddTo.revokeEvent(serverAuthor, previouslyValidAssignmentEventForBoatAsLogEventT); - } catch (NotRevokableException e) { - logger.severe("Couldn't revoke old certificate assignment event "+previouslyValidAssignmentEventForBoat+": "+e.getMessage()); - } - } else { - addEvent = false; - logger.info("Not replacing certificate "+previouslyValidAssignmentEventForBoat.getCertificate()+ - " because the certificate "+certificate+" requested to be assigned is considered equal."); - } - } else { - addEvent = true; - insertedCount++; - } - if (addEvent) { - final LogEventT assignment = logEventConstructor.create(now, now, serverAuthor, UUID.randomUUID(), certificate, boat); - logToAddTo.add(assignment); - } - } - } - for (final Entry boatIdAndEventToRevoke : validCertificateAssignmentsInLogByBoatId.entrySet()) { - @SuppressWarnings("unchecked") - final LogEventT eventToRevoke = (LogEventT) boatIdAndEventToRevoke.getValue(); - try { - logToAddTo.revokeEvent(serverAuthor, eventToRevoke); - removedCount++; - } catch (NotRevokableException e) { - logger.severe("Couldn't revoke old certificate assignment event "+eventToRevoke+": "+e.getMessage()); - } - } - return new Triple<>(insertedCount, replacedCount, removedCount); - } - - private LogEventConstructor createRaceLogEventConstructor() { - return (TimePoint createdAt, TimePoint logicalTimePoint, - AbstractLogEventAuthor author, Serializable pId, ORCCertificate certificate, Boat boat)->new RaceLogORCCertificateAssignmentEventImpl( - createdAt, logicalTimePoint, author, pId, /* passId */ 0, certificate, boat); - } - - @Override - public Triple assignORCPerformanceCurveCertificates(RegattaIdentifier regattaIdentifier, - Map certificatesForBoatsWithIdAsString) throws IOException, NotFoundException { - return createCertificateAssignmentsForRegatta(regattaIdentifier, certificatesForBoatsWithIdAsString); - } - - @Override - public Triple assignORCPerformanceCurveCertificates(String leaderboardName, - Map certificatesForBoatsWithIdAsString) throws IOException, NotFoundException { - return createCertificateAssignmentsForLeaderboard(leaderboardName, certificatesForBoatsWithIdAsString); - } - - @Override - public Triple assignORCPerformanceCurveCertificates(RegattaAndRaceIdentifier raceIdentifier, - Map certificatesForBoatsWithIdAsString) throws IOException, NotFoundException { - return createCertificateAssignmentsForRace(raceIdentifier.getRegattaName(), raceIdentifier.getRaceName(), certificatesForBoatsWithIdAsString); - } - - @Override - public Triple assignORCPerformanceCurveCertificates(String leaderboardName, String raceColumnName, String fleetName, - Map certificatesForBoatsWithIdAsString) throws IOException, NotFoundException { - return createCertificateAssignmentsForRaceLog(leaderboardName, raceColumnName, fleetName, certificatesForBoatsWithIdAsString); - } - - @Override - public CompetitorDTO getORCPerformanceCurveScratchBoat(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { - final Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - getService().getSecurityService().checkCurrentUserReadPermission(leaderboard); - final RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); - final RaceLogORCScratchBoatFinder finder = new RaceLogORCScratchBoatFinder(raceLog); - final Competitor scratchBoat = finder.analyze(); - return scratchBoat == null ? null : convertToCompetitorDTO(scratchBoat); - } - - @Override - public void setORCPerformanceCurveScratchBoat(String leaderboardName, String raceColumnName, String fleetName, CompetitorDTO newScratchBoatDTO) throws NotFoundException { - final Leaderboard leaderboard = getLeaderboardByName(leaderboardName); - getService().getSecurityService().checkCurrentUserUpdatePermission(leaderboard); - final RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); - final Competitor newScratchBoat = newScratchBoatDTO==null?null: - getService().getCompetitorAndBoatStore().getExistingCompetitorById(UUIDHelper.tryUuidConversion(newScratchBoatDTO.getIdAsString())); - final RaceLogORCScratchBoatAnalyzer analyzer = new RaceLogORCScratchBoatAnalyzer(raceLog); - final Pair previousScratchBoatAndEvent = analyzer.analyze(); - final Competitor previousScratchBoat = previousScratchBoatAndEvent == null ? null : previousScratchBoatAndEvent.getA(); - if (!Util.equalsWithNull(newScratchBoat, previousScratchBoat)) { - final AbstractLogEventAuthor serverAuthor = getService().getServerAuthor(); - if (previousScratchBoatAndEvent != null) { - // revoke scratch boat setting so far: - try { - raceLog.revokeEvent(serverAuthor, previousScratchBoatAndEvent.getB()); - } catch (NotRevokableException e) { - logger.log(Level.SEVERE, "Unable to revoke scratch boat definition event "+previousScratchBoatAndEvent.getB(), e); - } - } - if (newScratchBoat != null) { - final TimePoint now = MillisecondsTimePoint.now(); - raceLog.add(new RaceLogORCScratchBoatEventImpl(now, now, serverAuthor, UUID.randomUUID(), /* passId */ raceLog.getCurrentPassId(), newScratchBoat)); - } - } - } - @Override + //READ public ImpliedWindSource getImpliedWindSource(String leaderboardName, String raceColumnName, String fleetName) throws NotFoundException { final Leaderboard leaderboard = getLeaderboardByName(leaderboardName); getService().getSecurityService().checkCurrentUserReadPermission(leaderboard); @@ -9801,6 +6550,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public void setImpliedWindSource(String leaderboardName, String raceColumnName, String fleetName, ImpliedWindSource impliedWindSource) throws NotFoundException { final Leaderboard leaderboard = getLeaderboardByName(leaderboardName); getService().getSecurityService().checkCurrentUserUpdatePermission(leaderboard); @@ -9811,6 +6561,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Map> getSuggestedORCBoatCertificates(ArrayList boats) throws InterruptedException, ExecutionException { final ORCPublicCertificateDatabase db = ORCPublicCertificateDatabase.INSTANCE; final Map> result = new HashMap<>(); @@ -9828,6 +6579,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public Set searchORCBoatCertificates(CountryCode country, Integer yearOfIssuance, String referenceNumber, String yachtName, String sailNumber, String boatClassName) throws Exception { final ORCPublicCertificateDatabase db = ORCPublicCertificateDatabase.INSTANCE; @@ -9841,12 +6593,13 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List getMarkTemplates() { return getSecurityService().mapAndFilterByReadPermissionForCurrentUser( getSharedSailingData().getAllMarkTemplates(), m -> convertToMarkTemplateDTO(m)); } - private MarkTemplateDTO convertToMarkTemplateDTO(MarkTemplate markTemplate) { + protected MarkTemplateDTO convertToMarkTemplateDTO(MarkTemplate markTemplate) { final MarkTemplateDTO markTemplateDTO = new MarkTemplateDTO(markTemplate.getId(), markTemplate.getName(), markTemplate.getShortName() == null || markTemplate.getShortName().isEmpty() ? markTemplate.getName() : markTemplate.getShortName(), @@ -9856,75 +6609,28 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return markTemplateDTO; } - @Override - public MarkTemplateDTO addOrUpdateMarkTemplate(MarkTemplateDTO markTemplate) { - final UUID markTemplateUUID = UUID.randomUUID(); - final MarkTemplate mTemplate = getSecurityService() - .setOwnershipCheckPermissionForObjectCreationAndRevertOnError( - SecuredDomainType.MARK_TEMPLATE, - MarkTemplate.getTypeRelativeObjectIdentifier(markTemplateUUID), markTemplate.getName(), - () -> getSharedSailingData() - .createMarkTemplate(convertDtoToCommonMarkProperties( - markTemplate.getCommonMarkProperties()))); - return convertToMarkTemplateDTO(mTemplate); - } - - private CommonMarkProperties convertDtoToCommonMarkProperties(CommonMarkPropertiesDTO markProperties) { + //READ + protected CommonMarkProperties convertDtoToCommonMarkProperties(CommonMarkPropertiesDTO markProperties) { return new CommonMarkPropertiesImpl(markProperties.getName(), markProperties.getShortName(), markProperties.getColor(), markProperties.getShape(), markProperties.getPattern(), markProperties.getType()); } - private DeviceIdentifier convertDtoToDeviceIdentifier(DeviceIdentifierDTO deviceIdentifier) { + //READ + protected DeviceIdentifier convertDtoToDeviceIdentifier(DeviceIdentifierDTO deviceIdentifier) { return deviceIdentifier != null ? new SmartphoneUUIDIdentifierImpl(UUID.fromString(deviceIdentifier.deviceId)) : null; } @Override - public MarkPropertiesDTO addOrUpdateMarkProperties(MarkPropertiesDTO markProperties) { - MarkProperties createdOrUpdatedMarkProperties = getSharedSailingData() - .getMarkPropertiesById(markProperties.getUuid()); - if (createdOrUpdatedMarkProperties != null) { - getSecurityService().checkCurrentUserUpdatePermission(createdOrUpdatedMarkProperties); - getSharedSailingData().updateMarkProperties(markProperties.getUuid(), - convertDtoToCommonMarkProperties(markProperties.getCommonMarkProperties()), - markProperties.getTags()); - createdOrUpdatedMarkProperties = getSharedSailingData() - .getMarkPropertiesById(createdOrUpdatedMarkProperties.getId()); - } else { - createdOrUpdatedMarkProperties = getSecurityService() - .setOwnershipCheckPermissionForObjectCreationAndRevertOnError(SecuredDomainType.MARK_PROPERTIES, - MarkTemplate.getTypeRelativeObjectIdentifier(UUID.randomUUID()), markProperties.getName(), - () -> getSharedSailingData().createMarkProperties( - convertDtoToCommonMarkProperties(markProperties.getCommonMarkProperties()), - markProperties.getTags(), - /* non-default mark properties group ownership */ Optional.empty())); - } - return convertToMarkPropertiesDTO(createdOrUpdatedMarkProperties); - } - - @Override - public MarkPropertiesDTO updateMarkPropertiesPositioning(UUID markPropertiesId, DeviceIdentifierDTO deviceIdentifier, - Position fixedPosition) { - MarkProperties markProperties = getSharedSailingData().getMarkPropertiesById(markPropertiesId); - if (deviceIdentifier != null) { - getSharedSailingData().setTrackingDeviceIdentifierForMarkProperties(markProperties, convertDtoToDeviceIdentifier(deviceIdentifier)); - } else if (fixedPosition != null) { - getSharedSailingData().setFixedPositionForMarkProperties(markProperties, fixedPosition); - } else { - getSharedSailingData().clearPositioningForMarkProperties(markProperties); - } - return convertToMarkPropertiesDTO(getSharedSailingData().updateMarkProperties(markProperties.getId(), - markProperties, markProperties.getTags())); - } - - @Override + //READ public List getMarkProperties() { return getSecurityService().mapAndFilterByReadPermissionForCurrentUser( getSharedSailingData().getAllMarkProperties(), m -> convertToMarkPropertiesDTO(m)); } - private MarkPropertiesDTO convertToMarkPropertiesDTO(MarkProperties markProperties) { + //READ + protected MarkPropertiesDTO convertToMarkPropertiesDTO(MarkProperties markProperties) { final MarkPropertiesDTO markPropertiesDto = new MarkPropertiesDTO(markProperties.getId(), markProperties.getName(), markProperties.getTags(), markProperties.getShortName(), markProperties.getColor(), markProperties.getShape(), markProperties.getPattern(), @@ -9945,11 +6651,13 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public List getCourseTemplates() { return getSecurityService().mapAndFilterByReadPermissionForCurrentUser( getSharedSailingData().getAllCourseTemplates(), m -> convertToCourseTemplateDTO(m)); } + //READ public CourseTemplateDTO convertToCourseTemplateDTO(CourseTemplate courseTemplate) { final Map convertedDefaultMarkRolesForMarkTemplates = courseTemplate.getDefaultMarkRolesForMarkTemplates().entrySet() .stream().collect(Collectors.toMap(entry -> convertToMarkTemplateDTO(entry.getKey()), @@ -9976,6 +6684,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return result; } + //READ private RepeatablePartDTO convertToRepeatablePartDTO(RepeatablePart repeatablePart) { return repeatablePart != null ? new RepeatablePartDTO(repeatablePart.getZeroBasedIndexOfRepeatablePartStart(), @@ -9983,6 +6692,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet : null; } + //READ private WaypointTemplateDTO convertToWaypointTemplateDTO(WaypointTemplate waypointTemplate) { return new WaypointTemplateDTO(waypointTemplate.getControlPointTemplate().getName(), waypointTemplate.getControlPointTemplate().getShortName(), @@ -9992,13 +6702,15 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet } @Override + //READ public void removeCourseTemplates(Collection courseTemplateUuids) { for (UUID uuid : courseTemplateUuids) { getSharedSailingData().deleteCourseTemplate(getSharedSailingData().getCourseTemplateById(uuid)); } } - private WaypointTemplate convertToWaypointTemplate(WaypointTemplateDTO waypointTemplate, final MarkRolePairFactory markRolePairFactory) { + //READ + protected WaypointTemplate convertToWaypointTemplate(WaypointTemplateDTO waypointTemplate, final MarkRolePairFactory markRolePairFactory) { final List resolvedMarkRoles = waypointTemplate.getMarkRolesForControlPoint().stream() .map(t -> getSharedSailingData().getMarkRoleById(t.getUuid())).collect(Collectors.toList()); final ControlPointTemplate controlPointTemplate; @@ -10014,82 +6726,41 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet return new WaypointTemplateImpl(controlPointTemplate, waypointTemplate.getPassingInstruction()); } - private RepeatablePart convertToRepeatablePart(RepeatablePartDTO repeatablePart) { + //READ + protected RepeatablePart convertToRepeatablePart(RepeatablePartDTO repeatablePart) { return new RepeatablePartImpl(repeatablePart.getZeroBasedIndexOfRepeatablePartStart(), repeatablePart.getZeroBasedIndexOfRepeatablePartEnd()); } - @Override - public CourseTemplateDTO createOrUpdateCourseTemplate(CourseTemplateDTO courseTemplate) { - CourseTemplate existingCourseTemplate = getSharedSailingData().getCourseTemplateById(courseTemplate.getUuid()); - URL optionalImageURL = null; - try { - optionalImageURL = courseTemplate.getOptionalImageUrl().isPresent() - ? new URL(courseTemplate.getOptionalImageUrl().get()) - : null; - } catch (MalformedURLException e) { - throw new IllegalArgumentException( - String.format("Invalid URL: %s", courseTemplate.getOptionalImageUrl().get())); - } - final CourseTemplateDTO result; - if (existingCourseTemplate != null) { - getSecurityService().checkCurrentUserUpdatePermission(existingCourseTemplate); - result = convertToCourseTemplateDTO(getSharedSailingData().updateCourseTemplate(courseTemplate.getUuid(), - courseTemplate.getName(), courseTemplate.getShortName(), optionalImageURL, courseTemplate.getTags(), - courseTemplate.getDefaultNumberOfLaps())); - } else { - final List marks = courseTemplate.getMarkTemplates().stream() - .map(t -> getSharedSailingData().getMarkTemplateById(t.getUuid())).collect(Collectors.toList()); - final MarkRolePairFactory markPairTemplateFactory = new MarkRolePairFactory(); - final List waypoints = courseTemplate.getWaypointTemplates().stream() - .map(wp -> convertToWaypointTemplate(wp, markPairTemplateFactory)).collect(Collectors.toList()); - final Map defaultMarkRolesForMarkTemplates = courseTemplate.getDefaultMarkRolesForMarkTemplates().entrySet().stream() - .collect(Collectors.toMap( - entry -> getSharedSailingData().getMarkTemplateById(entry.getKey().getUuid()), - entry -> getSharedSailingData().getMarkRoleById(entry.getValue().getUuid()))); - final Map defaultMarkTemplatesForMarkRoles = courseTemplate.getDefaultMarkTemplatesForMarkRoles().entrySet().stream() - .collect(Collectors.toMap( - entry -> getSharedSailingData().getMarkRoleById(entry.getKey().getUuid()), - entry -> getSharedSailingData().getMarkTemplateById(entry.getValue().getUuid()))); - final RepeatablePart optionalRepeatablePart = courseTemplate.getRepeatablePart() != null - ? convertToRepeatablePart(courseTemplate.getRepeatablePart()) - : null; - result = convertToCourseTemplateDTO( - getSharedSailingData().createCourseTemplate(courseTemplate.getName(), courseTemplate.getShortName(), marks, - waypoints, defaultMarkRolesForMarkTemplates, defaultMarkTemplatesForMarkRoles, - optionalRepeatablePart, courseTemplate.getTags(), optionalImageURL, courseTemplate.getDefaultNumberOfLaps())); - } - return result; - } - - @Override - public void removeMarkProperties(Collection markPropertiesUuids) { - for (UUID uuid : markPropertiesUuids) { - getSharedSailingData().deleteMarkProperties(getSharedSailingData().getMarkPropertiesById(uuid)); - } - } - - private MarkRoleDTO convertToMarkRoleDTO(final MarkRole markRole) { + //READ + protected MarkRoleDTO convertToMarkRoleDTO(final MarkRole markRole) { final MarkRoleDTO markRoleDTO = new MarkRoleDTO(markRole.getId(), markRole.getName(), markRole.getShortName()); SecurityDTOUtil.addSecurityInformation(getSecurityService(), markRoleDTO, markRole.getIdentifier()); return markRoleDTO; } @Override + //READ public List getMarkRoles() { return getSecurityService().mapAndFilterByReadPermissionForCurrentUser(getSharedSailingData().getAllMarkRoles(), m -> convertToMarkRoleDTO(m)); } @Override - public MarkRoleDTO createMarkRole(MarkRoleDTO markRole) { - MarkRole existingMarkRole = getSharedSailingData().getMarkRoleById(markRole.getUuid()); - final MarkRoleDTO result; - if (existingMarkRole != null) { - throw new IllegalArgumentException("Mark role with ID "+markRole.getUuid()+" already exists"); - } else { - result = convertToMarkRoleDTO(getSharedSailingData().createMarkRole(markRole.getName(), markRole.getShortName())); + public EventDTO getEventById(UUID id, boolean withStatisticalData) throws MalformedURLException, UnauthorizedException { + EventDTO result = null; + Event event = getService().getEvent(id); + if (event != null) { + if (SecurityUtils.getSubject() + .isPermitted(SecuredDomainType.EVENT.getStringPermissionForObject(DefaultActions.READ, event))) { + result = convertToEventDTO(event, withStatisticalData); + result.setBaseURL(getEventBaseURLFromEventOrRequest(event)); + result.setIsOnRemoteServer(false); + } else { + throw new UnauthorizedException("You are not permitted to view event " + id); + } } return result; + } } \ No newline at end of file diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceWriteImpl.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceWriteImpl.java new file mode 100644 index 00000000000..61824cf9262 --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceWriteImpl.java @@ -0,0 +1,3488 @@ +package com.sap.sailing.gwt.ui.server; + +import java.awt.image.BufferedImage; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NavigableSet; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.logging.Level; +import java.util.stream.Collectors; + +import javax.imageio.metadata.IIOMetadata; +import javax.management.InvalidAttributeValueException; + +import org.apache.http.client.ClientProtocolException; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authz.AuthorizationException; +import org.apache.shiro.authz.UnauthorizedException; +import org.apache.shiro.subject.Subject; + +import com.sap.sailing.domain.abstractlog.AbstractLog; +import com.sap.sailing.domain.abstractlog.AbstractLogEvent; +import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; +import com.sap.sailing.domain.abstractlog.impl.AllEventsOfTypeFinder; +import com.sap.sailing.domain.abstractlog.impl.LogEventAuthorImpl; +import com.sap.sailing.domain.abstractlog.orc.BaseORCCertificateAssignmentAnalyzer; +import com.sap.sailing.domain.abstractlog.orc.ORCCertificateAssignmentEvent; +import com.sap.sailing.domain.abstractlog.orc.RaceLogORCCertificateAssignmentEvent; +import com.sap.sailing.domain.abstractlog.orc.RaceLogORCImpliedWindSourceEvent; +import com.sap.sailing.domain.abstractlog.orc.RaceLogORCLegDataAnalyzer; +import com.sap.sailing.domain.abstractlog.orc.RaceLogORCLegDataEvent; +import com.sap.sailing.domain.abstractlog.orc.RaceLogORCLegDataEventFinder; +import com.sap.sailing.domain.abstractlog.orc.RaceLogORCScratchBoatAnalyzer; +import com.sap.sailing.domain.abstractlog.orc.RaceLogORCScratchBoatEvent; +import com.sap.sailing.domain.abstractlog.orc.RaceLogORCScratchBoatFinder; +import com.sap.sailing.domain.abstractlog.orc.impl.RaceLogORCCertificateAssignmentEventImpl; +import com.sap.sailing.domain.abstractlog.orc.impl.RaceLogORCImpliedWindSourceEventImpl; +import com.sap.sailing.domain.abstractlog.orc.impl.RaceLogORCLegDataEventImpl; +import com.sap.sailing.domain.abstractlog.orc.impl.RaceLogORCScratchBoatEventImpl; +import com.sap.sailing.domain.abstractlog.orc.impl.RegattaLogORCCertificateAssignmentEventImpl; +import com.sap.sailing.domain.abstractlog.race.RaceLog; +import com.sap.sailing.domain.abstractlog.race.RaceLogCourseDesignChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogDependentStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogEndOfTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningConfirmedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFinishPositioningListChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFixedMarkPassingEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogFlagEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogGateLineOpeningTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogPathfinderEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogProtestStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogRaceStatusEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogStartOfTrackingEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogStartProcedureChangedEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogStartTimeEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogSuppressedMarkPassingsEvent; +import com.sap.sailing.domain.abstractlog.race.RaceLogWindFixEvent; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishedTimeFinder; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.FinishingTimeFinder; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.LastPublishedCourseDesignFinder; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinder; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.StartTimeFinderResult; +import com.sap.sailing.domain.abstractlog.race.analyzing.impl.TrackingTimesEventFinder; +import com.sap.sailing.domain.abstractlog.race.impl.BaseRaceLogEventVisitor; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogCourseDesignChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogDependentStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogEndOfTrackingEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningConfirmedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFinishPositioningListChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFixedMarkPassingEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogFlagEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogGateLineOpeningTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogPathfinderEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogProtestStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogRaceStatusEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartOfTrackingEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartProcedureChangedEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogStartTimeEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogSuppressedMarkPassingsEventImpl; +import com.sap.sailing.domain.abstractlog.race.impl.RaceLogWindFixEventImpl; +import com.sap.sailing.domain.abstractlog.race.scoring.RaceLogAdditionalScoringInformationEvent; +import com.sap.sailing.domain.abstractlog.race.scoring.impl.RaceLogAdditionalScoringInformationEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogRegisterCompetitorEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.RaceLogUseCompetitorsFromRaceLogEvent; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogDenoteForTrackingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogRegisterCompetitorEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogStartTrackingEventImpl; +import com.sap.sailing.domain.abstractlog.race.tracking.impl.RaceLogUseCompetitorsFromRaceLogEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLog; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEvent; +import com.sap.sailing.domain.abstractlog.regatta.RegattaLogEventVisitor; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogCloseOpenEndedDeviceMappingEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.RegattaLogDefineMarkEvent; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDefineMarkEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceBoatMappingEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorExpeditionExtendedMappingEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceCompetitorMappingEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.events.impl.RegattaLogDeviceMarkMappingEventImpl; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.BaseRegattaLogDeviceMappingFinder; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogDeviceMarkMappingFinder; +import com.sap.sailing.domain.abstractlog.regatta.tracking.analyzing.impl.RegattaLogOpenEndedDeviceMappingCloser; +import com.sap.sailing.domain.base.Boat; +import com.sap.sailing.domain.base.BoatClass; +import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorAndBoatStore; +import com.sap.sailing.domain.base.CompetitorWithBoat; +import com.sap.sailing.domain.base.ControlPoint; +import com.sap.sailing.domain.base.Course; +import com.sap.sailing.domain.base.CourseBase; +import com.sap.sailing.domain.base.Event; +import com.sap.sailing.domain.base.Fleet; +import com.sap.sailing.domain.base.Mark; +import com.sap.sailing.domain.base.Nationality; +import com.sap.sailing.domain.base.RaceColumn; +import com.sap.sailing.domain.base.RaceColumnInSeries; +import com.sap.sailing.domain.base.RaceDefinition; +import com.sap.sailing.domain.base.Regatta; +import com.sap.sailing.domain.base.Series; +import com.sap.sailing.domain.base.configuration.DeviceConfiguration; +import com.sap.sailing.domain.base.impl.BoatImpl; +import com.sap.sailing.domain.base.impl.CompetitorImpl; +import com.sap.sailing.domain.base.impl.CompetitorWithBoatImpl; +import com.sap.sailing.domain.base.impl.CourseDataImpl; +import com.sap.sailing.domain.base.impl.CourseImpl; +import com.sap.sailing.domain.base.impl.DynamicBoat; +import com.sap.sailing.domain.base.impl.DynamicCompetitorWithBoat; +import com.sap.sailing.domain.base.impl.DynamicPerson; +import com.sap.sailing.domain.base.impl.DynamicTeam; +import com.sap.sailing.domain.base.impl.EventBaseImpl; +import com.sap.sailing.domain.base.impl.PersonImpl; +import com.sap.sailing.domain.base.impl.TeamImpl; +import com.sap.sailing.domain.common.CompetitorDescriptor; +import com.sap.sailing.domain.common.CompetitorRegistrationType; +import com.sap.sailing.domain.common.CourseDesignerMode; +import com.sap.sailing.domain.common.DataImportProgress; +import com.sap.sailing.domain.common.LeaderboardNameConstants; +import com.sap.sailing.domain.common.MailInvitationType; +import com.sap.sailing.domain.common.MaxPointsReason; +import com.sap.sailing.domain.common.NoWindException; +import com.sap.sailing.domain.common.NotFoundException; +import com.sap.sailing.domain.common.PassingInstruction; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.RaceIdentifier; +import com.sap.sailing.domain.common.RankingMetrics; +import com.sap.sailing.domain.common.RegattaAndRaceIdentifier; +import com.sap.sailing.domain.common.RegattaIdentifier; +import com.sap.sailing.domain.common.RegattaName; +import com.sap.sailing.domain.common.RegattaNameAndRaceName; +import com.sap.sailing.domain.common.ScoringSchemeType; +import com.sap.sailing.domain.common.ServiceException; +import com.sap.sailing.domain.common.SpeedWithBearing; +import com.sap.sailing.domain.common.UnableToCloseDeviceMappingException; +import com.sap.sailing.domain.common.Wind; +import com.sap.sailing.domain.common.WindSource; +import com.sap.sailing.domain.common.WindSourceType; +import com.sap.sailing.domain.common.abstractlog.NotRevokableException; +import com.sap.sailing.domain.common.dto.BoatDTO; +import com.sap.sailing.domain.common.dto.CompetitorDTO; +import com.sap.sailing.domain.common.dto.CompetitorWithBoatDTO; +import com.sap.sailing.domain.common.dto.CourseAreaDTO; +import com.sap.sailing.domain.common.dto.FleetDTO; +import com.sap.sailing.domain.common.dto.PairingListDTO; +import com.sap.sailing.domain.common.dto.RaceColumnDTO; +import com.sap.sailing.domain.common.dto.RaceColumnInSeriesDTO; +import com.sap.sailing.domain.common.dto.RaceDTO; +import com.sap.sailing.domain.common.dto.RegattaCreationParametersDTO; +import com.sap.sailing.domain.common.dto.TagDTO; +import com.sap.sailing.domain.common.impl.KilometersPerHourSpeedImpl; +import com.sap.sailing.domain.common.impl.KnotSpeedImpl; +import com.sap.sailing.domain.common.impl.KnotSpeedWithBearingImpl; +import com.sap.sailing.domain.common.impl.WindImpl; +import com.sap.sailing.domain.common.impl.WindSourceImpl; +import com.sap.sailing.domain.common.media.MediaTrack; +import com.sap.sailing.domain.common.orc.ORCCertificate; +import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLeg; +import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveLegImpl; +import com.sap.sailing.domain.common.racelog.RaceLogRaceStatus; +import com.sap.sailing.domain.common.racelog.tracking.CompetitorRegistrationOnRaceLogDisabledException; +import com.sap.sailing.domain.common.racelog.tracking.DoesNotHaveRegattaLogException; +import com.sap.sailing.domain.common.racelog.tracking.NotDenotableForRaceLogTrackingException; +import com.sap.sailing.domain.common.racelog.tracking.NotDenotedForRaceLogTrackingException; +import com.sap.sailing.domain.common.racelog.tracking.TransformationException; +import com.sap.sailing.domain.common.security.SecuredDomainType; +import com.sap.sailing.domain.common.tagging.RaceLogNotFoundException; +import com.sap.sailing.domain.common.tagging.ServiceNotFoundException; +import com.sap.sailing.domain.common.tagging.TagAlreadyExistsException; +import com.sap.sailing.domain.common.tracking.GPSFix; +import com.sap.sailing.domain.common.tracking.impl.GPSFixImpl; +import com.sap.sailing.domain.coursetemplate.CourseTemplate; +import com.sap.sailing.domain.coursetemplate.MarkProperties; +import com.sap.sailing.domain.coursetemplate.MarkRole; +import com.sap.sailing.domain.coursetemplate.MarkRolePair.MarkRolePairFactory; +import com.sap.sailing.domain.coursetemplate.MarkTemplate; +import com.sap.sailing.domain.coursetemplate.RepeatablePart; +import com.sap.sailing.domain.coursetemplate.WaypointTemplate; +import com.sap.sailing.domain.igtimiadapter.Account; +import com.sap.sailing.domain.igtimiadapter.IgtimiConnection; +import com.sap.sailing.domain.igtimiadapter.IgtimiConnectionFactory; +import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.LeaderboardGroup; +import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; +import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; +import com.sap.sailing.domain.racelogtracking.DeviceMapping; +import com.sap.sailing.domain.regattalike.HasRegattaLike; +import com.sap.sailing.domain.regattalike.IsRegattaLike; +import com.sap.sailing.domain.regattalike.LeaderboardThatHasRegattaLike; +import com.sap.sailing.domain.resultimport.ResultUrlProvider; +import com.sap.sailing.domain.swisstimingadapter.StartList; +import com.sap.sailing.domain.swisstimingadapter.SwissTimingArchiveConfiguration; +import com.sap.sailing.domain.swisstimingadapter.SwissTimingConfiguration; +import com.sap.sailing.domain.trackimport.DoubleVectorFixImporter; +import com.sap.sailing.domain.tracking.DynamicTrackedRace; +import com.sap.sailing.domain.tracking.RaceHandle; +import com.sap.sailing.domain.tracking.RaceTracker; +import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.WindTrack; +import com.sap.sailing.domain.tractracadapter.RaceRecord; +import com.sap.sailing.domain.tractracadapter.TracTracConfiguration; +import com.sap.sailing.domain.tractracadapter.TracTracConnectionConstants; +import com.sap.sailing.expeditionconnector.ExpeditionDeviceConfiguration; +import com.sap.sailing.expeditionconnector.ExpeditionSensorDeviceIdentifier; +import com.sap.sailing.gwt.ui.adminconsole.RaceLogSetTrackingTimesDTO; +import com.sap.sailing.gwt.ui.client.SailingServiceWrite; +import com.sap.sailing.gwt.ui.shared.BulkScoreCorrectionDTO; +import com.sap.sailing.gwt.ui.shared.ControlPointDTO; +import com.sap.sailing.gwt.ui.shared.DeviceConfigurationDTO.RegattaConfigurationDTO; +import com.sap.sailing.gwt.ui.shared.DeviceIdentifierDTO; +import com.sap.sailing.gwt.ui.shared.DeviceMappingDTO; +import com.sap.sailing.gwt.ui.shared.EventDTO; +import com.sap.sailing.gwt.ui.shared.GPSFixDTO; +import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; +import com.sap.sailing.gwt.ui.shared.MarkDTO; +import com.sap.sailing.gwt.ui.shared.MigrateGroupOwnerForHierarchyDTO; +import com.sap.sailing.gwt.ui.shared.RegattaDTO; +import com.sap.sailing.gwt.ui.shared.SeriesDTO; +import com.sap.sailing.gwt.ui.shared.StrippedLeaderboardDTOWithSecurity; +import com.sap.sailing.gwt.ui.shared.SwissTimingArchiveConfigurationWithSecurityDTO; +import com.sap.sailing.gwt.ui.shared.SwissTimingConfigurationWithSecurityDTO; +import com.sap.sailing.gwt.ui.shared.SwissTimingRaceRecordDTO; +import com.sap.sailing.gwt.ui.shared.TracTracConfigurationWithSecurityDTO; +import com.sap.sailing.gwt.ui.shared.TracTracRaceRecordDTO; +import com.sap.sailing.gwt.ui.shared.TypedDeviceMappingDTO; +import com.sap.sailing.gwt.ui.shared.UrlDTO; +import com.sap.sailing.gwt.ui.shared.VenueDTO; +import com.sap.sailing.gwt.ui.shared.WindDTO; +import com.sap.sailing.gwt.ui.shared.courseCreation.CourseTemplateDTO; +import com.sap.sailing.gwt.ui.shared.courseCreation.MarkPropertiesDTO; +import com.sap.sailing.gwt.ui.shared.courseCreation.MarkRoleDTO; +import com.sap.sailing.gwt.ui.shared.courseCreation.MarkTemplateDTO; +import com.sap.sailing.server.hierarchy.SailingHierarchyOwnershipUpdater; +import com.sap.sailing.server.interfaces.RacingEventService; +import com.sap.sailing.server.operationaltransformation.AddColumnToLeaderboard; +import com.sap.sailing.server.operationaltransformation.AddColumnToSeries; +import com.sap.sailing.server.operationaltransformation.AddCourseAreas; +import com.sap.sailing.server.operationaltransformation.AddOrReplaceExpeditionDeviceConfiguration; +import com.sap.sailing.server.operationaltransformation.AddSpecificRegatta; +import com.sap.sailing.server.operationaltransformation.AllowBoatResetToDefaults; +import com.sap.sailing.server.operationaltransformation.AllowCompetitorResetToDefaults; +import com.sap.sailing.server.operationaltransformation.ConnectTrackedRaceToLeaderboardColumn; +import com.sap.sailing.server.operationaltransformation.CreateEvent; +import com.sap.sailing.server.operationaltransformation.CreateFlexibleLeaderboard; +import com.sap.sailing.server.operationaltransformation.CreateLeaderboardGroup; +import com.sap.sailing.server.operationaltransformation.CreateRegattaLeaderboard; +import com.sap.sailing.server.operationaltransformation.CreateRegattaLeaderboardWithEliminations; +import com.sap.sailing.server.operationaltransformation.DisconnectLeaderboardColumnFromTrackedRace; +import com.sap.sailing.server.operationaltransformation.MoveLeaderboardColumnDown; +import com.sap.sailing.server.operationaltransformation.MoveLeaderboardColumnUp; +import com.sap.sailing.server.operationaltransformation.RemoveAndUntrackRace; +import com.sap.sailing.server.operationaltransformation.RemoveColumnFromSeries; +import com.sap.sailing.server.operationaltransformation.RemoveCourseAreas; +import com.sap.sailing.server.operationaltransformation.RemoveEvent; +import com.sap.sailing.server.operationaltransformation.RemoveExpeditionDeviceConfiguration; +import com.sap.sailing.server.operationaltransformation.RemoveLeaderboard; +import com.sap.sailing.server.operationaltransformation.RemoveLeaderboardColumn; +import com.sap.sailing.server.operationaltransformation.RemoveLeaderboardGroup; +import com.sap.sailing.server.operationaltransformation.RemoveRegatta; +import com.sap.sailing.server.operationaltransformation.RemoveSeries; +import com.sap.sailing.server.operationaltransformation.RenameEvent; +import com.sap.sailing.server.operationaltransformation.RenameLeaderboardColumn; +import com.sap.sailing.server.operationaltransformation.SetRaceIsKnownToStartUpwind; +import com.sap.sailing.server.operationaltransformation.SetSuppressedFlagForCompetitorInLeaderboard; +import com.sap.sailing.server.operationaltransformation.SetWindSourcesToExclude; +import com.sap.sailing.server.operationaltransformation.StopTrackingRace; +import com.sap.sailing.server.operationaltransformation.UpdateBoat; +import com.sap.sailing.server.operationaltransformation.UpdateCompetitor; +import com.sap.sailing.server.operationaltransformation.UpdateCompetitorDisplayNameInLeaderboard; +import com.sap.sailing.server.operationaltransformation.UpdateEliminatedCompetitorsInLeaderboard; +import com.sap.sailing.server.operationaltransformation.UpdateEvent; +import com.sap.sailing.server.operationaltransformation.UpdateIsMedalRace; +import com.sap.sailing.server.operationaltransformation.UpdateLeaderboard; +import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardCarryValue; +import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardColumnFactor; +import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardGroup; +import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardMaxPointsReason; +import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardScoreCorrection; +import com.sap.sailing.server.operationaltransformation.UpdateLeaderboardScoreCorrectionMetadata; +import com.sap.sailing.server.operationaltransformation.UpdateRaceDelayToLive; +import com.sap.sailing.server.operationaltransformation.UpdateSeries; +import com.sap.sailing.server.operationaltransformation.UpdateSpecificRegatta; +import com.sap.sailing.server.util.WaitForTrackedRaceUtil; +import com.sap.sailing.xrr.schema.RegattaResults; +import com.sap.sse.common.Duration; +import com.sap.sse.common.NoCorrespondingServiceRegisteredException; +import com.sap.sse.common.Speed; +import com.sap.sse.common.TimePoint; +import com.sap.sse.common.TimeRange; +import com.sap.sse.common.Util; +import com.sap.sse.common.Util.Pair; +import com.sap.sse.common.Util.Triple; +import com.sap.sse.common.impl.DegreeBearingImpl; +import com.sap.sse.common.impl.MillisecondsTimePoint; +import com.sap.sse.common.impl.TimeRangeImpl; +import com.sap.sse.common.mail.MailException; +import com.sap.sse.common.media.MediaTagConstants; +import com.sap.sse.filestorage.FileStorageManagementService; +import com.sap.sse.filestorage.FileStorageService; +import com.sap.sse.filestorage.InvalidPropertiesException; +import com.sap.sse.filestorage.OperationFailedException; +import com.sap.sse.gwt.client.media.ImageDTO; +import com.sap.sse.gwt.client.media.ImageResizingTaskDTO; +import com.sap.sse.gwt.client.media.VideoDTO; +import com.sap.sse.gwt.server.filestorage.FileStorageServiceDTOUtils; +import com.sap.sse.gwt.shared.filestorage.FileStorageServiceDTO; +import com.sap.sse.gwt.shared.filestorage.FileStorageServicePropertyErrorsDTO; +import com.sap.sse.security.Action; +import com.sap.sse.security.shared.HasPermissions.DefaultActions; +import com.sap.sse.security.shared.QualifiedObjectIdentifier; +import com.sap.sse.security.shared.TypeRelativeObjectIdentifier; +import com.sap.sse.security.shared.impl.SecuredSecurityTypes.ServerActions; +import com.sap.sse.security.ui.server.SecurityDTOUtil; +import com.sap.sse.security.ui.shared.SuccessInfo; +import com.sap.sse.shared.media.ImageDescriptor; +import com.sap.sse.shared.media.VideoDescriptor; +import com.sap.sse.util.HttpUrlConnectionHelper; +import com.sap.sse.util.ImageConverter; +import com.sap.sse.util.ImageConverter.ImageWithMetadata; +import com.sap.sse.util.impl.UUIDHelper; + +public class SailingServiceWriteImpl extends SailingServiceImpl implements SailingServiceWrite { + + /** serial version uid */ + private static final long serialVersionUID = -992637440342246674L; + + // WRITE + public static class TimeoutExtendingInputStream extends FilterInputStream { + + // default timeout is high to ensure that long running client operations + // such as compressing data will not have the server run into a timeout. + // this especially applies to foiling data where compression on slower machines + // can take up to two hours. + private static final int DEFAULT_TIMEOUT_IN_SECONDS = 60 * 60 * 2; + + private final URLConnection connection; + + public TimeoutExtendingInputStream(InputStream in, URLConnection connection) { + super(in); + this.connection = connection; + } + + @Override + public int read() throws IOException { + connection.setReadTimeout(DEFAULT_TIMEOUT_IN_SECONDS * 1000); + return super.read(); + } + + @Override + public int read(byte[] b) throws IOException { + connection.setReadTimeout(DEFAULT_TIMEOUT_IN_SECONDS * 1000); + return super.read(b); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + connection.setReadTimeout(DEFAULT_TIMEOUT_IN_SECONDS * 1000); + return super.read(b, off, len); + } + + } + + @Override + public MarkRoleDTO createMarkRole(MarkRoleDTO markRole) { + MarkRole existingMarkRole = getSharedSailingData().getMarkRoleById(markRole.getUuid()); + final MarkRoleDTO result; + if (existingMarkRole != null) { + throw new IllegalArgumentException("Mark role with ID " + markRole.getUuid() + " already exists"); + } else { + result = convertToMarkRoleDTO( + getSharedSailingData().createMarkRole(markRole.getName(), markRole.getShortName())); + } + return result; + } + + @Override + public void removeMarkProperties(Collection markPropertiesUuids) { + for (UUID uuid : markPropertiesUuids) { + getSharedSailingData().deleteMarkProperties(getSharedSailingData().getMarkPropertiesById(uuid)); + } + } + + @Override + public CourseTemplateDTO createOrUpdateCourseTemplate(CourseTemplateDTO courseTemplate) { + CourseTemplate existingCourseTemplate = getSharedSailingData().getCourseTemplateById(courseTemplate.getUuid()); + URL optionalImageURL = null; + try { + optionalImageURL = courseTemplate.getOptionalImageUrl().isPresent() + ? new URL(courseTemplate.getOptionalImageUrl().get()) + : null; + } catch (MalformedURLException e) { + throw new IllegalArgumentException( + String.format("Invalid URL: %s", courseTemplate.getOptionalImageUrl().get())); + } + final CourseTemplateDTO result; + if (existingCourseTemplate != null) { + getSecurityService().checkCurrentUserUpdatePermission(existingCourseTemplate); + result = convertToCourseTemplateDTO(getSharedSailingData().updateCourseTemplate(courseTemplate.getUuid(), + courseTemplate.getName(), courseTemplate.getShortName(), optionalImageURL, courseTemplate.getTags(), + courseTemplate.getDefaultNumberOfLaps())); + } else { + final List marks = courseTemplate.getMarkTemplates().stream() + .map(t -> getSharedSailingData().getMarkTemplateById(t.getUuid())).collect(Collectors.toList()); + final MarkRolePairFactory markPairTemplateFactory = new MarkRolePairFactory(); + final List waypoints = courseTemplate.getWaypointTemplates().stream() + .map(wp -> convertToWaypointTemplate(wp, markPairTemplateFactory)).collect(Collectors.toList()); + final Map defaultMarkRolesForMarkTemplates = courseTemplate.getDefaultMarkRolesForMarkTemplates().entrySet().stream() + .collect(Collectors.toMap( + entry -> getSharedSailingData().getMarkTemplateById(entry.getKey().getUuid()), + entry -> getSharedSailingData().getMarkRoleById(entry.getValue().getUuid()))); + final Map defaultMarkTemplatesForMarkRoles = courseTemplate.getDefaultMarkTemplatesForMarkRoles().entrySet().stream() + .collect(Collectors.toMap( + entry -> getSharedSailingData().getMarkRoleById(entry.getKey().getUuid()), + entry -> getSharedSailingData().getMarkTemplateById(entry.getValue().getUuid()))); + final RepeatablePart optionalRepeatablePart = courseTemplate.getRepeatablePart() != null + ? convertToRepeatablePart(courseTemplate.getRepeatablePart()) + : null; + result = convertToCourseTemplateDTO( + getSharedSailingData().createCourseTemplate(courseTemplate.getName(), courseTemplate.getShortName(), marks, + waypoints, defaultMarkRolesForMarkTemplates, defaultMarkTemplatesForMarkRoles, + optionalRepeatablePart, courseTemplate.getTags(), optionalImageURL, courseTemplate.getDefaultNumberOfLaps())); + } + return result; + } + + @Override + public MarkPropertiesDTO updateMarkPropertiesPositioning(UUID markPropertiesId, DeviceIdentifierDTO deviceIdentifier, + Position fixedPosition) { + MarkProperties markProperties = getSharedSailingData().getMarkPropertiesById(markPropertiesId); + if (deviceIdentifier != null) { + getSharedSailingData().setTrackingDeviceIdentifierForMarkProperties(markProperties, convertDtoToDeviceIdentifier(deviceIdentifier)); + } else if (fixedPosition != null) { + getSharedSailingData().setFixedPositionForMarkProperties(markProperties, fixedPosition); + } else { + getSharedSailingData().clearPositioningForMarkProperties(markProperties); + } + return convertToMarkPropertiesDTO(getSharedSailingData().updateMarkProperties(markProperties.getId(), + markProperties, markProperties.getTags())); + } + + @Override + public MarkPropertiesDTO addOrUpdateMarkProperties(MarkPropertiesDTO markProperties) { + MarkProperties createdOrUpdatedMarkProperties = getSharedSailingData() + .getMarkPropertiesById(markProperties.getUuid()); + if (createdOrUpdatedMarkProperties != null) { + getSecurityService().checkCurrentUserUpdatePermission(createdOrUpdatedMarkProperties); + getSharedSailingData().updateMarkProperties(markProperties.getUuid(), + convertDtoToCommonMarkProperties(markProperties.getCommonMarkProperties()), + markProperties.getTags()); + createdOrUpdatedMarkProperties = getSharedSailingData() + .getMarkPropertiesById(createdOrUpdatedMarkProperties.getId()); + } else { + createdOrUpdatedMarkProperties = getSecurityService() + .setOwnershipCheckPermissionForObjectCreationAndRevertOnError(SecuredDomainType.MARK_PROPERTIES, + MarkTemplate.getTypeRelativeObjectIdentifier(UUID.randomUUID()), markProperties.getName(), + () -> getSharedSailingData().createMarkProperties( + convertDtoToCommonMarkProperties(markProperties.getCommonMarkProperties()), + markProperties.getTags(), + /* non-default mark properties group ownership */ Optional.empty())); + } + return convertToMarkPropertiesDTO(createdOrUpdatedMarkProperties); + } + + @Override + public void trackWithTracTrac(RegattaIdentifier regattaToAddTo, List rrs, String liveURI, String storedURI, + String courseDesignUpdateURI, boolean trackWind, final boolean correctWindByDeclination, + final Duration offsetToStartTimeOfSimulatedRace, final boolean useInternalMarkPassingAlgorithm, + boolean useOfficialEventsToUpdateRaceLog, String tracTracUsername, String tracTracPassword) + throws Exception { + logger.info("tracWithTracTrac for regatta " + regattaToAddTo + " for race records " + rrs + " with liveURI " + liveURI + + " and storedURI " + storedURI); + for (TracTracRaceRecordDTO rr : rrs) { + try { + // reload JSON and load clientparams.php + RaceRecord record = getTracTracAdapter().getSingleTracTracRaceRecord(new URL(rr.jsonURL), rr.id, /*loadClientParams*/true); + logger.info("Loaded race " + record.getName() + " in " + record.getEventName() + " start:" + record.getRaceStartTime() + + " trackingStart:" + record.getTrackingStartTime() + " trackingEnd:" + record.getTrackingEndTime()); + // note that the live URI may be null for races that were put into replay mode + final String effectiveLiveURI; + if (!record.getRaceStatus().equals(TracTracConnectionConstants.REPLAY_STATUS)) { + if (liveURI == null || liveURI.trim().length() == 0) { + effectiveLiveURI = record.getLiveURI() == null ? null : record.getLiveURI().toString(); + } else { + effectiveLiveURI = liveURI; + } + } else { + effectiveLiveURI = null; + } + final String effectiveStoredURI; + if (storedURI == null || storedURI.trim().length() == 0) { + effectiveStoredURI = record.getStoredURI().toString(); + } else { + effectiveStoredURI = storedURI; + } + getTracTracAdapter().addTracTracRace(getService(), regattaToAddTo, + record.getParamURL(), effectiveLiveURI == null ? null : new URI(effectiveLiveURI), + new URI(effectiveStoredURI), new URI(courseDesignUpdateURI), + new MillisecondsTimePoint(record.getTrackingStartTime().asMillis()), + new MillisecondsTimePoint(record.getTrackingEndTime().asMillis()), getRaceLogStore(), + getRegattaLogStore(), RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS, + offsetToStartTimeOfSimulatedRace, useInternalMarkPassingAlgorithm, tracTracUsername, + tracTracPassword, record.getRaceStatus(), record.getRaceVisibility(), trackWind, + correctWindByDeclination, useOfficialEventsToUpdateRaceLog); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error trying to load race " + rrs+". Continuing with remaining races...", e); + } + } + } + + @Override + public void createTracTracConfiguration(String name, String jsonURL, String liveDataURI, String storedDataURI, + String courseDesignUpdateURI, String tracTracUsername, String tracTracPassword) throws Exception { + if (existsTracTracConfigurationForCurrentUser(jsonURL)) { + throw new RuntimeException("A configuration for the current user with this json URL already exists."); + } + final String currentUserName = getSecurityService().getCurrentUser().getName(); + final TypeRelativeObjectIdentifier identifier = TracTracConfiguration.getTypeRelativeObjectIdentifier(jsonURL, currentUserName); + getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( + SecuredDomainType.TRACTRAC_ACCOUNT, + identifier, name, + () -> tractracMongoObjectFactory.createTracTracConfiguration( + getTracTracAdapter().createTracTracConfiguration(currentUserName, name, jsonURL, liveDataURI, + storedDataURI, + courseDesignUpdateURI, tracTracUsername, tracTracPassword))); + } + + @Override + public void deleteTracTracConfigurations(Collection tracTracConfigurations) { + for (TracTracConfigurationWithSecurityDTO tracTracConfiguration : tracTracConfigurations) { + getSecurityService().checkCurrentUserDeletePermission(tracTracConfiguration); + getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(tracTracConfiguration, + () -> tractracMongoObjectFactory.deleteTracTracConfiguration(tracTracConfiguration.getCreatorName(), + tracTracConfiguration.getJsonUrl())); + } + } + + @Override + public void updateTracTracConfiguration(TracTracConfigurationWithSecurityDTO tracTracConfiguration) + throws Exception { + getSecurityService().checkCurrentUserUpdatePermission(tracTracConfiguration); + tractracMongoObjectFactory.updateTracTracConfiguration( + getTracTracAdapter().createTracTracConfiguration(tracTracConfiguration.getCreatorName(), + tracTracConfiguration.getName(), tracTracConfiguration.getJsonUrl(), + tracTracConfiguration.getLiveDataURI(), tracTracConfiguration.getStoredDataURI(), + tracTracConfiguration.getCourseDesignUpdateURI(), tracTracConfiguration.getTracTracUsername(), + tracTracConfiguration.getTracTracPassword())); + } + + @Override + public void stopTrackingRaces(List regattaAndRaceIdentifiers) throws Exception { + for (RegattaAndRaceIdentifier regattaAndRaceIdentifier : regattaAndRaceIdentifiers) { + getSecurityService().checkCurrentUserUpdatePermission(regattaAndRaceIdentifier); + getService().apply(new StopTrackingRace(regattaAndRaceIdentifier)); + } + } + + @Override + public void removeAndUntrackRaces(List regattaAndRaceIdentifiers) { + for (RegattaAndRaceIdentifier regattaAndRaceIdentifier : regattaAndRaceIdentifiers) { + getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(regattaAndRaceIdentifier, + () -> getService().apply(new RemoveAndUntrackRace(regattaAndRaceIdentifier))); + } + } + + @Override + public void setWind(RegattaAndRaceIdentifier raceIdentifier, WindDTO windDTO) { + DynamicTrackedRace trackedRace = (DynamicTrackedRace) getExistingTrackedRace(raceIdentifier); + if (trackedRace != null) { + getSecurityService().checkCurrentUserUpdatePermission(trackedRace); + Position p = null; + if (windDTO.position != null) { + p = windDTO.position; + } + TimePoint at = null; + if (windDTO.measureTimepoint != null) { + at = new MillisecondsTimePoint(windDTO.measureTimepoint); + } + SpeedWithBearing speedWithBearing = null; + Speed speed = null; + if (windDTO.trueWindSpeedInKnots != null) { + speed = new KnotSpeedImpl(windDTO.trueWindSpeedInKnots); + } else if (windDTO.trueWindSpeedInMetersPerSecond != null) { + speed = new KilometersPerHourSpeedImpl(windDTO.trueWindSpeedInMetersPerSecond * 3600. / 1000.); + } else if (windDTO.dampenedTrueWindSpeedInKnots != null) { + speed = new KnotSpeedImpl(windDTO.dampenedTrueWindSpeedInKnots); + } else if (windDTO.dampenedTrueWindSpeedInMetersPerSecond != null) { + speed = new KilometersPerHourSpeedImpl(windDTO.dampenedTrueWindSpeedInMetersPerSecond * 3600. / 1000.); + } + if (speed != null) { + if (windDTO.trueWindBearingDeg != null) { + speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), + new DegreeBearingImpl(windDTO.trueWindBearingDeg)); + } else if (windDTO.trueWindFromDeg != null) { + speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), + new DegreeBearingImpl(windDTO.trueWindFromDeg).reverse()); + } + } + Wind wind = new WindImpl(p, at, speedWithBearing); + Iterable webWindSources = trackedRace.getWindSources(WindSourceType.WEB); + if (Util.size(webWindSources) == 0) { + // create a new WEB wind source if not available + trackedRace.recordWind(wind, new WindSourceImpl(WindSourceType.WEB)); + } else { + trackedRace.recordWind(wind, webWindSources.iterator().next()); + } + } + } + + /** + * Creates new ControlPoints, if nThe resulting list of control points is then passed to + * {@link Course#update(List, com.sap.sailing.domain.base.DomainFactory)} for the course of the race identified by + * raceIdentifier. + */ + @Override + public void updateRaceCourse(RegattaAndRaceIdentifier raceIdentifier, + List> courseDTO) { + TrackedRace trackedRace = getExistingTrackedRace(raceIdentifier); + if (trackedRace != null) { + getSecurityService().checkCurrentUserUpdatePermission(trackedRace); + Course course = trackedRace.getRace().getCourse(); + List> controlPoints = new ArrayList<>(); + for (Pair waypointDTO : courseDTO) { + controlPoints.add(new Pair<>(getOrCreateControlPoint(waypointDTO.getA()), waypointDTO.getB())); + } + try { + course.update(controlPoints, course.getAssociatedRoles(), course.getOriginatingCourseTemplateIdOrNull(), + baseDomainFactory); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + @Override + public void setRaceIsKnownToStartUpwind(RegattaAndRaceIdentifier raceIdentifier, boolean raceIsKnownToStartUpwind) { + getSecurityService().checkCurrentUserUpdatePermission(raceIdentifier); + getService().apply(new SetRaceIsKnownToStartUpwind(raceIdentifier, raceIsKnownToStartUpwind)); + } + + @Override + public void setWindSourcesToExclude(RegattaAndRaceIdentifier raceIdentifier, + List windSourcesToExclude) { + getSecurityService().checkCurrentUserUpdatePermission(raceIdentifier); + getService().apply(new SetWindSourcesToExclude(raceIdentifier, windSourcesToExclude)); + } + + @Override + public void removeWind(RegattaAndRaceIdentifier raceIdentifier, WindDTO windDTO) { + DynamicTrackedRace trackedRace = (DynamicTrackedRace) getExistingTrackedRace(raceIdentifier); + if (trackedRace != null) { + getSecurityService().checkCurrentUserUpdatePermission(trackedRace); + Position p = null; + if (windDTO.position != null) { + p = windDTO.position; + } + TimePoint at = null; + if (windDTO.measureTimepoint != null) { + at = new MillisecondsTimePoint(windDTO.measureTimepoint); + } + SpeedWithBearing speedWithBearing = null; + Speed speed = null; + if (windDTO.trueWindSpeedInKnots != null) { + speed = new KnotSpeedImpl(windDTO.trueWindSpeedInKnots); + } else if (windDTO.trueWindSpeedInMetersPerSecond != null) { + speed = new KilometersPerHourSpeedImpl(windDTO.trueWindSpeedInMetersPerSecond * 3600. / 1000.); + } else if (windDTO.dampenedTrueWindSpeedInKnots != null) { + speed = new KnotSpeedImpl(windDTO.dampenedTrueWindSpeedInKnots); + } else if (windDTO.dampenedTrueWindSpeedInMetersPerSecond != null) { + speed = new KilometersPerHourSpeedImpl(windDTO.dampenedTrueWindSpeedInMetersPerSecond * 3600. / 1000.); + } + if (speed != null) { + if (windDTO.trueWindBearingDeg != null) { + speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), + new DegreeBearingImpl(windDTO.trueWindBearingDeg)); + } else if (windDTO.trueWindFromDeg != null) { + speedWithBearing = new KnotSpeedWithBearingImpl(speed.getKnots(), + new DegreeBearingImpl(windDTO.trueWindFromDeg).reverse()); + } + } + Wind wind = new WindImpl(p, at, speedWithBearing); + trackedRace.removeWind(wind, trackedRace.getWindSources(WindSourceType.WEB).iterator().next()); + } + } + + @Override + public void createRegattaStructure(final List regattas, final EventDTO newEvent) throws MalformedURLException { + final List leaderboardNames = new ArrayList(); + for (RegattaDTO regatta : regattas) { + createRegattaFromRegattaDTO(regatta); + addRaceColumnsToRegattaSeries(regatta); + if (getLeaderboard(regatta.getName()) == null) { + leaderboardNames.add(regatta.getName()); + createRegattaLeaderboard(new RegattaName(regatta.getName()), regatta.boatClass.toString(), new int[0]); + } + } + createAndAddLeaderboardGroup(newEvent, leaderboardNames); + // TODO find a way to import the competitors for the selected regattas. You'll need the regattas as + // Iterable + // structureImporter.setCompetitors(regattas, ""); + } + + @Override + public void createSwissTimingArchiveConfiguration(final String jsonURL) + throws Exception { + if (existsSwissTimingArchiveConfigurationForCurrentUser(jsonURL)) { + throw new RuntimeException("A configuration for the current user with this json URL already exists."); + } + final String currentUserName = getSecurityService().getCurrentUser().getName(); + final TypeRelativeObjectIdentifier identifier = SwissTimingArchiveConfiguration + .getTypeRelativeObjectIdentifier(jsonURL, currentUserName); + getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( + SecuredDomainType.SWISS_TIMING_ARCHIVE_ACCOUNT, + identifier, identifier.toString(), + () -> swissTimingAdapterPersistence.createSwissTimingArchiveConfiguration( + swissTimingFactory.createSwissTimingArchiveConfiguration(jsonURL, + currentUserName))); + } + + @Override + public void updateSwissTimingArchiveConfiguration(SwissTimingArchiveConfigurationWithSecurityDTO dto) + throws Exception { + getSecurityService().checkCurrentUserUpdatePermission(dto); + swissTimingAdapterPersistence.updateSwissTimingArchiveConfiguration( + swissTimingFactory.createSwissTimingArchiveConfiguration(dto.getJsonUrl(), dto.getCreatorName())); + } + + @Override + public void deleteSwissTimingArchiveConfigurations(Collection dtos) + throws Exception { + for (SwissTimingArchiveConfigurationWithSecurityDTO dto : dtos) { + getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(dto.getIdentifier(), + () -> swissTimingAdapterPersistence.deleteSwissTimingArchiveConfiguration(swissTimingFactory + .createSwissTimingArchiveConfiguration(dto.getJsonUrl(), dto.getCreatorName()))); + } + } + + @Override + public void removeResultImportURLs(String resultProviderName, Set toRemove) throws Exception { + final RacingEventService racingEventService = getService(); + Set urlsToRemove = toRemove.stream().map(urlDto -> { + try { + return new URL(urlDto.getUrl()); + } catch (MalformedURLException e) { + return null; + } + }).filter(url -> url != null).collect(Collectors.toSet()); + racingEventService.removeResultImportURLs(resultProviderName, urlsToRemove); + } + + @Override + public void addResultImportUrl(String resultProviderName, UrlDTO urlDTO) throws Exception { + final RacingEventService racingEventService = getService(); + ResultUrlProvider resultUrlProvider = racingEventService.getUrlBasedScoreCorrectionProvider(resultProviderName) + .orElseThrow(() -> new IllegalStateException("ResultUrlProvider not found: " + resultProviderName)); + final URL url = resultUrlProvider.resolveUrl(urlDTO.getUrl()); + racingEventService.addResultImportUrl(resultProviderName, url); + } + + @Override + public StrippedLeaderboardDTOWithSecurity createFlexibleLeaderboard(String leaderboardName, + String leaderboardDisplayName, int[] discardThresholds, ScoringSchemeType scoringSchemeType, + List courseAreaIds) { + return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( + SecuredDomainType.LEADERBOARD, Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName), + leaderboardDisplayName, new Callable() { + @Override + public StrippedLeaderboardDTOWithSecurity call() throws Exception { + return createStrippedLeaderboardDTOWithSecurity( + getService().apply(new CreateFlexibleLeaderboard(leaderboardName, + leaderboardDisplayName, discardThresholds, + baseDomainFactory.createScoringScheme(scoringSchemeType), courseAreaIds)), false, false); + } + }); + } + + @Override + public StrippedLeaderboardDTOWithSecurity createRegattaLeaderboard(RegattaName regattaIdentifier, + String leaderboardDisplayName, int[] discardThresholds) { + return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( + SecuredDomainType.LEADERBOARD, Leaderboard.getTypeRelativeObjectIdentifier(regattaIdentifier), + leaderboardDisplayName, new Callable() { + @Override + public StrippedLeaderboardDTOWithSecurity call() throws Exception { + return createStrippedLeaderboardDTOWithSecurity(getService().apply(new CreateRegattaLeaderboard( + regattaIdentifier, leaderboardDisplayName, discardThresholds)), false, false); + } + }); + } + + @Override + public StrippedLeaderboardDTOWithSecurity createRegattaLeaderboardWithEliminations(String name, String displayName, + String fullRegattaLeaderboardName) { + return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( + SecuredDomainType.LEADERBOARD, Leaderboard.getTypeRelativeObjectIdentifier(name), displayName, + new Callable() { + @Override + public StrippedLeaderboardDTOWithSecurity call() throws Exception { + return createStrippedLeaderboardDTOWithSecurity( + getService().apply(new CreateRegattaLeaderboardWithEliminations(name, displayName, + fullRegattaLeaderboardName)), + false, false); + } + }); + } + + @Override + public StrippedLeaderboardDTOWithSecurity updateLeaderboard(String leaderboardName, String newLeaderboardDisplayName, + int[] newDiscardingThresholds, List newCourseAreaIds) { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + Leaderboard updatedLeaderboard = getService().apply( + new UpdateLeaderboard(leaderboardName, newLeaderboardDisplayName, newDiscardingThresholds, newCourseAreaIds)); + return createStrippedLeaderboardDTOWithSecurity(updatedLeaderboard, false, false); + } + + @Override + public void removeLeaderboards(Collection leaderboardNames) { + for (String leaderboardName : leaderboardNames) { + removeLeaderboard(leaderboardName); + } + } + + @Override + public void removeLeaderboard(String leaderboardName) { + Leaderboard leaderBoard = getService().getLeaderboardByName(leaderboardName); + if (leaderBoard != null) { + getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(leaderBoard, new Action() { + @Override + public void run() throws Exception { + getService().apply(new RemoveLeaderboard(leaderboardName)); + } + }); + } + } + + @Override + public void addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace) { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + getService().apply(new AddColumnToLeaderboard(columnName, leaderboardName, medalRace)); + } + + @Override + public void removeLeaderboardGroups(Set groupNames) { + for (String groupName : groupNames) { + removeLeaderboardGroup(groupName); + } + } + + private void removeLeaderboardGroup(String groupName) { + LeaderboardGroup group = getService().getLeaderboardGroupByName(groupName); + if (group != null) { + if (group.getOverallLeaderboard() != null) { + removeLeaderboard(group.getOverallLeaderboard().getName()); + } + + getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(group, new Action() { + @Override + public void run() throws Exception { + getService().apply(new RemoveLeaderboardGroup(groupName)); + } + }); + } + } + + @Override + public void addColumnsToLeaderboard(String leaderboardName, + List> columnsToAdd) { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + for (com.sap.sse.common.Util.Pair columnToAdd : columnsToAdd) { + getService().apply(new AddColumnToLeaderboard(columnToAdd.getA(), leaderboardName, columnToAdd.getB())); + } + } + + @Override + public void removeLeaderboardColumn(String leaderboardName, String columnName) { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + getService().apply(new RemoveLeaderboardColumn(columnName, leaderboardName)); + } + + @Override + public void renameLeaderboardColumn(String leaderboardName, String oldColumnName, String newColumnName) { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + getService().apply(new RenameLeaderboardColumn(leaderboardName, oldColumnName, newColumnName)); + } + + @Override + public void updateLeaderboardColumnFactor(String leaderboardName, String columnName, Double newFactor) { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + getService().apply(new UpdateLeaderboardColumnFactor(leaderboardName, columnName, newFactor)); + } + + @Override + public void suppressCompetitorInLeaderboard(String leaderboardName, String competitorIdAsString, + boolean suppressed) { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + getService().apply( + new SetSuppressedFlagForCompetitorInLeaderboard(leaderboardName, competitorIdAsString, suppressed)); + } + + @Override + public boolean connectTrackedRaceToLeaderboardColumn(String leaderboardName, String raceColumnName, + String fleetName, RegattaAndRaceIdentifier raceIdentifier) { + final Subject subject = SecurityUtils.getSubject(); + subject.checkPermission(SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier( + DefaultActions.UPDATE, Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + Object principal = subject.getPrincipal(); + if (principal != null) { + logger.info(String.format("%s linked race column %s %s (%s) with tracked race %s.", principal.toString(), + leaderboardName, raceColumnName, fleetName, raceIdentifier.getRaceName())); + } else { + logger.info(String.format("Linked race column %s %s (%s) with tracked race %s.", leaderboardName, + raceColumnName, fleetName, raceIdentifier.getRaceName())); + } + return getService().apply( + new ConnectTrackedRaceToLeaderboardColumn(leaderboardName, raceColumnName, fleetName, raceIdentifier)); + } + + @Override + public void disconnectLeaderboardColumnFromTrackedRace(String leaderboardName, String raceColumnName, + String fleetName) { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + getService().apply(new DisconnectLeaderboardColumnFromTrackedRace(leaderboardName, raceColumnName, fleetName)); + } + + @Override + public void updateLeaderboardCarryValue(String leaderboardName, String competitorIdAsString, Double carriedPoints) { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + getService().apply(new UpdateLeaderboardCarryValue(leaderboardName, competitorIdAsString, carriedPoints)); + } + + @Override + public com.sap.sse.common.Util.Triple updateLeaderboardMaxPointsReason( + String leaderboardName, String competitorIdAsString, String raceColumnName, MaxPointsReason maxPointsReason, + Date date) throws NoWindException { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + return getService().apply(new UpdateLeaderboardMaxPointsReason(leaderboardName, raceColumnName, + competitorIdAsString, maxPointsReason, new MillisecondsTimePoint(date))); + } + + @Override + public com.sap.sse.common.Util.Triple updateLeaderboardScoreCorrection( + String leaderboardName, String competitorIdAsString, String columnName, Double correctedScore, Date date) + throws NoWindException { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + return getService().apply(new UpdateLeaderboardScoreCorrection(leaderboardName, columnName, + competitorIdAsString, correctedScore, new MillisecondsTimePoint(date))); + } + + @Override + public void updateLeaderboardScoreCorrectionMetadata(String leaderboardName, Date timePointOfLastCorrectionValidity, + String comment) { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + getService().apply(new UpdateLeaderboardScoreCorrectionMetadata(leaderboardName, + timePointOfLastCorrectionValidity == null ? null + : new MillisecondsTimePoint(timePointOfLastCorrectionValidity), + comment)); + } + + @Override + public void updateLeaderboardScoreCorrectionsAndMaxPointsReasons(BulkScoreCorrectionDTO updates) + throws NoWindException { + SecurityUtils.getSubject() + .checkPermission(SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier( + DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(updates.getLeaderboardName()))); + Date dateForResults = new Date(); // we don't care about the result date/time here; use current date as default + for (Map.Entry> e : updates.getScoreUpdatesForRaceColumnByCompetitorIdAsString() + .entrySet()) { + for (Map.Entry raceColumnNameAndCorrectedScore : e.getValue().entrySet()) { + updateLeaderboardScoreCorrection(updates.getLeaderboardName(), e.getKey(), + raceColumnNameAndCorrectedScore.getKey(), raceColumnNameAndCorrectedScore.getValue(), + dateForResults); + } + } + for (Map.Entry> e : updates + .getMaxPointsUpdatesForRaceColumnByCompetitorIdAsString().entrySet()) { + for (Map.Entry raceColumnNameAndNewMaxPointsReason : e.getValue().entrySet()) { + updateLeaderboardMaxPointsReason(updates.getLeaderboardName(), e.getKey(), + raceColumnNameAndNewMaxPointsReason.getKey(), raceColumnNameAndNewMaxPointsReason.getValue(), + dateForResults); + } + } + } + + @Override + public void updateCompetitorDisplayNameInLeaderboard(String leaderboardName, String competitorIdAsString, + String displayName) { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + getService().apply( + new UpdateCompetitorDisplayNameInLeaderboard(leaderboardName, competitorIdAsString, displayName)); + } + + @Override + public void moveLeaderboardColumnUp(String leaderboardName, String columnName) { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + getService().apply(new MoveLeaderboardColumnUp(leaderboardName, columnName)); + } + + @Override + public void moveLeaderboardColumnDown(String leaderboardName, String columnName) { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + getService().apply(new MoveLeaderboardColumnDown(leaderboardName, columnName)); + } + + @Override + public void updateIsMedalRace(String leaderboardName, String columnName, boolean isMedalRace) { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(leaderboardName))); + getService().apply(new UpdateIsMedalRace(leaderboardName, columnName, isMedalRace)); + } + + @Override + public void updateRacesDelayToLive(List regattaAndRaceIdentifiers, long delayToLiveInMs) { + for (RegattaAndRaceIdentifier regattaAndRaceIdentifier : regattaAndRaceIdentifiers) { + getSecurityService().checkCurrentUserUpdatePermission(regattaAndRaceIdentifier); + getService().apply(new UpdateRaceDelayToLive(regattaAndRaceIdentifier, delayToLiveInMs)); + } + } + + @Override + public void createSwissTimingConfiguration(String configName, String jsonURL, String hostname, Integer port, + String updateURL, String updateUsername, String updatePassword) throws Exception { + if (!jsonURL.equalsIgnoreCase("test")) { + if (existsSwissTimingConfigurationForCurrentUser(jsonURL)) { + throw new RuntimeException("A Configuration for the current user with this json URL already exists."); + } + final String currentUserName = getSecurityService().getCurrentUser().getName(); + final TypeRelativeObjectIdentifier identifier = SwissTimingConfiguration.getTypeRelativeObjectIdentifier(jsonURL, currentUserName); + getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( + SecuredDomainType.SWISS_TIMING_ACCOUNT, + identifier, configName, + () -> swissTimingAdapterPersistence + .createSwissTimingConfiguration( + swissTimingFactory.createSwissTimingConfiguration(configName, + jsonURL, hostname, port, updateURL, updateUsername, updatePassword, + currentUserName))); + } + } + + @Override + public void deleteSwissTimingConfigurations( + final Collection configurations) { + for (SwissTimingConfigurationWithSecurityDTO dto : configurations) { + getSecurityService().checkCurrentUserDeletePermission(dto); + getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(dto, + () -> swissTimingAdapterPersistence.deleteSwissTimingConfiguration(dto.getCreatorName(), + dto.getJsonUrl())); + } + } + + @Override + public void updateSwissTimingConfiguration(SwissTimingConfigurationWithSecurityDTO configuration) + throws Exception { + getSecurityService().checkCurrentUserUpdatePermission(configuration); + swissTimingAdapterPersistence.updateSwissTimingConfiguration(swissTimingFactory.createSwissTimingConfiguration( + configuration.getName(), configuration.getJsonUrl(), configuration.getHostname(), + configuration.getPort(), configuration.getUpdateURL(), configuration.getUpdateUsername(), + configuration.getUpdatePassword(), configuration.getCreatorName())); + } + + @Override + public void trackWithSwissTiming(RegattaIdentifier regattaToAddTo, List rrs, + String hostname, int port, boolean trackWind, final boolean correctWindByDeclination, + boolean useInternalMarkPassingAlgorithm, String updateURL, String updateUsername, String updatePassword, + String eventName, String manage2SailEventUrl) throws InterruptedException, ParseException, Exception { + logger.info( + "tracWithSwissTiming for regatta " + regattaToAddTo + " for race records " + rrs + + " with hostname " + hostname + " and port " + port); + Map cachedRegattaEntriesLists = new HashMap(); + for (SwissTimingRaceRecordDTO rr : rrs) { + BoatClass boatClass = getBaseDomainFactory().getOrCreateBoatClass(rr.boatClass); + String raceDescription = rr.regattaName != null ? rr.regattaName : ""; + raceDescription += rr.seriesName != null ? "/" + rr.seriesName : ""; + raceDescription += raceDescription.length() > 0 ? "/" + rr.getName() : rr.getName(); + // try to find a cached entry list for the regatta + RegattaResults regattaResults = cachedRegattaEntriesLists.get(rr.xrrEntriesUrl); + if (regattaResults == null && rr.xrrEntriesUrl != null) { + regattaResults = getSwissTimingAdapter().readRegattaEntryListFromXrrUrl(rr.xrrEntriesUrl); + if (regattaResults != null) { + cachedRegattaEntriesLists.put(rr.xrrEntriesUrl, regattaResults); + } + } + StartList startList = null; + if (regattaResults != null) { + startList = getSwissTimingAdapter().readStartListForRace(rr.raceId, regattaResults); + } + // now read the entry list for the race from the result + getSwissTimingAdapter().addSwissTimingRace(getService(), regattaToAddTo, + rr.raceId, rr.getName(), raceDescription, boatClass, hostname, port, startList, + getRaceLogStore(), getRegattaLogStore(), + RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS, useInternalMarkPassingAlgorithm, trackWind, + correctWindByDeclination, updateURL, updateUsername, updatePassword, eventName, manage2SailEventUrl); + } + } + + @Override + public LeaderboardGroupDTO createLeaderboardGroup(String groupName, String description, String displayName, + boolean displayGroupsInReverseOrder, int[] overallLeaderboardDiscardThresholds, + ScoringSchemeType overallLeaderboardScoringSchemeType) { + List leaderBoards = new ArrayList<>(); + + return doCreateLeaderboardGroup(groupName, description, displayName, displayGroupsInReverseOrder, + overallLeaderboardDiscardThresholds, overallLeaderboardScoringSchemeType, leaderBoards); + } + + private LeaderboardGroupDTO doCreateLeaderboardGroup(String groupName, String description, String displayName, + boolean displayGroupsInReverseOrder, int[] overallLeaderboardDiscardThresholds, + ScoringSchemeType overallLeaderboardScoringSchemeType, List leaderBoards) { + UUID newLeaderboardGroupId = UUID.randomUUID(); + return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( + SecuredDomainType.LEADERBOARD_GROUP, + LeaderboardGroupImpl.getTypeRelativeObjectIdentifier(newLeaderboardGroupId), displayName, + new Callable() { + @Override + public LeaderboardGroupDTO call() throws Exception { + CreateLeaderboardGroup createLeaderboardGroupOp = new CreateLeaderboardGroup( + newLeaderboardGroupId, groupName, description, displayName, displayGroupsInReverseOrder, + leaderBoards, overallLeaderboardDiscardThresholds, overallLeaderboardScoringSchemeType); + return convertToLeaderboardGroupDTO(getService().apply(createLeaderboardGroupOp), false, false); + } + }); + } + + @Override + public void updateLeaderboardGroup(UUID leaderboardGroupId, String oldName, String newName, String newDescription, + String newDisplayName, List leaderboardNames, int[] overallLeaderboardDiscardThresholds, + ScoringSchemeType overallLeaderboardScoringSchemeType) { + SecurityUtils.getSubject() + .checkPermission(SecuredDomainType.LEADERBOARD_GROUP.getStringPermissionForTypeRelativeIdentifier( + DefaultActions.UPDATE, + LeaderboardGroupImpl.getTypeRelativeObjectIdentifier(leaderboardGroupId))); + getService().apply(new UpdateLeaderboardGroup(oldName, newName, newDescription, newDisplayName, + leaderboardNames, overallLeaderboardDiscardThresholds, overallLeaderboardScoringSchemeType)); + } + + protected void createAndAddLeaderboardGroup(final EventDTO newEvent, List leaderboardNames) + throws MalformedURLException { + LeaderboardGroupDTO leaderboardGroupDTO = null; + String description = ""; + if (newEvent.getDescription() != null) { + description = newEvent.getDescription(); + } + String eventName = newEvent.getName(); + List eventLeaderboardGroupUUIDs = new ArrayList<>(); + // create Leaderboard Group + LeaderboardGroup leaderboardGroup = getService().getLeaderboardGroupByName(eventName); + if (leaderboardGroup == null) { + leaderboardGroupDTO = doCreateLeaderboardGroup(eventName, description, eventName, false, null, null, + leaderboardNames); + eventLeaderboardGroupUUIDs.add(leaderboardGroupDTO.getId()); + } else { + updateLeaderboardGroup(leaderboardGroup.getId(), eventName, eventName, newEvent.getDescription(), eventName, + leaderboardNames, null, null); + leaderboardGroupDTO = getLeaderboardGroupByName(eventName, false); + } + for (LeaderboardGroupDTO lg : newEvent.getLeaderboardGroups()) { + eventLeaderboardGroupUUIDs.add(lg.getId()); + } + updateEvent(newEvent.id, newEvent.getName(), description, newEvent.startDate, newEvent.endDate, newEvent.venue, + newEvent.isPublic, eventLeaderboardGroupUUIDs, newEvent.getOfficialWebsiteURL(), newEvent.getBaseURL(), + newEvent.getSailorsInfoWebsiteURLs(), newEvent.getImages(), newEvent.getVideos(), + newEvent.getWindFinderReviewedSpotsCollectionIds()); + } + + @Override + public EventDTO updateEvent(UUID eventId, String eventName, String eventDescription, Date startDate, Date endDate, + VenueDTO venue, boolean isPublic, List leaderboardGroupIds, String officialWebsiteURLString, + String baseURLAsString, Map sailorsInfoWebsiteURLsByLocaleName, List images, + List videos, List windFinderReviewedSpotCollectionIds) + throws MalformedURLException, UnauthorizedException { + if (SecurityUtils.getSubject().isPermitted(SecuredDomainType.EVENT.getStringPermissionForTypeRelativeIdentifier( + DefaultActions.UPDATE, EventBaseImpl.getTypeRelativeObjectIdentifier(eventId)))) { + TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null; + TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; + URL officialWebsiteURL = officialWebsiteURLString != null ? new URL(officialWebsiteURLString) : null; + URL baseURL = baseURLAsString != null ? new URL(baseURLAsString) : null; + Map sailorsInfoWebsiteURLs = convertToLocalesAndUrls(sailorsInfoWebsiteURLsByLocaleName); + List eventImages = convertToImages(images); + List eventVideos = convertToVideos(videos); + getService().apply(new UpdateEvent(eventId, eventName, eventDescription, startTimePoint, endTimePoint, + venue.getName(), isPublic, leaderboardGroupIds, officialWebsiteURL, baseURL, sailorsInfoWebsiteURLs, + eventImages, eventVideos, windFinderReviewedSpotCollectionIds)); + return getEventById(eventId, false); + } + throw new UnauthorizedException("You are not permitted to edit event " + eventId); + } + + @Override + public EventDTO createEvent(String eventName, String eventDescription, Date startDate, Date endDate, String venue, + boolean isPublic, List courseAreaNames, String officialWebsiteURLAsString, String baseURLAsString, + Map sailorsInfoWebsiteURLsByLocaleName, List images, + List videos, List leaderboardGroupIds) + throws UnauthorizedException { + final UUID eventUuid = UUID.randomUUID(); + + return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( + SecuredDomainType.EVENT, EventBaseImpl.getTypeRelativeObjectIdentifier(eventUuid), eventName, + new Callable() { + @Override + public EventDTO call() throws Exception { + TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null; + TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; + URL officialWebsiteURL = officialWebsiteURLAsString != null + ? new URL(officialWebsiteURLAsString) + : null; + URL baseURL = baseURLAsString != null ? new URL(baseURLAsString) : null; + Map sailorsInfoWebsiteURLs = convertToLocalesAndUrls( + sailorsInfoWebsiteURLsByLocaleName); + List eventImages = convertToImages(images); + List eventVideos = convertToVideos(videos); + getService().apply(new CreateEvent(eventName, eventDescription, startTimePoint, endTimePoint, + venue, isPublic, eventUuid, officialWebsiteURL, baseURL, sailorsInfoWebsiteURLs, + eventImages, eventVideos, leaderboardGroupIds)); + createCourseAreas(eventUuid, courseAreaNames.toArray(new String[courseAreaNames.size()])); + return getEventById(eventUuid, false); + } + }); + } + + @Override + public void createCourseAreas(UUID eventId, String[] courseAreaNames) { + getSecurityService().checkCurrentUserUpdatePermission(getService().getEvent(eventId)); + final UUID[] courseAreaIDs = new UUID[courseAreaNames.length]; + for (int i = 0; i < courseAreaNames.length; i++) { + courseAreaIDs[i] = UUID.randomUUID(); + } + getService().apply(new AddCourseAreas(eventId, courseAreaNames, courseAreaIDs)); + } + + @Override + public void removeCourseAreas(UUID eventId, UUID[] courseAreaIds) { + getSecurityService().checkCurrentUserDeletePermission(getService().getEvent(eventId)); + getService().apply(new RemoveCourseAreas(eventId, courseAreaIds)); + } + + @Override + public void removeEvents(Collection eventIds) throws UnauthorizedException { + for (UUID eventId : eventIds) { + removeEvent(eventId); + } + } + + @Override + public void removeEvent(UUID eventId) throws UnauthorizedException { + Event event = getService().getEvent(eventId); + if (event != null) { + getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(event, new Action() { + @Override + public void run() throws Exception { + getService().apply(new RemoveEvent(eventId)); + } + }); + } + } + + @Override + public void renameEvent(UUID eventId, String newName) throws UnauthorizedException { + if (SecurityUtils.getSubject().isPermitted(SecuredDomainType.EVENT.getStringPermissionForTypeRelativeIdentifier( + DefaultActions.UPDATE, EventBaseImpl.getTypeRelativeObjectIdentifier(eventId)))) { + getService().apply(new RenameEvent(eventId, newName)); + } else { + throw new UnauthorizedException("You are not permitted to edit event " + eventId); + } + } + + @Override + public void removeRegattas(Collection selectedRegattas) { + for (RegattaIdentifier regatta : selectedRegattas) { + removeRegatta(regatta); + } + } + + @Override + public void removeRegatta(RegattaIdentifier regattaIdentifier) { + Regatta regatta = getService().getRegatta(regattaIdentifier); + if (regatta != null) { + Set objectsThatWillBeImplicitlyCleanedByRemoveRegatta = new HashSet<>(); + objectsThatWillBeImplicitlyCleanedByRemoveRegatta.add(regatta.getIdentifier()); + for (RaceDefinition race : regatta.getAllRaces()) { + TypeRelativeObjectIdentifier typeRelativeObjectIdentifier = RegattaNameAndRaceName + .getTypeRelativeObjectIdentifier(regatta.getName(), race.getName()); + QualifiedObjectIdentifier identifier = SecuredDomainType.TRACKED_RACE + .getQualifiedObjectIdentifier(typeRelativeObjectIdentifier); + objectsThatWillBeImplicitlyCleanedByRemoveRegatta.add(identifier); + } + for (Leaderboard leaderboard : getService().getLeaderboards().values()) { + if (leaderboard instanceof RegattaLeaderboard) { + RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; + if (regattaLeaderboard.getRegatta() == regatta) { + objectsThatWillBeImplicitlyCleanedByRemoveRegatta.add(regattaLeaderboard.getIdentifier()); + } + } + } + // check if we can delete everything RemoveRegatta will remove + for (QualifiedObjectIdentifier toRemovePermissionObjects : objectsThatWillBeImplicitlyCleanedByRemoveRegatta) { + getSecurityService().checkCurrentUserDeletePermission(toRemovePermissionObjects); + } + // we have all permissions, execute + getService().apply(new RemoveRegatta(regattaIdentifier)); + // cleanup the Ownership and ACLs + for (QualifiedObjectIdentifier toRemovePermissionObjects : objectsThatWillBeImplicitlyCleanedByRemoveRegatta) { + getSecurityService().deleteAllDataForRemovedObject(toRemovePermissionObjects); + } + } + } + + @Override + public void removeSeries(RegattaIdentifier identifier, String seriesName) { + Regatta regatta = getService().getRegatta(identifier); + if (regatta != null) { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.REGATTA.getStringPermissionForObject(DefaultActions.UPDATE, regatta)); + } + getService().apply(new RemoveSeries(identifier, seriesName)); + } + + @Override + public void updateRegatta(RegattaIdentifier regattaName, Date startDate, Date endDate, List courseAreaUuids, + RegattaConfigurationDTO configurationDTO, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, boolean controlTrackingFromStartAndFinishTimes, + boolean autoRestartTrackingUponCompetitorSetChange, String registrationLinkSecret, CompetitorRegistrationType registrationType) { + Regatta regatta = getService().getRegatta(regattaName); + if (regatta != null) { + SecurityUtils.getSubject().checkPermission(SecuredDomainType.REGATTA.getStringPermissionForObject(DefaultActions.UPDATE, regatta)); + } + TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null; + TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; + getService().apply(new UpdateSpecificRegatta(regattaName, startTimePoint, endTimePoint, courseAreaUuids, + convertToRegattaConfiguration(configurationDTO), buoyZoneRadiusInHullLengths, useStartTimeInference, + controlTrackingFromStartAndFinishTimes, autoRestartTrackingUponCompetitorSetChange, registrationLinkSecret, registrationType)); + } + + @Override + public List addRaceColumnsToSeries(RegattaIdentifier regattaIdentifier, String seriesName, + List> columnNamesWithInsertIndex) { + Regatta regatta = getService().getRegatta(regattaIdentifier); + if (regatta != null) { + SecurityUtils.getSubject().checkPermission(SecuredDomainType.REGATTA.getStringPermissionForObject(DefaultActions.UPDATE, regatta)); + } + List result = new ArrayList(); + for (Pair columnNameAndInsertIndex : columnNamesWithInsertIndex) { + RaceColumnInSeries raceColumnInSeries = getService().apply( + new AddColumnToSeries(columnNameAndInsertIndex.getB(), regattaIdentifier, seriesName, columnNameAndInsertIndex.getA())); + if (raceColumnInSeries != null) { + result.add(convertToRaceColumnInSeriesDTO(raceColumnInSeries)); + } + } + return result; + } + + @Override + public void updateSeries(RegattaIdentifier regattaIdentifier, String seriesName, String newSeriesName, boolean isMedal, boolean isFleetsCanRunInParallel, + int[] resultDiscardingThresholds, boolean startsWithZeroScore, + boolean firstColumnIsNonDiscardableCarryForward, boolean hasSplitFleetContiguousScoring, + Integer maximumNumberOfDiscards, List fleets) { + Regatta regatta = getService().getRegatta(regattaIdentifier); + if (regatta != null) { + SecurityUtils.getSubject().checkPermission(SecuredDomainType.REGATTA.getStringPermissionForObject(DefaultActions.UPDATE, regatta)); + } + getService().apply( + new UpdateSeries(regattaIdentifier, seriesName, newSeriesName, isMedal, isFleetsCanRunInParallel, resultDiscardingThresholds, + startsWithZeroScore, firstColumnIsNonDiscardableCarryForward, hasSplitFleetContiguousScoring, + maximumNumberOfDiscards, fleets)); + } + + @Override + public void removeRaceColumnsFromSeries(RegattaIdentifier regattaIdentifier, String seriesName, List columnNames) { + Regatta regatta = getService().getRegatta(regattaIdentifier); + if (regatta != null) { + SecurityUtils.getSubject().checkPermission(SecuredDomainType.REGATTA.getStringPermissionForObject(DefaultActions.UPDATE, regatta)); + } + for(String columnName: columnNames) { + getService().apply(new RemoveColumnFromSeries(regattaIdentifier, seriesName, columnName)); + } + } + + @Override + public RegattaDTO createRegatta(String regattaName, String boatClassName, + boolean canBoatsOfCompetitorsChangePerRace, CompetitorRegistrationType competitorRegistrationType, String registrationLinkSecret, + Date startDate, Date endDate, + RegattaCreationParametersDTO seriesNamesWithFleetNamesAndFleetOrderingAndMedal, + boolean persistent, ScoringSchemeType scoringSchemeType, List courseAreaIds, Double buoyZoneRadiusInHullLengths, boolean useStartTimeInference, + boolean controlTrackingFromStartAndFinishTimes, boolean autoRestartTrackingUponCompetitorSetChange, RankingMetrics rankingMetricType) { + return getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( + SecuredDomainType.REGATTA, Regatta.getTypeRelativeObjectIdentifier(regattaName), + regattaName, new Callable() { + @Override + public RegattaDTO call() throws Exception { + TimePoint startTimePoint = startDate != null ? new MillisecondsTimePoint(startDate) : null; + TimePoint endTimePoint = endDate != null ? new MillisecondsTimePoint(endDate) : null; + Regatta regatta = getService().apply(new AddSpecificRegatta(regattaName, boatClassName, + canBoatsOfCompetitorsChangePerRace, competitorRegistrationType, registrationLinkSecret, + startTimePoint, endTimePoint, UUID.randomUUID(), + seriesNamesWithFleetNamesAndFleetOrderingAndMedal, persistent, + baseDomainFactory.createScoringScheme(scoringSchemeType), courseAreaIds, + buoyZoneRadiusInHullLengths, useStartTimeInference, + controlTrackingFromStartAndFinishTimes, autoRestartTrackingUponCompetitorSetChange, rankingMetricType)); + return convertToRegattaDTO(regatta); + } + }); + } + + private void createRegattaFromRegattaDTO(RegattaDTO regatta) { + this.createRegatta(regatta.getName(), regatta.boatClass.getName(), regatta.canBoatsOfCompetitorsChangePerRace, + regatta.competitorRegistrationType, regatta.registrationLinkSecret, regatta.startDate, regatta.endDate, + new RegattaCreationParametersDTO(getSeriesCreationParameters(regatta)), true, regatta.scoringScheme, + Util.mapToArrayList(regatta.courseAreas, CourseAreaDTO::getId), regatta.buoyZoneRadiusInHullLengths, + regatta.useStartTimeInference, regatta.controlTrackingFromStartAndFinishTimes, + regatta.autoRestartTrackingUponCompetitorSetChange, regatta.rankingMetricType); + } + + /** + * Uses {@link #addRaceColumnsToSeries} which also handles replication to update the regatta identified by + * regatta's {@link RegattaDTO#getRegattaIdentifier() identifier} with the race columns as specified by + * regatta. The domain regatta object is assumed to have no races associated when this method is + * called. + */ + protected void addRaceColumnsToRegattaSeries(RegattaDTO regatta) { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.REGATTA.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Regatta.getTypeRelativeObjectIdentifier(regatta.getName()))); + for (SeriesDTO series : regatta.series) { + List> raceNamesAndInsertIndex = new ArrayList<>(); + int insertIndex = 0; + for (RaceColumnDTO raceColumnInSeries : series.getRaceColumns()) { + raceNamesAndInsertIndex.add(new Pair<>(raceColumnInSeries.getName(), insertIndex)); + insertIndex++; + } + addRaceColumnsToSeries(regatta.getRegattaIdentifier(), series.getName(), raceNamesAndInsertIndex); + } + } + + protected RaceColumnInSeriesDTO convertToRaceColumnInSeriesDTO(RaceColumnInSeries raceColumnInSeries) { + RaceColumnInSeriesDTO raceColumnInSeriesDTO = new RaceColumnInSeriesDTO(raceColumnInSeries.getSeries().getName(), + raceColumnInSeries.getRegatta().getName()); + fillRaceColumnDTO(raceColumnInSeries, raceColumnInSeriesDTO); + return raceColumnInSeriesDTO; + } + + @Override + public UUID importMasterData(final String urlAsString, final String[] groupNames, final boolean override, + final boolean compress, final boolean exportWind, final boolean exportDeviceConfigurations, + String targetServerUsername, String targetServerPassword, + final boolean exportTrackedRacesAndStartTracking) { + final UUID importOperationId = UUID.randomUUID(); + getSecurityService().checkCurrentUserServerPermission(ServerActions.CAN_IMPORT_MASTERDATA); + // // Create a progress indicator for as long as the server gets data from the other server. + // // As soon as the server starts the import operation, a progress object will be built on every server + Runnable masterDataImportTask = new Runnable() { + @Override + public void run() { + getService().importMasterData(urlAsString, groupNames, override, compress, exportWind, + exportDeviceConfigurations, targetServerUsername, targetServerPassword, /* targetServerBeararToken */ null, + exportTrackedRacesAndStartTracking, importOperationId); + } + }; + executor.execute(masterDataImportTask); + return importOperationId; + } + + @Override + public List addOrUpdateCompetitors(List competitors) throws URISyntaxException { + final List result = new ArrayList<>(); + for (final CompetitorDTO competitor : competitors) { + if (competitor.hasBoat()) { + final CompetitorWithBoatDTO competitorWithBoat = addOrUpdateCompetitorWithBoat( + (CompetitorWithBoatDTO) competitor); + SecurityDTOUtil.addSecurityInformation(getSecurityService(), competitorWithBoat, + competitorWithBoat.getIdentifier()); + result.add(competitorWithBoat); + } else { + final CompetitorDTO competitorWithoutBoat = addOrUpdateCompetitorWithoutBoat(competitor); + SecurityDTOUtil.addSecurityInformation(getSecurityService(), competitorWithoutBoat, + competitorWithoutBoat.getIdentifier()); + result.add(competitorWithoutBoat); + } + } + return result; + } + + private CompetitorWithBoat addOrUpdateCompetitorWithBoatInternal(CompetitorWithBoatDTO competitor) + throws URISyntaxException { + final CompetitorWithBoat result; + CompetitorWithBoat existingCompetitor = getService().getCompetitorAndBoatStore() + .getExistingCompetitorWithBoatByIdAsString(competitor.getIdAsString()); + Nationality nationality = (competitor.getThreeLetterIocCountryCode() == null + || competitor.getThreeLetterIocCountryCode().isEmpty()) ? null + : getBaseDomainFactory().getOrCreateNationality(competitor.getThreeLetterIocCountryCode()); + if (competitor.getIdAsString() == null || competitor.getIdAsString().isEmpty() || existingCompetitor == null) { + // new competitor + final UUID competitorUUID = UUID.randomUUID(); + final DynamicPerson sailor = new PersonImpl(competitor.getName(), nationality, null, null); + final DynamicTeam team = new TeamImpl(competitor.getName() + " team", Collections.singleton(sailor), null); + // new boat + final DynamicBoat boat = (DynamicBoat) addOrUpdateBoatInternal(competitor.getBoat()); + result = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( + SecuredDomainType.COMPETITOR, CompetitorImpl.getTypeRelativeObjectIdentifier(competitorUUID), + competitor.getName(), + () -> getBaseDomainFactory().getCompetitorAndBoatStore().getOrCreateCompetitorWithBoat( + competitorUUID, competitor.getName(), competitor.getShortName(), competitor.getColor(), + competitor.getEmail(), + competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), team, + competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(), + competitor.getSearchTag(), boat, /* storePersistently */ true)); + } else { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.COMPETITOR.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + CompetitorImpl.getTypeRelativeObjectIdentifier(competitor.getId()))); + Competitor updatedCompetitor = getService().apply(new UpdateCompetitor(competitor.getIdAsString(), + competitor.getName(), competitor.getShortName(), competitor.getColor(), competitor.getEmail(), + nationality, competitor.getImageURL() == null ? null : new URI(competitor.getImageURL()), + competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), + competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(), + competitor.getSearchTag())); + DynamicBoat updatedBoat = (DynamicBoat) addOrUpdateBoatInternal(competitor.getBoat()); + result = new CompetitorWithBoatImpl(updatedCompetitor, updatedBoat); + } + return result; + } + + private Competitor addOrUpdateCompetitorWithoutBoatInternal(CompetitorDTO competitor) throws URISyntaxException { + final Competitor result; + Competitor existingCompetitor = getService().getCompetitorAndBoatStore() + .getExistingCompetitorByIdAsString(competitor.getIdAsString()); + Nationality nationality = (competitor.getThreeLetterIocCountryCode() == null + || competitor.getThreeLetterIocCountryCode().isEmpty()) ? null + : getBaseDomainFactory().getOrCreateNationality(competitor.getThreeLetterIocCountryCode()); + if (competitor.getIdAsString() == null || competitor.getIdAsString().isEmpty() || existingCompetitor == null) { + // new competitor + UUID competitorUUID = UUID.randomUUID(); + DynamicPerson sailor = new PersonImpl(competitor.getName(), nationality, null, null); + DynamicTeam team = new TeamImpl(competitor.getName() + " team", Collections.singleton(sailor), null); + result = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( + SecuredDomainType.COMPETITOR, CompetitorImpl.getTypeRelativeObjectIdentifier(competitorUUID), + competitor.getName(), + () -> getBaseDomainFactory().getOrCreateCompetitor(competitorUUID, competitor.getName(), + competitor.getShortName(), competitor.getColor(), competitor.getEmail(), + competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), team, + competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(), + competitor.getSearchTag(), /* storePersistently */ true)); + } else { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.COMPETITOR.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + CompetitorImpl.getTypeRelativeObjectIdentifier(competitor.getId()))); + result = getService().apply(new UpdateCompetitor(competitor.getIdAsString(), competitor.getName(), + competitor.getShortName(), competitor.getColor(), competitor.getEmail(), nationality, + competitor.getImageURL() == null ? null : new URI(competitor.getImageURL()), + competitor.getFlagImageURL() == null ? null : new URI(competitor.getFlagImageURL()), + competitor.getTimeOnTimeFactor(), competitor.getTimeOnDistanceAllowancePerNauticalMile(), + competitor.getSearchTag())); + } + return result; + } + + @Override + public CompetitorDTO addOrUpdateCompetitorWithoutBoat(CompetitorDTO competitorDTO) throws URISyntaxException { + Competitor competitor = addOrUpdateCompetitorWithoutBoatInternal(competitorDTO); + return convertToCompetitorDTO(competitor); + } + + @Override + public CompetitorWithBoatDTO addOrUpdateCompetitorWithBoat(CompetitorWithBoatDTO competitorDTO) + throws URISyntaxException { + CompetitorWithBoat competitor = addOrUpdateCompetitorWithBoatInternal(competitorDTO); + return convertToCompetitorWithBoatDTO(competitor); + } + + @Override + public List addCompetitors(List competitorDescriptors, + String searchTag) throws URISyntaxException { + List competitorsForSaving = new ArrayList<>(); + for (final CompetitorDescriptor competitorDescriptor : competitorDescriptors) { + final Action action = () -> competitorsForSaving + .add(getService().convertCompetitorDescriptorToCompetitorWithBoat(competitorDescriptor, searchTag)); + final Boat existingBoat = getService().getCompetitorAndBoatStore() + .getExistingBoatById(competitorDescriptor.getBoatUUID()); + final Action actionIncludingBoatSecurityCheck; + if (existingBoat == null) { + actionIncludingBoatSecurityCheck = () -> getSecurityService() + .setOwnershipCheckPermissionForObjectCreationAndRevertOnError(SecuredDomainType.BOAT, + BoatImpl.getTypeRelativeObjectIdentifier(competitorDescriptor.getBoatUUID()), + competitorDescriptor.getBoatName(), action); + } else { + actionIncludingBoatSecurityCheck = action; + } + final Competitor existingCompetitor = getService().getCompetitorAndBoatStore() + .getExistingCompetitorById(competitorDescriptor.getCompetitorUUID()); + final Action actionIncludingCompetitorAndBoatSecurityCheck; + if (existingCompetitor == null) { + actionIncludingCompetitorAndBoatSecurityCheck = () -> getSecurityService() + .setOwnershipCheckPermissionForObjectCreationAndRevertOnError(SecuredDomainType.COMPETITOR, + CompetitorImpl + .getTypeRelativeObjectIdentifier(competitorDescriptor.getCompetitorUUID()), + competitorDescriptor.getName(), actionIncludingBoatSecurityCheck); + } else { + actionIncludingCompetitorAndBoatSecurityCheck = actionIncludingBoatSecurityCheck; + } + try { + actionIncludingCompetitorAndBoatSecurityCheck.run(); + } catch (Exception e) { + throw new RuntimeException(e); // this can onlyhave been a RuntimeException in the first place because + // nothing of the above throws a checked one + } + } + getBaseDomainFactory().getCompetitorAndBoatStore().addNewCompetitorsWithBoat(competitorsForSaving); + return convertToCompetitorWithBoatDTOs(competitorsForSaving); + } + + @Override + public void allowCompetitorResetToDefaults(List competitors) { + List competitorIdsAsStrings = new ArrayList(); + for (CompetitorDTO competitor : competitors) { + getSecurityService().checkCurrentUserUpdatePermission(competitor); + competitorIdsAsStrings.add(competitor.getIdAsString()); + } + getService().apply(new AllowCompetitorResetToDefaults(competitorIdsAsStrings)); + } + + @Override + public BoatDTO addOrUpdateBoat(BoatDTO boat) { + return convertToBoatDTO(addOrUpdateBoatInternal(boat)); + } + + private Boat addOrUpdateBoatInternal(BoatDTO boat) { + Boat existingBoat = getService().getCompetitorAndBoatStore().getExistingBoatByIdAsString(boat.getIdAsString()); + final Boat result; + if (boat.getIdAsString() == null || boat.getIdAsString().isEmpty() || existingBoat == null) { + // new boat + UUID boatUUID = UUID.randomUUID(); + BoatClass boatClass = getBaseDomainFactory().getOrCreateBoatClass(boat.getBoatClass().getName()); + result = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( + SecuredDomainType.BOAT, BoatImpl.getTypeRelativeObjectIdentifier(boatUUID), boat.getName(), + () -> getBaseDomainFactory().getOrCreateBoat(boatUUID, boat.getName(), boatClass, boat.getSailId(), boat.getColor(), /* storePersistently */ true)); + } else { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.BOAT.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + BoatImpl.getTypeRelativeObjectIdentifier(boat.getId()))); + result = getService() + .apply(new UpdateBoat(boat.getIdAsString(), boat.getName(), boat.getColor(), boat.getSailId())); + } + return result; + } + + @Override + public void allowBoatResetToDefaults(List boats) { + List boatIdsAsStrings = new ArrayList(); + for (BoatDTO boat : boats) { + getSecurityService().checkCurrentUserUpdatePermission(boat); + boatIdsAsStrings.add(boat.getIdAsString()); + } + getService().apply(new AllowBoatResetToDefaults(boatIdsAsStrings)); + } + + @Override + public DataImportProgress getImportOperationProgress(UUID id) { + return getService().getDataImportLock().getProgress(id); + } + + @Override + public boolean removeDeviceConfiguration(UUID deviceConfigurationId) { + final DeviceConfiguration configuration = getService().getDeviceConfigurationById(deviceConfigurationId); + getSecurityService().checkCurrentUserDeletePermission(configuration); + getService().removeDeviceConfiguration(deviceConfigurationId); + return true; + } + + @Override + public void setTrackingTimes(RaceLogSetTrackingTimesDTO dto) throws NotFoundException { + getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(dto.leaderboardName)); + RaceLog raceLog = getRaceLog(dto.leaderboardName, dto.raceColumnName, dto.fleetName); + // the tracking start/end time events are not revoked; updates with null as TimePoint may be added instead + final LogEventAuthorImpl author = new LogEventAuthorImpl(dto.authorName, dto.authorPriority); + if (!Util.equalsWithNull(dto.newStartOfTracking, dto.currentStartOfTracking)) { + if (dto.newStartOfTracking != null) { + raceLog.add(new RaceLogStartOfTrackingEventImpl(dto.newStartOfTracking.getTimePoint(), author, + raceLog.getCurrentPassId())); + } else { + final Pair trackingTimesEvents = new TrackingTimesEventFinder( + raceLog).analyze(); + // we assume to find a valid "set start of tracking time" event that matches the old start of tracking + // time; + // if the time doesn't match dto.currentStartOfTracking, the revocation is rejected with an exception; + // the result of trying to revoke is returned otherwise, and it may not be the result intended in case + // the author's priority was lower than that of the author of the event that is to be revoked. + if (trackingTimesEvents == null || trackingTimesEvents.getA() == null || !Util.equalsWithNull( + trackingTimesEvents.getA().getLogicalTimePoint(), + dto.currentStartOfTracking == null ? null : dto.currentStartOfTracking.getTimePoint())) { + throw new NotFoundException("Old start of tracking time in the race log (" + + (trackingTimesEvents == null || trackingTimesEvents.getA() == null ? "unset" + : trackingTimesEvents.getA().getLogicalTimePoint()) + + ") does not match start of tracking time at transaction start (" + + dto.currentStartOfTracking == null ? null + : dto.currentStartOfTracking.getTimePoint() + ")"); + } else { + try { + raceLog.revokeEvent(author, trackingTimesEvents.getA(), "resetting tracking start time"); + } catch (NotRevokableException e) { + logger.log(Level.WARNING, + "Internal error: event " + trackingTimesEvents.getA() + " was expected to be revokable", + e); + } + } + } + } + if (!Util.equalsWithNull(dto.newEndOfTracking, dto.currentEndOfTracking)) { + if (dto.newEndOfTracking != null) { + raceLog.add(new RaceLogEndOfTrackingEventImpl(dto.newEndOfTracking.getTimePoint(), author, + raceLog.getCurrentPassId())); + } else { + final Pair trackingTimesEvents = new TrackingTimesEventFinder( + raceLog).analyze(); + // we assume to find a valid "set start of tracking time" event that matches the old start of tracking + // time; + // if the time doesn't match dto.currentStartOfTracking, the revocation is rejected with an exception; + // the result of trying to revoke is returned otherwise, and it may not be the result intended in case + // the author's priority was lower than that of the author of the event that is to be revoked. + if (trackingTimesEvents == null || trackingTimesEvents.getB() == null + || !Util.equalsWithNull(trackingTimesEvents.getB().getLogicalTimePoint(), + dto.currentEndOfTracking == null ? null : dto.currentEndOfTracking.getTimePoint())) { + throw new NotFoundException("Old end of tracking time in the race log (" + + (trackingTimesEvents == null || trackingTimesEvents.getB() == null ? "unset" + : trackingTimesEvents.getB().getLogicalTimePoint()) + + ") does not match end of tracking time at transaction start (" + + dto.currentEndOfTracking == null ? null : dto.currentEndOfTracking.getTimePoint() + ")"); + } else { + try { + raceLog.revokeEvent(author, trackingTimesEvents.getB(), "resetting tracking end time"); + } catch (NotRevokableException e) { + logger.log(Level.WARNING, + "Internal error: event " + trackingTimesEvents.getB() + " was expected to be revokable", + e); + } + } + } + } + } + + @Override + public boolean authorizeAccessToIgtimiUser(String eMailAddress, String password) throws Exception { + final Account existingAccount = getIgtimiConnectionFactory().getExistingAccountByEmail(eMailAddress); + final Account account; + if (existingAccount == null) { + final String creatorName = getSecurityService().getCurrentUser().getName(); + account = getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( + SecuredDomainType.IGTIMI_ACCOUNT, + Account.getTypeRelativeObjectIdentifier(eMailAddress, creatorName), eMailAddress, + () -> getIgtimiConnectionFactory().createAccountToAccessUserData(creatorName, eMailAddress, + password)); + } else { + logger.warning("Igtimi account " + eMailAddress + " already exists."); + account = null; // account with that e-mail already exists + } + return account != null; + } + + @Override + public void removeIgtimiAccount(String eMailOfAccountToRemove) { + final Account existingAccount = getIgtimiConnectionFactory().getExistingAccountByEmail(eMailOfAccountToRemove); + if (existingAccount != null) { + getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(existingAccount, () -> { + getIgtimiConnectionFactory().removeAccount(existingAccount); + }); + } + } + + @Override + public Map importWindFromIgtimi(List selectedRaces, + boolean correctByDeclination) + throws IllegalStateException, ClientProtocolException, IOException, org.json.simple.parser.ParseException { + final IgtimiConnectionFactory igtimiConnectionFactory = getIgtimiConnectionFactory(); + final List trackedRaces = new ArrayList<>(); + if (selectedRaces != null && !selectedRaces.isEmpty()) { + for (RaceDTO raceDTO : selectedRaces) { + DynamicTrackedRace trackedRace = getTrackedRace(raceDTO.getRaceIdentifier()); + // In case the user selected a distinct set of races, we want the call to completely fail if + // tracking wind isn't allowed for at least one race + getSecurityService().checkCurrentUserUpdatePermission(trackedRace); + trackedRaces.add(trackedRace); + } + } else { + for (DynamicTrackedRace race : getAllTrackedRaces()) { + // In case the user likes to track wind for all races, we silently filter for the ones + // for which the user has sufficient permissions + if (getSecurityService().hasCurrentUserUpdatePermission(race)) { + trackedRaces.add(race); + } + } + } + Map numberOfWindFixesImportedPerRace = new HashMap(); + for (Account account : igtimiConnectionFactory.getAllAccounts()) { + // filter account based on used permissions to read account: + if (getSecurityService().hasCurrentUserReadPermission(account)) { + IgtimiConnection conn = igtimiConnectionFactory.connect(account); + Map resultsForAccounts = conn.importWindIntoRace(trackedRaces, + correctByDeclination); + for (Entry resultForAccount : resultsForAccounts.entrySet()) { + RegattaAndRaceIdentifier key = resultForAccount.getKey().getRaceIdentifier(); + Integer i = numberOfWindFixesImportedPerRace.get(key); + if (i == null) { + i = 0; + } + numberOfWindFixesImportedPerRace.put(key, i + resultForAccount.getValue()); + } + } + } + for (final TrackedRace trackedRace : trackedRaces) { + // update polar sheets: + getService().getPolarDataService().insertExistingFixes(trackedRace); + } + return numberOfWindFixesImportedPerRace; + } + + @Override + public Boolean denoteForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName) + throws NotFoundException, NotDenotableForRaceLogTrackingException { + Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + getSecurityService().checkCurrentUserUpdatePermission(leaderboard); + RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); + Fleet fleet = getFleetByName(raceColumn, fleetName); + return getRaceLogTrackingAdapter().denoteRaceForRaceLogTracking(getService(), leaderboard, raceColumn, fleet, + null); + } + + @Override + public void removeDenotationForRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName) + throws NotFoundException { + Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + getSecurityService().checkCurrentUserUpdatePermission(leaderboard); + RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); + getRaceLogTrackingAdapter().removeDenotationForRaceLogTracking(getService(), raceLog); + } + + @Override + public void denoteForRaceLogTracking(String leaderboardName, String prefix) throws Exception { + Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + getSecurityService().checkCurrentUserUpdatePermission(leaderboard); + getRaceLogTrackingAdapter().denoteAllRacesForRaceLogTracking(getService(), leaderboard, prefix); + } + + @Override + public void setCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName, + Map competitorAndBoatDTOs) + throws CompetitorRegistrationOnRaceLogDisabledException, NotFoundException { + getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); + RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); + Fleet fleet = getFleetByName(raceColumn, fleetName); + + Map competitorToBoatMappingsToRegister = new HashMap<>(); + for (Entry competitorAndBoatEntry : competitorAndBoatDTOs.entrySet()) { + competitorToBoatMappingsToRegister.put(getCompetitor(competitorAndBoatEntry.getKey()), + getBoat(competitorAndBoatEntry.getValue())); + } + + final Iterable competitorRegistrationsToRemove = filterCompetitorDuplicates( + competitorToBoatMappingsToRegister, raceColumn.getCompetitorsRegisteredInRacelog(fleet)); + raceColumn.deregisterCompetitors(competitorRegistrationsToRemove, fleet); + // we assume that the competitors id of type Competitor here, so we need to find the corresponding boat + for (final Entry competitorAndBoatToRegister : competitorToBoatMappingsToRegister + .entrySet()) { + raceColumn.registerCompetitor(competitorAndBoatToRegister.getKey(), competitorAndBoatToRegister.getValue(), + fleet); + } + } + + @Override + public void setCompetitorRegistrationsInRaceLog(String leaderboardName, String raceColumnName, String fleetName, + Set competitorDTOs) + throws CompetitorRegistrationOnRaceLogDisabledException, NotFoundException { + getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); + + RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); + Fleet fleet = getFleetByName(raceColumn, fleetName); + + Map competitorsToRegister = new HashMap<>(); + for (CompetitorWithBoatDTO dto : competitorDTOs) { + competitorsToRegister.put(getCompetitor(dto), getBoat(dto.getBoat())); + } + + Map competitorsRegisteredInRaceLog = new HashMap<>(); + for (final Entry e : raceColumn.getCompetitorsRegisteredInRacelog(fleet).entrySet()) { + competitorsRegisteredInRaceLog.put((CompetitorWithBoat) e.getKey(), e.getValue()); + } + final Iterable competitorSetToRemove = filterCompetitorDuplicates(competitorsToRegister, + competitorsRegisteredInRaceLog); + raceColumn.deregisterCompetitors(competitorSetToRemove, fleet); + // we assume that the competitors id of type Competitor here, so we need to find the corresponding boat + for (CompetitorWithBoat competitorToRegister : competitorsToRegister.keySet()) { + if (competitorToRegister.hasBoat()) { + raceColumn.registerCompetitor(competitorToRegister, fleet); + } else { + logger.warning("The competitor " + competitorToRegister.getName() + + " does not have a boat associated but should have; " + + "competitor is not registered for race log of race " + raceColumnName + " in leaderboard " + + leaderboardName + " for fleet " + fleetName); + } + } + } + + @Override + public void setCompetitorRegistrationsInRegattaLog(String leaderboardName, + Set competitorDTOs) throws DoesNotHaveRegattaLogException, NotFoundException { + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + getSecurityService().checkCurrentUserUpdatePermission(leaderboard); + if (!(leaderboard instanceof HasRegattaLike)) { + throw new DoesNotHaveRegattaLogException(); + } + Map competitorsToRegister = new HashMap<>(); + for (CompetitorDTO dto : competitorDTOs) { + competitorsToRegister.put(getCompetitor(dto), /* boat doesn't matter here */ null); + } + HasRegattaLike hasRegattaLike = (HasRegattaLike) leaderboard; + Map competitorsAlreadyRegistered = new HashMap<>(); + for (final Competitor c : leaderboard.getAllCompetitors()) { + competitorsAlreadyRegistered.put(c, /* boat doesn't matter here */ null); + } + final Iterable competitorSetToRemove = filterCompetitorDuplicates(competitorsToRegister, + competitorsAlreadyRegistered); + hasRegattaLike.deregisterCompetitors(competitorSetToRemove); + hasRegattaLike.registerCompetitors(competitorsToRegister.keySet()); + } + + /** + * Removes competitors already registered to the same boats (those in {@code competitorsRegistered}) from + * {@code competitorsToRegister} to avoid registering them again and then returns those competitors that need to be + * de-registered. Those to de-register includes those registered but to a different boat, and those will be left in + * the {@code competitorToBoatMappingsToRegister} map. + * + * @param competitorToBoatMappingsToRegister + * will be modified by removing all competitors in {@code competitorsRegistered} + * @param competitorToBoatMappingsRegistered + * the competitors already registered; those will be removed from {@code competitorsToRegister} + * @return the competitors to de-register because they were in {@code competitorsRegistered} but are not in + * {@code competitorsToRegister} + */ + private Iterable filterCompetitorDuplicates( + Map competitorToBoatMappingsToRegister, + Map competitorToBoatMappingsRegistered) { + final Set competitorsToUnregister = new HashSet<>(); + Util.addAll(competitorToBoatMappingsRegistered.keySet(), competitorsToUnregister); + for (final Entry e : competitorToBoatMappingsRegistered.entrySet()) { + CompetitorType competitor = e.getKey(); + if (competitorToBoatMappingsToRegister.containsKey(competitor)) { // is competitor to be registered? + final Boat boatOfCompetitorToRegister = competitorToBoatMappingsToRegister.get(competitor); + final Boat boatOfRegisteredCompetitor = e.getValue(); + if (boatOfCompetitorToRegister == boatOfRegisteredCompetitor) { + // User wants to map competitor to boat, and that mapping already exists; neither add nor remove + // this registration but leave as is: + competitorToBoatMappingsToRegister.remove(competitor); + competitorsToUnregister.remove(competitor); + } + } + } + return competitorsToUnregister; + } + + private HashSet filterBoatDuplicates(Set boatsToRegister, HashSet boatSetToRemove) { + for (Iterator iterator = boatSetToRemove.iterator(); iterator.hasNext();) { + Boat boat = iterator.next(); + if (boatsToRegister.remove(boat)) { + iterator.remove(); + } + } + return boatSetToRemove; + } + + @Override + public void setBoatRegistrationsInRegattaLog(String leaderboardName, Set boatDTOs) + throws DoesNotHaveRegattaLogException, NotFoundException { + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + getSecurityService().checkCurrentUserUpdatePermission(leaderboard); + if (!(leaderboard instanceof HasRegattaLike)) { + throw new DoesNotHaveRegattaLogException(); + } + + Set boatsToRegister = new HashSet(); + for (BoatDTO dto : boatDTOs) { + final Boat boat = getBoat(dto); + getSecurityService().checkCurrentUserReadPermission(boat); + boatsToRegister.add(boat); + } + + HasRegattaLike hasRegattaLike = (HasRegattaLike) leaderboard; + Iterable boatsToRemove = leaderboard.getAllBoats(); + HashSet boatSetToRemove = new HashSet<>(); + Util.addAll(boatsToRemove, boatSetToRemove); + filterBoatDuplicates(boatsToRegister, boatSetToRemove); + + hasRegattaLike.deregisterBoats(boatSetToRemove); + hasRegattaLike.registerBoats(boatsToRegister); + } + + @Override + public void fillRaceLogsFromPairingListTemplate(final String leaderboardName, final int flightMultiplier, + final List selectedFlightNames, final PairingListDTO pairingListDTO) + throws NotFoundException, CompetitorRegistrationOnRaceLogDisabledException { + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + getSecurityService().checkCurrentUserUpdatePermission(leaderboard); + int flightCount = 0; + int groupCount = 0; + for (RaceColumn raceColumn : leaderboard.getRaceColumns()) { + if (Util.contains(selectedFlightNames, raceColumn.getName())) { + groupCount = 0; + for (Fleet fleet : raceColumn.getFleets()) { + raceColumn.enableCompetitorRegistrationOnRaceLog(fleet); + Map competitors = new HashMap<>(); + List> competitorsFromPairingList = pairingListDTO.getPairingList() + .get(flightCount).get(groupCount); + for (Pair competitorAndBoatPair : competitorsFromPairingList) { + if (competitorAndBoatPair.getA() != null && competitorAndBoatPair.getA().getName() != null) { + competitors.put(competitorAndBoatPair.getA(), competitorAndBoatPair.getB()); + } + } + this.setCompetitorRegistrationsInRaceLog(leaderboard.getName(), raceColumn.getName(), + fleet.getName(), competitors); + groupCount++; + } + flightCount++; + } else { + for (Fleet fleet : raceColumn.getFleets()) { + this.setCompetitorRegistrationsInRaceLog(leaderboard.getName(), raceColumn.getName(), + fleet.getName(), new HashSet()); + } + } + } + if (leaderboard instanceof LeaderboardThatHasRegattaLike && flightMultiplier > 1) { + final IsRegattaLike regattaLike = ((LeaderboardThatHasRegattaLike) leaderboard).getRegattaLike(); + logger.info("Updating regatta " + regattaLike.getRegattaLikeIdentifier().getName() + + ", setting flag that fleets can run in parallel because a pairing list with flight multiplier " + + flightMultiplier + " has been used."); + regattaLike.setFleetsCanRunInParallelToTrue(); + } + } + + @Override + public void addMarkToRegattaLog(String leaderboardName, MarkDTO markDTO) throws DoesNotHaveRegattaLogException { + getSecurityService().checkCurrentUserUpdatePermission(getService().getLeaderboardByName(leaderboardName)); + Mark mark = convertToMark(markDTO, false); + + RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); + RegattaLogDefineMarkEventImpl event = new RegattaLogDefineMarkEventImpl(MillisecondsTimePoint.now(), + getService().getServerAuthor(), MillisecondsTimePoint.now(), UUID.randomUUID(), mark); + regattaLog.add(event); + } + + @Override + public void revokeMarkDefinitionEventInRegattaLog(String leaderboardName, MarkDTO markDTO) + throws DoesNotHaveRegattaLogException, NotFoundException { + getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); + RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); + final List regattaLogDefineMarkEvents = new AllEventsOfTypeFinder<>(regattaLog, + /* only unrevoked */ true, RegattaLogDefineMarkEvent.class).analyze(); + RegattaLogDefineMarkEvent eventToRevoke = null; + for (RegattaLogEvent event : regattaLogDefineMarkEvents) { + RegattaLogDefineMarkEvent defineMarkEvent = (RegattaLogDefineMarkEvent) event; + if (defineMarkEvent.getMark().getId().toString().equals(markDTO.getIdAsString())) { + eventToRevoke = defineMarkEvent; + break; + } + } + regattaLog.revokeDefineMarkEventAndRelatedDeviceMappings(eventToRevoke, getService().getServerAuthor(), logger); + } + + @Override + public void addCourseDefinitionToRaceLog(String leaderboardName, String raceColumnName, String fleetName, + List> courseDTO, int priority) + throws NotFoundException { + getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); + RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); + String courseName = "Course of " + raceColumnName; + if (!LeaderboardNameConstants.DEFAULT_FLEET_NAME.equals(fleetName)) { + courseName += " - " + fleetName; + } + CourseBase lastPublishedCourse = new LastPublishedCourseDesignFinder(raceLog, + /* onlyCoursesWithValidWaypointList */ false).analyze(); + if (lastPublishedCourse == null) { + lastPublishedCourse = new CourseDataImpl(courseName); + } + + List> controlPoints = new ArrayList<>(); + for (Pair waypointDTO : courseDTO) { + controlPoints.add(new Pair<>(getOrCreateControlPoint(waypointDTO.getA()), waypointDTO.getB())); + } + Course course = new CourseImpl(courseName, lastPublishedCourse.getWaypoints()); + + try { + course.update(controlPoints, lastPublishedCourse.getAssociatedRoles(), + lastPublishedCourse.getOriginatingCourseTemplateIdOrNull(), baseDomainFactory); + } catch (Exception e) { + throw new RuntimeException(e); + } + RaceLogEvent event = new RaceLogCourseDesignChangedEventImpl(MillisecondsTimePoint.now(), + new LogEventAuthorImpl(getService().getServerAuthor().getName(), priority), raceLog.getCurrentPassId(), + course, CourseDesignerMode.ADMIN_CONSOLE); + raceLog.add(event); + } + + @Override + public void pingMark(String leaderboardName, MarkDTO markDTO, TimePoint timePoint, Position positionDTO) + throws DoesNotHaveRegattaLogException, NotFoundException { + getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); + final RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); + final Mark mark = convertToMark(markDTO, true); + final TimePoint time = timePoint == null ? MillisecondsTimePoint.now() : timePoint; + final Position position = positionDTO; + final GPSFix fix = new GPSFixImpl(position, time); + getRaceLogTrackingAdapter().pingMark(regattaLog, mark, fix, getService()); + } + + @Override + public void copyCourseToOtherRaceLogs(com.sap.sse.common.Util.Triple fromTriple, + Set> toTriples, int priority) + throws NotFoundException { + getSecurityService().checkCurrentUserReadPermission(getLeaderboardByName(fromTriple.getA())); + for (com.sap.sse.common.Util.Triple toTriple : toTriples) { + getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(toTriple.getA())); + } + RaceLog fromRaceLog = getRaceLog(fromTriple); + Set toRaceLogs = new HashSet<>(); + for (com.sap.sse.common.Util.Triple toTriple : toTriples) { + toRaceLogs.add(getRaceLog(toTriple)); + } + getRaceLogTrackingAdapter().copyCourse(fromRaceLog, toRaceLogs, baseDomainFactory, getService(), priority); + } + + @Override + public void copyCompetitorsToOtherRaceLogs(com.sap.sse.common.Util.Triple fromTriple, + Set> toTriples) throws NotFoundException { + getSecurityService().checkCurrentUserReadPermission(getLeaderboardByName(fromTriple.getA())); + for (com.sap.sse.common.Util.Triple toTriple : toTriples) { + getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(toTriple.getA())); + } + final RaceColumn raceColumn = getRaceColumn(fromTriple.getA(), fromTriple.getB()); + final Set> toRaces = new HashSet<>(); + for (com.sap.sse.common.Util.Triple toTriple : toTriples) { + final RaceColumn toRaceColumn = getRaceColumn(toTriple.getA(), toTriple.getB()); + final Fleet toFleet = getFleetByName(toRaceColumn, toTriple.getC()); + toRaces.add(new Pair<>(toRaceColumn, toFleet)); + } + getRaceLogTrackingAdapter().copyCompetitors(raceColumn, getFleetByName(raceColumn, fromTriple.getC()), toRaces); + } + + @Override + public void addDeviceMappingToRegattaLog(String leaderboardName, DeviceMappingDTO dto) + throws NoCorrespondingServiceRegisteredException, TransformationException, DoesNotHaveRegattaLogException { + SecurityUtils.getSubject().checkPermission(SecuredDomainType.REGATTA + .getStringPermissionForObject(DefaultActions.UPDATE, getService().getRegattaByName(leaderboardName))); + RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); + DeviceMapping mapping = convertToDeviceMapping(dto); + TimePoint now = MillisecondsTimePoint.now(); + RegattaLogEvent event = null; + TimePoint from = mapping.getTimeRange().hasOpenBeginning() ? null : mapping.getTimeRange().from(); + TimePoint to = mapping.getTimeRange().hasOpenEnd() ? null : mapping.getTimeRange().to(); + if (mapping.getMappedTo() instanceof Mark) { + Mark mark = (Mark) mapping.getMappedTo(); + event = new RegattaLogDeviceMarkMappingEventImpl(now, now, getService().getServerAuthor(), + UUID.randomUUID(), mark, mapping.getDevice(), from, to); + } else if (mapping.getMappedTo() instanceof Competitor) { + Competitor competitor = (Competitor) mapping.getMappedTo(); + if (mapping.getDevice().getIdentifierType().equals(ExpeditionSensorDeviceIdentifier.TYPE)) { + event = new RegattaLogDeviceCompetitorExpeditionExtendedMappingEventImpl(now, now, + getService().getServerAuthor(), UUID.randomUUID(), competitor, mapping.getDevice(), from, to); + } else { + event = new RegattaLogDeviceCompetitorMappingEventImpl(now, now, getService().getServerAuthor(), + UUID.randomUUID(), competitor, mapping.getDevice(), from, to); + } + } else if (mapping.getMappedTo() instanceof Boat) { + final Boat boat = (Boat) mapping.getMappedTo(); + event = new RegattaLogDeviceBoatMappingEventImpl(now, now, getService().getServerAuthor(), + UUID.randomUUID(), boat, mapping.getDevice(), from, to); + } else { + throw new RuntimeException("Can only map devices to competitors, boats or marks"); + } + regattaLog.add(event); + } + + @Override + public void addTypedDeviceMappingToRegattaLog(String leaderboardName, TypedDeviceMappingDTO dto) + throws NoCorrespondingServiceRegisteredException, TransformationException, DoesNotHaveRegattaLogException, + NotFoundException { + getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); + RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); + DeviceMapping mapping = convertToDeviceMapping(dto); + TimePoint now = MillisecondsTimePoint.now(); + RegattaLogEvent event = null; + TimePoint from = mapping.getTimeRange().hasOpenBeginning() ? null : mapping.getTimeRange().from(); + TimePoint to = mapping.getTimeRange().hasOpenEnd() ? null : mapping.getTimeRange().to(); + if (dto.mappedTo instanceof CompetitorWithBoatDTO) { + DoubleVectorFixImporter importer = getRegisteredImporter(DoubleVectorFixImporter.class, dto.dataType); + event = importer.createEvent(now, now, getService().getServerAuthor(), UUID.randomUUID(), + getCompetitor((CompetitorWithBoatDTO) dto.mappedTo), mapping.getDevice(), from, to); + } else if (dto.mappedTo instanceof BoatDTO) { + DoubleVectorFixImporter importer = getRegisteredImporter(DoubleVectorFixImporter.class, dto.dataType); + event = importer.createEvent(now, now, getService().getServerAuthor(), UUID.randomUUID(), + getBoat((BoatDTO) dto.mappedTo), mapping.getDevice(), from, to); + } else { + throw new RuntimeException("Can only map devices to a competitor or boat"); + } + regattaLog.add(event); + } + + private void closeOpenEndedDeviceMapping(RegattaLog regattaLog, DeviceMappingDTO mappingDTO, Date closingTimePoint) + throws TransformationException, UnableToCloseDeviceMappingException { + boolean successfullyClosed = false; + List closingEvents = null; + regattaLog.lockForRead(); + try { + RegattaLogEvent event = regattaLog.getEventById(mappingDTO.originalRaceLogEventIds.get(0)); + if (event != null) { + successfullyClosed = true; + DeviceMapping mapping = convertToDeviceMapping(mappingDTO); + closingEvents = new RegattaLogOpenEndedDeviceMappingCloser(regattaLog, mapping, + getService().getServerAuthor(), new MillisecondsTimePoint(closingTimePoint)).analyze(); + } + } finally { + regattaLog.unlockAfterRead(); + } + // important: read lock must be release before write lock is obtained in add(...); see bug 3774 + if (successfullyClosed) { + for (RegattaLogEvent closingEvent : closingEvents) { + regattaLog.add(closingEvent); + } + } else { + throw new UnableToCloseDeviceMappingException(); + } + } + + @Override + public void revokeRaceAndRegattaLogEvents(String leaderboardName, + List eventIds) throws NotRevokableException, DoesNotHaveRegattaLogException, NotFoundException { + getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); + List> logs = getLogHierarchy(leaderboardName); + revokeEventsFromLogs(logs, eventIds); + } + + private void revokeEventsFromLogs(List> logs, List eventIds) throws NotRevokableException{ + boolean eventRevoked = false; + for (Serializable idToRevoke : eventIds) { + eventRevoked = false; + for (AbstractLog abstractLog : logs) { + eventRevoked = revokeEvent(eventRevoked, idToRevoke, abstractLog); + } + if (!eventRevoked){ + logger.warning("Could not revoke event with id "+idToRevoke); + } + } + } + + private , VisitorT> boolean revokeEvent(boolean eventRevoked, Serializable idToRevoke, AbstractLog abstractLog) + throws NotRevokableException { + final EventT event; + abstractLog.lockForRead(); + try { + event = abstractLog.getEventById(idToRevoke); + } finally { + abstractLog.unlockAfterRead(); + } + if (event != null) { + abstractLog.revokeEvent(getService().getServerAuthor(), event, "revoke triggered by GWT user action"); + eventRevoked = true; + } + return eventRevoked; + } + + private void startRaceLogTracking(String leaderboardName, String raceColumnName, String fleetName, final boolean trackWind, final boolean correctWindByDeclination) + throws NotDenotedForRaceLogTrackingException, Exception { + // no permission checks needed here, since they already exist in PermissionAwareRaceTrackingHandler + Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + Fleet fleet = raceColumn.getFleetByName(fleetName); + getRaceLogTrackingAdapter().startTracking(getService(), leaderboard, raceColumn, fleet, trackWind, correctWindByDeclination, + getService().getPermissionAwareRaceTrackingHandler()); + } + + @Override + public void startRaceLogTracking(List> leaderboardRaceColumnFleetNames, + final boolean trackWind, final boolean correctWindByDeclination) + throws NotDenotedForRaceLogTrackingException, Exception { + for (final Triple leaderboardRaceColumnFleetName : leaderboardRaceColumnFleetNames) { + startRaceLogTracking(leaderboardRaceColumnFleetName.getA(), leaderboardRaceColumnFleetName.getB(), + leaderboardRaceColumnFleetName.getC(), trackWind, correctWindByDeclination); + } + } + + @Override + public RaceDTO setStartTimeReceivedForRace(RaceIdentifier raceIdentifier, Date newStartTimeReceived) { + RegattaNameAndRaceName regattaAndRaceIdentifier = new RegattaNameAndRaceName(raceIdentifier.getRegattaName(), + raceIdentifier.getRaceName()); + DynamicTrackedRace trackedRace = getService().getTrackedRace(regattaAndRaceIdentifier); + getSecurityService().checkCurrentUserUpdatePermission(trackedRace); + trackedRace.setStartTimeReceived( + newStartTimeReceived == null ? null : new MillisecondsTimePoint(newStartTimeReceived)); + return baseDomainFactory.createRaceDTO(getService(), false, regattaAndRaceIdentifier, trackedRace); + } + + @Override + public void closeOpenEndedDeviceMapping(String leaderboardName, DeviceMappingDTO mappingDTO, Date closingTimePoint) + throws TransformationException, DoesNotHaveRegattaLogException, UnableToCloseDeviceMappingException, + NotFoundException { + getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); + RegattaLog regattaLog = getRegattaLogInternal(leaderboardName); + closeOpenEndedDeviceMapping(regattaLog, mappingDTO, closingTimePoint); + } + + @Override + public void updateFixedMarkPassing(String leaderboardName, String raceColumnName, String fleetName, Integer indexOfWaypoint, + Date dateOfMarkPassing, CompetitorDTO competitorDTO) throws NotFoundException { + getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); + final RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); + final Competitor competitor = getCompetitor(competitorDTO); + RaceLogFixedMarkPassingEvent oldFixedMarkPassingEvent = null; + raceLog.lockForRead(); + try { + for (RaceLogEvent event : raceLog.getUnrevokedEvents()) { + if (event instanceof RaceLogFixedMarkPassingEventImpl && event.getInvolvedCompetitors().contains(competitor)) { + RaceLogFixedMarkPassingEvent fixedEvent = (RaceLogFixedMarkPassingEvent) event; + if (Util.equalsWithNull(fixedEvent.getZeroBasedIndexOfPassedWaypoint(), indexOfWaypoint)) { + oldFixedMarkPassingEvent = fixedEvent; + } + } + } + } finally { + raceLog.unlockAfterRead(); + } + if (oldFixedMarkPassingEvent != null) { + try { + raceLog.revokeEvent(getService().getServerAuthor(), oldFixedMarkPassingEvent); + } catch (NotRevokableException e) { + e.printStackTrace(); + } + } + if (dateOfMarkPassing != null) { + raceLog.add(new RaceLogFixedMarkPassingEventImpl(MillisecondsTimePoint.now(), getService() + .getServerAuthor(), competitor, raceLog.getCurrentPassId(), + new MillisecondsTimePoint(dateOfMarkPassing), indexOfWaypoint)); + } + } + + @Override + public void updateSuppressedMarkPassings(String leaderboardName, String raceColumnName, String fleetName, + Integer newZeroBasedIndexOfSuppressedMarkPassing, CompetitorDTO competitorDTO) throws NotFoundException { + getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); + RaceLogSuppressedMarkPassingsEvent oldSuppressedMarkPassingEvent = null; + final RaceLog raceLog = getService().getRaceLog(leaderboardName, raceColumnName, fleetName); + final Competitor competitor = getCompetitor(competitorDTO); + raceLog.lockForRead(); + try { + final NavigableSet unrevokedEvents = raceLog.getUnrevokedEvents(); + for (RaceLogEvent event : unrevokedEvents) { + if (event instanceof RaceLogSuppressedMarkPassingsEvent && event.getInvolvedCompetitors().contains(competitor)) { + oldSuppressedMarkPassingEvent = (RaceLogSuppressedMarkPassingsEvent) event; + break; + } + } + } finally { + raceLog.unlockAfterRead(); + } + final boolean create; + final boolean revoke; + if (oldSuppressedMarkPassingEvent == null) { + if (newZeroBasedIndexOfSuppressedMarkPassing == null) { + create = false; + revoke = false; + } else { + create = true; + revoke = false; + } + } else { + if (newZeroBasedIndexOfSuppressedMarkPassing == null) { + revoke = true; + create = false; + } else { + boolean equal = Util.equalsWithNull(newZeroBasedIndexOfSuppressedMarkPassing, + oldSuppressedMarkPassingEvent.getZeroBasedIndexOfFirstSuppressedWaypoint()); + create = !equal; + revoke = !equal; + } + } + if (revoke) { + try { + raceLog.revokeEvent(getService().getServerAuthor(), oldSuppressedMarkPassingEvent); + } catch (NotRevokableException e) { + logger.log(Level.SEVERE, "Unable to revoke event "+oldSuppressedMarkPassingEvent, e); + } + } + if (create) { + raceLog.add(new RaceLogSuppressedMarkPassingsEventImpl(MillisecondsTimePoint.now(), getService() + .getServerAuthor(), competitor, raceLog.getCurrentPassId(), + newZeroBasedIndexOfSuppressedMarkPassing)); + } + } + + private FileStorageService getFileStorageService(String name) { + if (name == null || name.equals("")) { + return null; + } + return getService().getFileStorageManagementService().getFileStorageService(name); + } + + @Override + public FileStorageServiceDTO[] getAvailableFileStorageServices(String localeInfoName) { + List serviceDtos = new ArrayList<>(); + final FileStorageManagementService fileStorageManagementService = getService() + .getFileStorageManagementService(); + if (fileStorageManagementService != null) { + for (FileStorageService s : fileStorageManagementService.getAvailableFileStorageServices()) { + serviceDtos.add(FileStorageServiceDTOUtils.convert(s, getLocale(localeInfoName))); + } + } + return serviceDtos.toArray(new FileStorageServiceDTO[0]); + } + + @Override + public void setFileStorageServiceProperties(String serviceName, Map properties) { + getSecurityService().checkCurrentUserUpdatePermission(getServerInfo()); + for (Entry p : properties.entrySet()) { + try { + getService().getFileStorageManagementService() + .setFileStorageServiceProperty(getFileStorageService(serviceName), p.getKey(), p.getValue()); + } catch (NoCorrespondingServiceRegisteredException | IllegalArgumentException e) { + // ignore, doing refresh afterwards anyways + } + } + } + + @Override + public FileStorageServicePropertyErrorsDTO testFileStorageServiceProperties(String serviceName, + String localeInfoName) throws IOException { + try { + if (serviceName == null) { + serviceName = getActiveFileStorageServiceName(); + } + FileStorageService service = getFileStorageService(serviceName); + if (service != null) { + service.testProperties(); + } + } catch (InvalidPropertiesException e) { + return FileStorageServiceDTOUtils.convert(e, getLocale(localeInfoName)); + } + return null; + } + + @Override + public void setActiveFileStorageService(String serviceName, String localeInfoName) { + getSecurityService().checkCurrentUserUpdatePermission(getServerInfo()); + getService().getFileStorageManagementService().setActiveFileStorageService(getFileStorageService(serviceName)); + } + + @Override + public String getActiveFileStorageServiceName() { + try { + final FileStorageService activeFileStorageService = getService().getFileStorageManagementService() + .getActiveFileStorageService(); + return activeFileStorageService == null ? null : activeFileStorageService.getName(); + } catch (NoCorrespondingServiceRegisteredException e) { + return null; + } + } + + @Override + public void inviteCompetitorsForTrackingViaEmail(String serverUrlWithoutTrailingSlash, EventDTO eventDto, + String leaderboardName, Collection competitorDtos, String iOSAppUrl, String androidAppUrl, + String localeInfoName) throws MailException { + Event event = getService().getEvent(eventDto.id); + getSecurityService().checkCurrentUserReadPermission(event); + Set competitors = new HashSet<>(); + for (CompetitorDTO c : competitorDtos) { + competitors.add(getCompetitor(c)); + } + Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + getSecurityService().checkCurrentUserUpdatePermission(leaderboard); + Regatta regatta = getService().getRegattaByName(leaderboardName); + getSecurityService().checkCurrentUserUpdatePermission(regatta); + getRaceLogTrackingAdapter().inviteCompetitorsForTrackingViaEmail(event, leaderboard, regatta, + serverUrlWithoutTrailingSlash, competitors, iOSAppUrl, androidAppUrl, getLocale(localeInfoName), + getMailType()); + } + + @Override + public void inviteBuoyTenderViaEmail(String serverUrlWithoutTrailingSlash, EventDTO eventDto, + String leaderboardName, String emails, String iOSAppUrl, String androidAppUrl, String localeInfoName) + throws MailException { + Event event = getService().getEvent(eventDto.id); + getSecurityService().checkCurrentUserReadPermission(event); + Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + getSecurityService().checkCurrentUserReadPermission(leaderboard); + Regatta regatta = getService().getRegattaByName(leaderboardName); + getSecurityService().checkCurrentUserUpdatePermission(regatta); + MailInvitationType type = MailInvitationType + .valueOf(System.getProperty(MAILTYPE_PROPERTY, MailInvitationType.SailInsight1.name())); + getRaceLogTrackingAdapter().inviteBuoyTenderViaEmail(event, leaderboard, regatta, serverUrlWithoutTrailingSlash, + emails, iOSAppUrl, androidAppUrl, getLocale(localeInfoName), type); + } + + @Override + public void disableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) + throws NotRevokableException, NotFoundException { + getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); + if (areCompetitorRegistrationsEnabledForRace(leaderboardName, raceColumnName, fleetName)) { + RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); + raceColumn.disableCompetitorRegistrationOnRaceLog(getFleetByName(raceColumn, fleetName)); + } + } + + @Override + public void enableCompetitorRegistrationsForRace(String leaderboardName, String raceColumnName, String fleetName) + throws IllegalArgumentException, NotFoundException { + getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); + if (!areCompetitorRegistrationsEnabledForRace(leaderboardName, raceColumnName, fleetName)) { + RaceColumn raceColumn = getRaceColumn(leaderboardName, raceColumnName); + raceColumn.enableCompetitorRegistrationOnRaceLog(getFleetByName(raceColumn, fleetName)); + } + } + + @Override + public void removeMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, + GPSFixDTO fix) throws NotRevokableException { + final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + getSecurityService().checkCurrentUserUpdatePermission(leaderboard); + if (leaderboard != null) { + final RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + if (raceColumn != null) { + final TimePoint fixTimePoint = new MillisecondsTimePoint(fix.timepoint); + final RegattaLog regattaLog = raceColumn.getRegattaLog(); + final BaseRegattaLogDeviceMappingFinder mappingFinder = new RegattaLogDeviceMarkMappingFinder( + regattaLog); + final Fleet fleet = raceColumn.getFleetByName(fleetName); + if (fleet != null) { + for (final Mark mark : raceColumn.getAvailableMarks(fleet)) { + if (mark.getId().toString().equals(markIdAsString)) { + mappingFinder.removeTimePointFromMapping(mark, fixTimePoint); + } + } + } + } + } + } + + @Override + public void addMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, + GPSFixDTO newFix) { + final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + if (leaderboard != null) { + final RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + if (raceColumn != null) { + final RegattaLog regattaLog = raceColumn.getRegattaLog(); + final Fleet fleet = raceColumn.getFleetByName(fleetName); + if (fleet != null) { + for (final Mark mark : raceColumn.getAvailableMarks(fleet)) { + if (mark.getId().toString().equals(markIdAsString)) { + getRaceLogTrackingAdapter().pingMark(regattaLog, mark, + new GPSFixImpl(newFix.position, new MillisecondsTimePoint(newFix.timepoint)), + getService()); + } + } + } + } + } + } + + @Override + public void editMarkFix(String leaderboardName, String raceColumnName, String fleetName, String markIdAsString, + GPSFixDTO oldFix, Position newPosition) throws NotRevokableException { + final Leaderboard leaderboard = getService().getLeaderboardByName(leaderboardName); + getSecurityService().checkCurrentUserUpdatePermission(leaderboard); + if (leaderboard != null) { + final RaceColumn raceColumn = leaderboard.getRaceColumnByName(raceColumnName); + if (raceColumn != null) { + final RegattaLog regattaLog = raceColumn.getRegattaLog(); + final BaseRegattaLogDeviceMappingFinder mappingFinder = new RegattaLogDeviceMarkMappingFinder( + regattaLog); + final Fleet fleet = raceColumn.getFleetByName(fleetName); + if (fleet != null) { + final TimePoint fixTimePoint = new MillisecondsTimePoint(oldFix.timepoint); + for (final Mark mark : raceColumn.getAvailableMarks(fleet)) { + if (mark.getId().toString().equals(markIdAsString)) { + mappingFinder.removeTimePointFromMapping(mark, fixTimePoint); + getRaceLogTrackingAdapter().pingMark(regattaLog, mark, + new GPSFixImpl(newPosition, fixTimePoint), getService()); + } + } + } + } + } + } + + @Override + public void setEliminatedCompetitors(String leaderboardName, Set newEliminatedCompetitorDTOs) + throws NotFoundException { + getSecurityService().checkCurrentUserUpdatePermission(getLeaderboardByName(leaderboardName)); + Set newEliminatedCompetitors = new HashSet<>(); + for (final CompetitorDTO cDTO : newEliminatedCompetitorDTOs) { + final Competitor competitor = getCompetitor(cDTO); + newEliminatedCompetitors.add(competitor); + } + getService().apply(new UpdateEliminatedCompetitorsInLeaderboard(leaderboardName, newEliminatedCompetitors)); + } + + @Override + public void addOrReplaceExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration deviceConfiguration) { + getSecurityService().setOwnershipCheckPermissionForObjectCreationAndRevertOnError( + SecuredDomainType.EXPEDITION_DEVICE_CONFIGURATION, deviceConfiguration.getTypeRelativeObjectIdentifier(), + /* display name */ deviceConfiguration.getName(), () -> { + getService() + .apply(new AddOrReplaceExpeditionDeviceConfiguration(deviceConfiguration.getDeviceUuid(), + deviceConfiguration.getName(), deviceConfiguration.getExpeditionBoatId())); + }); + } + + @Override + public void removeExpeditionDeviceConfiguration(ExpeditionDeviceConfiguration deviceConfiguration) { + getSecurityService().checkPermissionAndDeleteOwnershipForObjectRemoval(deviceConfiguration.getIdentifier(), new Callable() { + @Override + public Void call() throws Exception { + getService().apply(new RemoveExpeditionDeviceConfiguration(deviceConfiguration.getDeviceUuid())); + return null; + } + }); + } + + @Override + public boolean canSliceRace(RegattaAndRaceIdentifier raceIdentifier) { + final Regatta regatta = getService().getRegattaByName(raceIdentifier.getRegattaName()); + final Leaderboard regattaLeaderboard = getService().getLeaderboardByName(raceIdentifier.getRegattaName()); + final DynamicTrackedRace trackedRace = getService().getTrackedRace(raceIdentifier); + getSecurityService().checkCurrentUserUpdatePermission(raceIdentifier); + getSecurityService().checkCurrentUserUpdatePermission(regattaLeaderboard); + getSecurityService().checkCurrentUserUpdatePermission(regatta); + + final boolean result; + if (regatta == null || !(regattaLeaderboard instanceof RegattaLeaderboard) || trackedRace == null + || trackedRace.getStartOfTracking() == null || !isSmartphoneTrackingEnabled(trackedRace)) { + result = false; + } else { + final Pair raceColumnAndFleetOfRaceToSlice = regattaLeaderboard + .getRaceColumnAndFleet(trackedRace); + result = (raceColumnAndFleetOfRaceToSlice != null); // is the TrackedRace associated to the given + // RegattaLeaderboard? + } + return result; + } + + @Override + public RegattaAndRaceIdentifier sliceRace(RegattaAndRaceIdentifier raceIdentifier, String newRaceColumnName, + TimePoint sliceFrom, TimePoint sliceTo) throws ServiceException { + SecurityUtils.getSubject().checkPermission( + SecuredDomainType.REGATTA.getStringPermissionForTypeRelativeIdentifier(DefaultActions.UPDATE, + Regatta.getTypeRelativeObjectIdentifier(raceIdentifier.getRegattaName()))); + SecurityUtils.getSubject() + .checkPermission(SecuredDomainType.LEADERBOARD.getStringPermissionForTypeRelativeIdentifier( + DefaultActions.UPDATE, + Leaderboard.getTypeRelativeObjectIdentifier(raceIdentifier.getRegattaName()))); + final Locale locale = getClientLocale(); + if (!canSliceRace(raceIdentifier)) { + throw new ServiceException(serverStringMessages.get(locale, "slicingCannotSliceRace")); + } + final String trackedRaceName = newRaceColumnName; + final RegattaIdentifier regattaIdentifier = new RegattaName(raceIdentifier.getRegattaName()); + final Regatta regatta = getService().getRegatta(regattaIdentifier); + final Leaderboard regattaLeaderboard = getService().getLeaderboardByName(regatta.getName()); + if (regattaLeaderboard == null) { + throw new IllegalArgumentException("Cannot slice a race for which no regatta leaderboard exists"); + } + if (regatta.getRaceColumnByName(newRaceColumnName) != null) { + throw new ServiceException(serverStringMessages.get(locale, "slicingRaceColumnAlreadyUsedThe")); + } + final DynamicTrackedRace trackedRaceToSlice = getService().getTrackedRace(raceIdentifier); + final TimePoint startOfTrackingOfRaceToSlice = trackedRaceToSlice.getStartOfTracking(); + final TimePoint endOfTrackingOfRaceToSlice = trackedRaceToSlice.getEndOfTracking(); + if (sliceFrom == null || sliceTo == null || startOfTrackingOfRaceToSlice.after(sliceFrom) + || (endOfTrackingOfRaceToSlice != null && endOfTrackingOfRaceToSlice.before(sliceTo))) { + throw new ServiceException(serverStringMessages.get(locale, "slicingTimeRangeOutOfBounds")); + } + final Pair raceColumnAndFleetOfRaceToSlice = regatta.getRaceColumnAndFleet(trackedRaceToSlice); + // RaceColumns in a RegattaLeaderboard are always RaceColumnInSeries instances + final RaceColumnInSeries raceColumnOfRaceToSlice = (RaceColumnInSeries) raceColumnAndFleetOfRaceToSlice.getA(); + final Fleet fleet = raceColumnAndFleetOfRaceToSlice.getB(); + final Series series = raceColumnOfRaceToSlice.getSeries(); + final RaceLog raceLogOfRaceToSlice = raceColumnOfRaceToSlice.getRaceLog(fleet); + final RaceColumn raceColumn = getService().apply(new AddColumnToSeries(regattaIdentifier, series.getName(), newRaceColumnName)); + final RaceLog raceLog = raceColumn.getRaceLog(fleet); + final AbstractLogEventAuthor author = getService().getServerAuthor(); + final TimePoint startOfTracking = sliceFrom; + final TimePoint endOfTracking = sliceTo; + raceLog.add(new RaceLogStartOfTrackingEventImpl(startOfTracking, author, raceLog.getCurrentPassId())); + raceLog.add(new RaceLogEndOfTrackingEventImpl(endOfTracking, author, raceLog.getCurrentPassId())); + final TimeRange timeRange = new TimeRangeImpl(sliceFrom, sliceTo); + final StartTimeFinderResult startTimeFinderResult = new StartTimeFinder(getService(), raceLogOfRaceToSlice).analyze(); + final TimePoint startTime = startTimeFinderResult.getStartTime(); + final boolean hasStartTime = startTime != null && timeRange.includes(startTime); + final boolean dependentStartTime = startTimeFinderResult.isDependentStartTime(); + final boolean hasFinishingTime; + final boolean hasFinishedTime; + if (hasStartTime) { + final TimePoint finishingTime = new FinishingTimeFinder(raceLog).analyze(); + hasFinishingTime = finishingTime != null && timeRange.includes(finishingTime); + if (hasFinishingTime) { + final TimePoint finishedTime = new FinishedTimeFinder(raceLog).analyze(); + hasFinishedTime = finishedTime != null && timeRange.includes(finishedTime); + } else { + hasFinishedTime = false; + } + } else { + hasFinishingTime = false; + hasFinishedTime = false; + } + + // Only wind fixes in the new tracking interval as well as the best fallback fixes are added to the new RaceLog + final LogEventTimeRangeWithFallbackFilter windFixEvents = new LogEventTimeRangeWithFallbackFilter<>( + timeRange); + raceLogOfRaceToSlice.lockForRead(); + try { + for (RaceLogEvent raceLogEvent : raceLogOfRaceToSlice.getUnrevokedEvents()) { + raceLogEvent.accept(new BaseRaceLogEventVisitor() { + @Override + public void visit(RaceLogDependentStartTimeEvent event) { + if (dependentStartTime && isLatestPass(event)) { + raceLog.add(new RaceLogDependentStartTimeEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), + raceLog.getCurrentPassId(), event.getDependentOnRaceIdentifier(), + event.getStartTimeDifference(), event.getNextStatus(), event.getCourseAreaId())); + } + } + + @Override + public void visit(RaceLogStartTimeEvent event) { + if (!dependentStartTime && isLatestPass(event)) { + raceLog.add(new RaceLogStartTimeEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), + event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), event.getStartTime(), + event.getNextStatus(), event.getCourseAreaId())); + } + } + + @Override + public void visit(RaceLogRegisterCompetitorEvent event) { + raceLog.add(new RaceLogRegisterCompetitorEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), + raceLog.getCurrentPassId(), event.getCompetitor(), event.getBoat())); + } + + @Override + public void visit(RaceLogWindFixEvent event) { + windFixEvents.addEvent(event); + } + + @Override + public void visit(RaceLogUseCompetitorsFromRaceLogEvent event) { + raceLog.add(new RaceLogUseCompetitorsFromRaceLogEventImpl(event.getCreatedAt(), event.getAuthor(), + event.getLogicalTimePoint(), UUID.randomUUID(), raceLog.getCurrentPassId())); + } + + @Override + public void visit(RaceLogCourseDesignChangedEvent event) { + raceLog.add(new RaceLogCourseDesignChangedEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), + raceLog.getCurrentPassId(), event.getCourseDesign(), event.getCourseDesignerMode())); + } + + @Override + public void visit(RaceLogFlagEvent event) { + if (hasStartTime && isLatestPass(event) && !event.getLogicalTimePoint().after(sliceTo)) { + raceLog.add(new RaceLogFlagEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), + event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), event.getUpperFlag(), + event.getLowerFlag(), event.isDisplayed())); + } + } + + @Override + public void visit(RaceLogStartProcedureChangedEvent event) { + if (hasStartTime && isLatestPass(event)) { + raceLog.add(new RaceLogStartProcedureChangedEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), + raceLog.getCurrentPassId(), event.getStartProcedureType())); + } + } + + @Override + public void visit(RaceLogFinishPositioningConfirmedEvent event) { + if (hasFinishedTime && isLatestPass(event)) { + raceLog.add(new RaceLogFinishPositioningConfirmedEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), + raceLog.getCurrentPassId(), event.getPositionedCompetitorsIDsNamesMaxPointsReasons())); + } + } + + @Override + public void visit(RaceLogFinishPositioningListChangedEvent event) { + if (hasFinishedTime && isLatestPass(event)) { + raceLog.add(new RaceLogFinishPositioningListChangedEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), + raceLog.getCurrentPassId(), event.getPositionedCompetitorsIDsNamesMaxPointsReasons())); + } + } + + @Override + public void visit(RaceLogFixedMarkPassingEvent event) { + if (hasStartTime && isLatestPass(event) && timeRange.includes(event.getTimePointOfFixedPassing())) { + raceLog.add(new RaceLogFixedMarkPassingEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), + event.getInvolvedCompetitors(), raceLog.getCurrentPassId(), + event.getTimePointOfFixedPassing(), event.getZeroBasedIndexOfPassedWaypoint())); + } + } + + @Override + public void visit(RaceLogSuppressedMarkPassingsEvent event) { + if (hasStartTime && isLatestPass(event) && timeRange.includes(event.getLogicalTimePoint())) { + raceLog.add(new RaceLogSuppressedMarkPassingsEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), + event.getInvolvedCompetitors(), raceLog.getCurrentPassId(), + event.getZeroBasedIndexOfFirstSuppressedWaypoint())); + } + } + + @Override + public void visit(RaceLogProtestStartTimeEvent event) { + if (hasFinishedTime && isLatestPass(event)) { + raceLog.add(new RaceLogProtestStartTimeEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), + raceLog.getCurrentPassId(), event.getProtestTime())); + } + } + + @Override + public void visit(RaceLogAdditionalScoringInformationEvent event) { + if (hasFinishedTime && isLatestPass(event)) { + raceLog.add(new RaceLogAdditionalScoringInformationEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), + raceLog.getCurrentPassId(), event.getType())); + } + } + + @Override + public void visit(RaceLogPathfinderEvent event) { + if (hasStartTime && isLatestPass(event)) { + raceLog.add(new RaceLogPathfinderEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), + event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), + event.getPathfinderId())); + } + } + + @Override + public void visit(RaceLogGateLineOpeningTimeEvent event) { + if (hasStartTime && isLatestPass(event)) { + raceLog.add(new RaceLogGateLineOpeningTimeEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), + raceLog.getCurrentPassId(), event.getGateLineOpeningTimes().getGateLaunchStopTime(), + event.getGateLineOpeningTimes().getGolfDownTime())); + } + } + + @Override + public void visit(RaceLogRaceStatusEvent event) { + if (isLatestPass(event) && !(event instanceof RaceLogDependentStartTimeEvent) + && !(event instanceof RaceLogStartTimeEvent)) { + if ((hasStartTime + && event.getNextStatus().getOrderNumber() <= RaceLogRaceStatus.RUNNING.getOrderNumber()) + || (hasFinishingTime && event.getNextStatus() == RaceLogRaceStatus.FINISHING) + || (hasFinishedTime && event.getNextStatus() == RaceLogRaceStatus.FINISHED)) { + raceLog.add(new RaceLogRaceStatusEventImpl(event.getCreatedAt(), event.getLogicalTimePoint(), + event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), + event.getNextStatus())); + } + } + } + + @Override + public void visit(RaceLogORCImpliedWindSourceEvent event) { + raceLog.add(new RaceLogORCImpliedWindSourceEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), + raceLog.getCurrentPassId(), event.getImpliedWindSource())); + } + + @Override + public void visit(RaceLogORCCertificateAssignmentEvent event) { + raceLog.add(new RaceLogORCCertificateAssignmentEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), + raceLog.getCurrentPassId(), event.getCertificate(), event.getBoatId())); + } + + @Override + public void visit(RaceLogORCScratchBoatEvent event) { + raceLog.add(new RaceLogORCScratchBoatEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), + raceLog.getCurrentPassId(), event.getCompetitor())); + } + + private boolean isLatestPass(RaceLogEvent event) { + return event.getPassId() == raceLogOfRaceToSlice.getCurrentPassId(); + } + }); + } + } finally { + raceLogOfRaceToSlice.unlockAfterRead(); + } + windFixEvents.getFilteredEvents() + .forEach(event -> raceLog.add(new RaceLogWindFixEventImpl(event.getCreatedAt(), + event.getLogicalTimePoint(), event.getAuthor(), UUID.randomUUID(), raceLog.getCurrentPassId(), + event.getWindFix(), event.isMagnetic()))); + final TimePoint startTrackingTimePoint = MillisecondsTimePoint.now(); + // this ensures that the events consistently have different timepoints to ensure a consistent result of the state analysis + // that's why we can't just call adapter.denoteRaceForRaceLogTracking + final TimePoint denotationTimePoint = startTrackingTimePoint.minus(1); + raceLog.add(new RaceLogDenoteForTrackingEventImpl(denotationTimePoint, + author, raceLog.getCurrentPassId(), trackedRaceName, regatta.getBoatClass(), UUID.randomUUID())); + raceLog.add(new RaceLogStartTrackingEventImpl(startTrackingTimePoint, author, raceLog.getCurrentPassId())); + try { + final RaceHandle raceHandle = getRaceLogTrackingAdapter().startTracking(getService(), regattaLeaderboard, + raceColumn, fleet, /* trackWind */ true, /* correctWindDirectionByMagneticDeclination */ true, + getService().getPermissionAwareRaceTrackingHandler()); + + // wait for the RaceDefinition to be created + raceHandle.getRace(); + + final DynamicTrackedRace trackedRace = WaitForTrackedRaceUtil.waitForTrackedRace(raceColumn, fleet, 10); + if (trackedRace == null) { + throw new ServiceException(serverStringMessages.get(locale, "slicingCouldNotObtainRace")); + } + for (WindSource windSourceToCopy : trackedRaceToSlice.getWindSources()) { + if (windSourceToCopy.canBeStored()) { + final WindTrack windTrackToCopyFrom = trackedRaceToSlice.getOrCreateWindTrack(windSourceToCopy); + windTrackToCopyFrom.lockForRead(); + try { + for (Wind windToCopy : windTrackToCopyFrom.getFixes(startOfTracking, true, endOfTracking, true)) { + trackedRace.recordWind(windToCopy, windSourceToCopy); + } + } finally { + windTrackToCopyFrom.unlockAfterRead(); + } + } + } + + final Iterable mediaTracksForOriginalRace = getService().getMediaTracksForRace(raceIdentifier); + for (MediaTrack mediaTrack : mediaTracksForOriginalRace) { + if (mediaTrack.overlapsWith(sliceFrom, sliceTo)) { + final Set assignedRaces = new HashSet<>(mediaTrack.assignedRaces); + assignedRaces.add(trackedRace.getRaceIdentifier()); + // we can't just use the original instance and add the Race due to the fact that this leads to + // assignedRaces being empty afterwards. + final MediaTrack mediaTrackToSave = new MediaTrack(mediaTrack.dbId, mediaTrack.title, + mediaTrack.url, mediaTrack.startTime, mediaTrack.duration, mediaTrack.mimeType, + assignedRaces); + getService().mediaTrackAssignedRacesChanged(mediaTrackToSave); + } + } + return trackedRace.getRaceIdentifier(); + } catch (Exception e) { + throw new ServiceException(serverStringMessages.get(locale, "slicingError")); + } + } + + + @Override + public Set resizeImage(final ImageResizingTaskDTO resizingTask) throws Exception { + if (resizingTask.getResizingTask() == null || resizingTask.getResizingTask().size() == 0) { + throw new InvalidAttributeValueException("Resizing Task can not be null or empty"); + } + final ImageConverter converter = new ImageConverter(); + // calculating the fileType of the image by its uri + final String sourceRef = resizingTask.getImage().getSourceRef(); + final String fileType = sourceRef.substring(sourceRef.lastIndexOf(".") + 1); + final ImageWithMetadata imageAndMetadata = converter + .loadImage(HttpUrlConnectionHelper.redirectConnection(new URL(sourceRef)).getInputStream(), fileType); + final List resizedImages = converter.convertImage(imageAndMetadata.getImage(), + resizingTask.getResizingTask()); + final List sourceRefs = storeImages(resizedImages, fileType, imageAndMetadata.getMetadata()); + // if an error occures while storing the files, all already stored files are removed before throwing an + // exception + if (sourceRefs == null || sourceRefs.size() < resizingTask.getResizingTask().size()) { + for (String alreadyStoredFileRef : sourceRefs) { + try { + getService().getFileStorageManagementService().getActiveFileStorageService() + .removeFile(new URI(alreadyStoredFileRef)); + } catch (Exception e) { + } + // Exception occured while trying to revert changes after exception + // This only keeps some trash on the FileStorage + } + throw new Exception("Error occured while storing images on the FileStorage"); + } + final Set resizedImagesAsDTOs = createImageDTOsFromURLsAndResizingTask(sourceRefs, resizingTask, + resizedImages); + for (String tag : resizingTask.getImage().getTags()) { + final MediaTagConstants predefinedTag = MediaTagConstants.fromName(tag); + if (predefinedTag != null && !resizingTask.getResizingTask().contains(predefinedTag)) { + final ImageDTO image = resizingTask.getImage(); + for (MediaTagConstants tagConstant : resizingTask.getResizingTask()) { + image.getTags().remove(tagConstant.getName()); + } + resizedImagesAsDTOs.add(image); + } + } + return resizedImagesAsDTOs; + } + + /** + * Stores a list of BufferedImages and returns a list of URLs as Strings under which the BufferedImages are stored + * + * @author Robin Fleige (D067799) + * + * @param resizedImages + * the BufferedImages that will be stored + * @param fileType + * the format of the image, for example "png", "jpeg" or "jpg" + * @param metadata + * the metadata of the original image + * @returns a list of URLs as Strings under which the BufferedImages are stored + */ + private List storeImages(final List resizedImages, final String fileType, + final IIOMetadata metadata) { + final List sourceRefs = new ArrayList<>(); + + try { + for (final BufferedImage resizedImage : resizedImages) { + final InputStream fileStorageStream = new ImageConverter().imageWithMetadataToInputStream(resizedImage, + metadata, fileType); + sourceRefs.add(getService().getFileStorageManagementService().getActiveFileStorageService() + .storeFile(fileStorageStream, "." + fileType, new Long(fileStorageStream.available())) + .toString()); + } + } catch (NoCorrespondingServiceRegisteredException | IOException | OperationFailedException + | InvalidPropertiesException e) { + logger.log(Level.SEVERE, "Could not store file. Cause: " + e.getMessage()); + } + return sourceRefs; + } + + @Override + public SuccessInfo addTag(String leaderboardName, String raceColumnName, String fleetName, String tag, + String comment, String imageURL, String resizedImageURL, boolean visibleForPublic, + TimePoint raceTimepoint) { + SuccessInfo successInfo = new SuccessInfo(true, null, null, null); + try { + getService().getTaggingService().addTag(leaderboardName, raceColumnName, fleetName, tag, comment, imageURL, + resizedImageURL, visibleForPublic, raceTimepoint); + } catch (AuthorizationException e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "missingAuthorization"), + null, null); + } catch (IllegalArgumentException e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "invalidParameters"), null, + null); + } catch (RaceLogNotFoundException e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "raceLogNotFound"), null, + null); + } catch (ServiceNotFoundException e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "securityServiceNotFound"), + null, null); + } catch (TagAlreadyExistsException e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagAlreadyExists"), null, + null); + } catch (Exception e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "unknownError"), null, + null); + } + return successInfo; + } + + @Override + public SuccessInfo removeTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tag) { + SuccessInfo successInfo = new SuccessInfo(true, null, null, null); + try { + getService().getTaggingService().removeTag(leaderboardName, raceColumnName, fleetName, tag); + } catch (AuthorizationException e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "missingAuthorization"), + null, null); + } catch (IllegalArgumentException e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "invalidParameters"), null, + null); + } catch (NotRevokableException e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagNotRevokable"), null, + null); + } catch (RaceLogNotFoundException e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "raceLogNotFound"), null, + null); + } catch (Exception e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "unknownError"), null, + null); + } + return successInfo; + } + + @Override + public SuccessInfo updateTag(String leaderboardName, String raceColumnName, String fleetName, TagDTO tagToUpdate, + String tag, String comment, String imageURL, String resizedImageURL, boolean visibleForPublic) { + SuccessInfo successInfo = new SuccessInfo(true, null, null, null); + try { + getService().getTaggingService().updateTag(leaderboardName, raceColumnName, fleetName, tagToUpdate, tag, + comment, imageURL, resizedImageURL, visibleForPublic); + } catch (AuthorizationException e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "missingAuthorization"), + null, null); + } catch (IllegalArgumentException e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "invalidParameters"), null, + null); + } catch (NotRevokableException e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagNotRevokable"), null, + null); + } catch (RaceLogNotFoundException e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "raceLogNotFound"), null, + null); + } catch (TagAlreadyExistsException e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "tagAlreadyExists"), null, + null); + } catch (Exception e) { + successInfo = new SuccessInfo(false, serverStringMessages.get(getClientLocale(), "unknownError"), null, + null); + } + return successInfo; + } + + @Override + public void updateGroupOwnerForEventHierarchy(UUID eventId, + MigrateGroupOwnerForHierarchyDTO migrateGroupOwnerForHierarchyDTO) { + Event event = getService().getEvent(eventId); + if (event != null) { + createOwnershipUpdater(migrateGroupOwnerForHierarchyDTO).updateGroupOwnershipForEventHierarchy(event); + } + } + + private SailingHierarchyOwnershipUpdater createOwnershipUpdater( + MigrateGroupOwnerForHierarchyDTO migrateGroupOwnerForHierarchyDTO) { + return SailingHierarchyOwnershipUpdater.createOwnershipUpdater( + migrateGroupOwnerForHierarchyDTO.isCreateNewGroup(), + migrateGroupOwnerForHierarchyDTO.getExistingUserGroupIdOrNull(), + migrateGroupOwnerForHierarchyDTO.getGroupName(), migrateGroupOwnerForHierarchyDTO.isUpdateCompetitors(), + migrateGroupOwnerForHierarchyDTO.isUpdateBoats(), + migrateGroupOwnerForHierarchyDTO.isCopyMembersAndRoles(), getService()); + } + + @Override + public void updateGroupOwnerForLeaderboardGroupHierarchy(UUID leaderboardGroupId, + MigrateGroupOwnerForHierarchyDTO migrateGroupOwnerForHierarchyDTO) { + LeaderboardGroup leaderboardGroup = getService().getLeaderboardGroupByID(leaderboardGroupId); + if (leaderboardGroup != null) { + createOwnershipUpdater(migrateGroupOwnerForHierarchyDTO) + .updateGroupOwnershipForLeaderboardGroupHierarchy(leaderboardGroup); + } + } + + @Override + public String getSecretForRegattaByName(String regattaName) { + String result = ""; + Regatta regatta = getService().getRegattaByName(regattaName); + if (regatta != null) { + getSecurityService().checkCurrentUserUpdatePermission(regatta); + result = regatta.getRegistrationLinkSecret(); + } + return result; + } + + @Override + public void setORCPerformanceCurveLegInfo(RegattaAndRaceIdentifier raceIdentifier, + Map legInfo) throws NotRevokableException { + final TrackedRace existingTrackedRace = getExistingTrackedRace(raceIdentifier); + getService().getSecurityService().checkCurrentUserUpdatePermission(existingTrackedRace); + setORCPerformanceCurveInfo(existingTrackedRace.getAttachedRaceLogs().iterator().next(), legInfo); + } + + private void setORCPerformanceCurveInfo(RaceLog raceLog, Map legInfo) + throws NotRevokableException { + final AbstractLogEventAuthor author = getService().getServerAuthor(); + for (final Entry e : new RaceLogORCLegDataEventFinder(raceLog).analyze() + .entrySet()) { + assert e.getValue() != null; + final ORCPerformanceCurveLeg leg = RaceLogORCLegDataAnalyzer.createORCPerformanceCurveLeg(e.getValue()); + final ORCPerformanceCurveLegImpl desiredLeg = legInfo.get(e.getKey()); + final boolean explicitRevoke = legInfo.containsKey(e.getKey()) && legInfo.get(e.getKey()) == null; + if (Util.equalsWithNull(desiredLeg, leg)) { + assert desiredLeg != null; + // we already have what the client wants, namely either nothing found and an explicitRevoke was + // requested, + // or the desiredLeg matched with what the log has; remove the request from the legInfo, meaning it has + // been handled: + legInfo.remove(e.getKey()); + } else { + // either we have an explicitRevoke and found a leg setting in the race log that therefore needs to be + // revoked, + // or the leg event found in the log does not match the desiredLeg for this index. + raceLog.revokeEvent(author, e.getValue()); + // In case an explicit revoke was what was requested, we have handled the request: + if (explicitRevoke) { + legInfo.remove(e.getKey()); + } + } + } + // for the remaining legInfo entries we now have to create race log events: + final TimePoint now = MillisecondsTimePoint.now(); + for (final Entry e : legInfo.entrySet()) { + if (e.getValue() != null) { + raceLog.add(new RaceLogORCLegDataEventImpl(now, now, author, UUID.randomUUID(), /* pPassId */ 0, + e.getKey(), e.getValue().getTwa(), e.getValue().getLength(), e.getValue().getType())); + } + } + } + + @Override + public void setORCPerformanceCurveLegInfo(String leaderboardName, String raceColumnName, String fleetName, + Map legInfo) throws NotFoundException, NotRevokableException { + setORCPerformanceCurveInfo(getRaceLog(leaderboardName, raceColumnName, fleetName), legInfo); + } + + private Triple createCertificateAssignmentsForRaceLog(String leaderboardName, + String raceColumnName, String fleetName, Map certificatesForBoatIdsAsString) + throws IOException, NotFoundException { + final Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + getService().getSecurityService().checkCurrentUserUpdatePermission(leaderboard); + final RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); + final LogEventConstructor logEventConstructor = createRaceLogEventConstructor(); + return createCertificateAssignments(raceLog, logEventConstructor, certificatesForBoatIdsAsString); + } + + private Triple createCertificateAssignmentsForRegatta( + RegattaIdentifier regattaIdentifier, Map certificatesForBoatIdsAsString) + throws IOException, NotFoundException { + final Regatta regatta = (Regatta) regattaIdentifier.getRegatta(getService()); + if (regatta == null) { + throw new NotFoundException("Regatta named " + regattaIdentifier + " not found"); + } else { + getService().getSecurityService().checkCurrentUserUpdatePermission(regatta); + final RegattaLog regattaLog = regatta.getRegattaLog(); + final LogEventConstructor logEventConstructor = createRegattaLogEventConstructor(); + return createCertificateAssignments(regattaLog, logEventConstructor, certificatesForBoatIdsAsString); + } + } + + private LogEventConstructor createRegattaLogEventConstructor() { + final LogEventConstructor logEventConstructor = (TimePoint createdAt, + TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, ORCCertificate certificate, + Boat boat) -> new RegattaLogORCCertificateAssignmentEventImpl(createdAt, logicalTimePoint, author, pId, + certificate, boat); + return logEventConstructor; + } + + @Override + public Triple assignORCPerformanceCurveCertificates(RegattaIdentifier regattaIdentifier, + Map certificatesForBoatsWithIdAsString) throws IOException, NotFoundException { + return createCertificateAssignmentsForRegatta(regattaIdentifier, certificatesForBoatsWithIdAsString); + } + + @Override + public Triple assignORCPerformanceCurveCertificates(String leaderboardName, + String raceColumnName, String fleetName, Map certificatesForBoatsWithIdAsString) + throws IOException, NotFoundException { + return createCertificateAssignmentsForRaceLog(leaderboardName, raceColumnName, fleetName, + certificatesForBoatsWithIdAsString); + } + + /** + * @return the number of certificate assignments inserted into (not replaced in) the log in the first component of + * the triple returned; this may be fewer than requested because redundant assignments are ignored; the + * number of assignments replaced in the log in the second component of the triple. The third element of the + * triple is the number of assignments effectively revoked (not including those replaced). + */ + protected , VisitorT, LogEventT extends AbstractLogEvent, AssignmentEventT extends ORCCertificateAssignmentEvent> Triple createCertificateAssignments( + LogT logToAddTo, LogEventConstructor logEventConstructor, + Map certificatesForBoatIdsAsString) throws IOException { + int insertedCount = 0; + int replacedCount = 0; + int removedCount = 0; + final BaseORCCertificateAssignmentAnalyzer analyzerForPreviousAssignments = new BaseORCCertificateAssignmentAnalyzer<>( + logToAddTo); + final Map validCertificateAssignmentsInLogByBoatId = analyzerForPreviousAssignments + .analyze(); + final TimePoint now = MillisecondsTimePoint.now(); + final CompetitorAndBoatStore boatStore = getService().getCompetitorAndBoatStore(); + final AbstractLogEventAuthor serverAuthor = getService().getServerAuthor(); + for (final Entry mapping : certificatesForBoatIdsAsString.entrySet()) { + final Serializable boatId = UUIDHelper.tryUuidConversion(mapping.getKey()); + final AssignmentEventT previouslyValidAssignmentEventForBoat = validCertificateAssignmentsInLogByBoatId + .remove(boatId); + final ORCCertificate certificate = mapping.getValue(); + final Boat boat = boatStore.getExistingBoatById(boatId); + if (boat != null) { + final boolean addEvent; + if (previouslyValidAssignmentEventForBoat != null) { + if (!previouslyValidAssignmentEventForBoat.getCertificate().getId().equals(certificate.getId())) { + // revoke the previously valid event because it has a different certificate + logger.info("Replacing certificate " + previouslyValidAssignmentEventForBoat.getCertificate() + + " for boat " + boat + " by " + certificate); + replacedCount++; + addEvent = true; + try { + @SuppressWarnings("unchecked") + final LogEventT previouslyValidAssignmentEventForBoatAsLogEventT = (LogEventT) previouslyValidAssignmentEventForBoat; + logToAddTo.revokeEvent(serverAuthor, previouslyValidAssignmentEventForBoatAsLogEventT); + } catch (NotRevokableException e) { + logger.severe("Couldn't revoke old certificate assignment event " + + previouslyValidAssignmentEventForBoat + ": " + e.getMessage()); + } + } else { + addEvent = false; + logger.info("Not replacing certificate " + + previouslyValidAssignmentEventForBoat.getCertificate() + " because the certificate " + + certificate + " requested to be assigned is considered equal."); + } + } else { + addEvent = true; + insertedCount++; + } + if (addEvent) { + final LogEventT assignment = logEventConstructor.create(now, now, serverAuthor, UUID.randomUUID(), + certificate, boat); + logToAddTo.add(assignment); + } + } + } + for (final Entry boatIdAndEventToRevoke : validCertificateAssignmentsInLogByBoatId + .entrySet()) { + @SuppressWarnings("unchecked") + final LogEventT eventToRevoke = (LogEventT) boatIdAndEventToRevoke.getValue(); + try { + logToAddTo.revokeEvent(serverAuthor, eventToRevoke); + removedCount++; + } catch (NotRevokableException e) { + logger.severe( + "Couldn't revoke old certificate assignment event " + eventToRevoke + ": " + e.getMessage()); + } + } + return new Triple<>(insertedCount, replacedCount, removedCount); + } + + protected LogEventConstructor createRaceLogEventConstructor() { + return (TimePoint createdAt, TimePoint logicalTimePoint, AbstractLogEventAuthor author, Serializable pId, + ORCCertificate certificate, Boat boat) -> new RaceLogORCCertificateAssignmentEventImpl(createdAt, + logicalTimePoint, author, pId, /* passId */ 0, certificate, boat); + } + + @Override + public CompetitorDTO getORCPerformanceCurveScratchBoat(String leaderboardName, String raceColumnName, + String fleetName) throws NotFoundException { + final Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + getService().getSecurityService().checkCurrentUserReadPermission(leaderboard); + final RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); + final RaceLogORCScratchBoatFinder finder = new RaceLogORCScratchBoatFinder(raceLog); + final Competitor scratchBoat = finder.analyze(); + return scratchBoat == null ? null : convertToCompetitorDTO(scratchBoat); + } + + @Override + public void setORCPerformanceCurveScratchBoat(String leaderboardName, String raceColumnName, String fleetName, + CompetitorDTO newScratchBoatDTO) throws NotFoundException { + final Leaderboard leaderboard = getLeaderboardByName(leaderboardName); + getService().getSecurityService().checkCurrentUserUpdatePermission(leaderboard); + final RaceLog raceLog = getRaceLog(leaderboardName, raceColumnName, fleetName); + final Competitor newScratchBoat = newScratchBoatDTO == null ? null + : getService().getCompetitorAndBoatStore() + .getExistingCompetitorById(UUIDHelper.tryUuidConversion(newScratchBoatDTO.getIdAsString())); + final RaceLogORCScratchBoatAnalyzer analyzer = new RaceLogORCScratchBoatAnalyzer(raceLog); + final Pair previousScratchBoatAndEvent = analyzer.analyze(); + final Competitor previousScratchBoat = previousScratchBoatAndEvent == null ? null + : previousScratchBoatAndEvent.getA(); + if (!Util.equalsWithNull(newScratchBoat, previousScratchBoat)) { + final AbstractLogEventAuthor serverAuthor = getService().getServerAuthor(); + if (previousScratchBoatAndEvent != null) { + // revoke scratch boat setting so far: + try { + raceLog.revokeEvent(serverAuthor, previousScratchBoatAndEvent.getB()); + } catch (NotRevokableException e) { + logger.log(Level.SEVERE, + "Unable to revoke scratch boat definition event " + previousScratchBoatAndEvent.getB(), e); + } + } + if (newScratchBoat != null) { + final TimePoint now = MillisecondsTimePoint.now(); + raceLog.add(new RaceLogORCScratchBoatEventImpl(now, now, serverAuthor, UUID.randomUUID(), + /* passId */ raceLog.getCurrentPassId(), newScratchBoat)); + } + } + } + + @Override + public MarkTemplateDTO addOrUpdateMarkTemplate(MarkTemplateDTO markTemplate) { + final UUID markTemplateUUID = UUID.randomUUID(); + final MarkTemplate mTemplate = getSecurityService() + .setOwnershipCheckPermissionForObjectCreationAndRevertOnError(SecuredDomainType.MARK_TEMPLATE, + MarkTemplate.getTypeRelativeObjectIdentifier(markTemplateUUID), markTemplate.getName(), + () -> getSharedSailingData().createMarkTemplate( + convertDtoToCommonMarkProperties(markTemplate.getCommonMarkProperties()))); + return convertToMarkTemplateDTO(mTemplate); + } + + private boolean existsSwissTimingArchiveConfigurationForCurrentUser(String jsonUrl) + throws Exception, UnauthorizedException { + boolean found = false; + final String currentUserName = getSecurityService().getCurrentUser().getName(); + for (final SwissTimingArchiveConfigurationWithSecurityDTO dto : getPreviousSwissTimingArchiveConfigurations()) { + if (dto.getJsonUrl().equals(jsonUrl) && currentUserName.equals(dto.getCreatorName())) { + found = true; + break; + } + } + return found; + } + + private boolean existsTracTracConfigurationForCurrentUser(String jsonUrl) throws Exception, UnauthorizedException { + boolean found = false; + final String currentUserName = getSecurityService().getCurrentUser().getName(); + for (final TracTracConfigurationWithSecurityDTO dto : getPreviousTracTracConfigurations()) { + if (dto.getJsonUrl().equals(jsonUrl) && currentUserName.equals(dto.getCreatorName())) { + found = true; + break; + } + } + return found; + } + + public boolean existsSwissTimingConfigurationForCurrentUser(String jsonUrl) + throws Exception, UnauthorizedException { + boolean found = false; + final String currentUserName = getSecurityService().getCurrentUser().getName(); + for (final SwissTimingConfigurationWithSecurityDTO dto : getPreviousSwissTimingConfigurations()) { + if (dto.getJsonUrl().equals(jsonUrl) && currentUserName.equals(dto.getCreatorName())) { + found = true; + break; + } + } + return found; + } + +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/EventBaseDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/EventBaseDTO.java index e2b31df53a4..db6a0b89308 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/EventBaseDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/EventBaseDTO.java @@ -9,6 +9,7 @@ import java.util.Map; import java.util.UUID; import com.google.gwt.user.client.rpc.IsSerializable; +import com.sap.sse.common.Util; import com.sap.sse.common.WithID; import com.sap.sse.common.media.ImageSize; import com.sap.sse.common.media.MediaTagConstants; @@ -16,6 +17,14 @@ import com.sap.sse.gwt.client.media.ImageDTO; import com.sap.sse.gwt.client.media.VideoDTO; import com.sap.sse.security.shared.dto.NamedDTO; +/** + * Basic event information as a DTO. The inherited {@link NamedDTO#equals(Object)} and {@link NamedDTO#hashCode()} + * methods that are based on the {@link NamedDTO#getName()} response are overridden here to be based on this event's + * {@link #getId() ID}. + * + * @author Axel Uhl (D043530) + * + */ public class EventBaseDTO extends NamedDTO implements WithID, IsSerializable { private static final long serialVersionUID = 818666323178097939L; @@ -68,6 +77,16 @@ public class EventBaseDTO extends NamedDTO implements WithID, IsSerializable { sailorsInfoWebsiteURLs = new HashMap<>(); } + @Override + public boolean equals(Object o) { + return Util.equalsWithNull(this.getId(), ((EventBaseDTO) o).getId()); + } + + @Override + public int hashCode() { + return this.getId().hashCode(); + } + public ImageDTO getLogoImage() { ImageDTO result = null; for (ImageDTO image : images) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/EventDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/EventDTO.java index e99bd8669fb..ff8a35c0936 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/EventDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/EventDTO.java @@ -80,7 +80,7 @@ public class EventDTO extends EventBaseDTO implements SecuredDTO { return leaderboardGroups; } - public Iterable getLeaderboardGroupIds() { + public List getLeaderboardGroupIds() { final List updatedEventLeaderboardGroupIds = new ArrayList<>(); for (LeaderboardGroupDTO leaderboardGroup : this.getLeaderboardGroups()) { updatedEventLeaderboardGroupIds.add(leaderboardGroup.getId()); @@ -106,10 +106,10 @@ public class EventDTO extends EventBaseDTO implements SecuredDTO { * * @return always a valid {@link Iterable} which may, though, be empty */ - public Iterable getWindFinderReviewedSpotsCollectionIds() { - final Iterable result; + public List getWindFinderReviewedSpotsCollectionIds() { + final List result; if (windFinderReviewedSpotsCollectionIds == null) { - result = Collections.emptySet(); + result = Collections.emptyList(); } else { result = windFinderReviewedSpotsCollectionIds; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LeaderboardGroupBaseDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LeaderboardGroupBaseDTO.java index 3875c855f43..9bee4b6bf0d 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LeaderboardGroupBaseDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LeaderboardGroupBaseDTO.java @@ -14,7 +14,7 @@ public class LeaderboardGroupBaseDTO extends NamedSecuredObjectDTO implements Wi private static final long serialVersionUID = -4276452763988957L; private UUID id; - public String description; + private String description; private String displayName; private boolean hasOverallLeaderboard; @@ -66,4 +66,11 @@ public class LeaderboardGroupBaseDTO extends NamedSecuredObjectDTO implements Wi return new TypeRelativeObjectIdentifier(id.toString()); } + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LeaderboardGroupDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LeaderboardGroupDTO.java index 4a8e9884342..1036e9e1aae 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LeaderboardGroupDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/LeaderboardGroupDTO.java @@ -55,12 +55,10 @@ public class LeaderboardGroupDTO extends LeaderboardGroupBaseDTO { * Creates a new LeaderboardGroupDTO with the given parameters as attributes.
    * All parameters can be null but then the attributes will also be null.
    * The additional data (start dates and places for the races) will be initialized but empty. - * @param displayName TODO */ private LeaderboardGroupDTO(UUID id, String name, String description, String displayName, List leaderboards) { - super(id, name, displayName); + super(id, name, description, displayName, /* hasOverallLeaderboard */ false); currentServerTime = new Date(); - this.description = description; this.leaderboards = leaderboards; } @@ -169,7 +167,7 @@ public class LeaderboardGroupDTO extends LeaderboardGroupBaseDTO { public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((getDescription() == null) ? 0 : getDescription().hashCode()); result = prime * result + ((leaderboards == null) ? 0 : leaderboards.hashCode()); return result; } @@ -183,10 +181,10 @@ public class LeaderboardGroupDTO extends LeaderboardGroupBaseDTO { if (getClass() != obj.getClass()) return false; LeaderboardGroupDTO other = (LeaderboardGroupDTO) obj; - if (description == null) { - if (other.description != null) + if (getDescription() == null) { + if (other.getDescription() != null) return false; - } else if (!description.equals(other.description)) + } else if (!getDescription().equals(other.getDescription())) return false; if (leaderboards == null) { if (other.leaderboards != null) diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/MarkDTO.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/MarkDTO.java index 91b092581a9..797d435cb43 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/MarkDTO.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/shared/MarkDTO.java @@ -14,14 +14,12 @@ public class MarkDTO extends ControlPointDTO implements MappableToDevice { public Color color; public String shape; public String pattern; - public String shortName; public MarkType type; MarkDTO() {} public MarkDTO(String idAsString, String name, String shortName, double latDeg, double lngDeg) { super(idAsString, name, shortName); - this.shortName = shortName; this.position = new DegreePosition(latDeg, lngDeg); } @@ -43,10 +41,6 @@ public class MarkDTO extends ControlPointDTO implements MappableToDevice { return false; } - public String getShortName() { - return shortName; - } - @Override public int hashCode() { return getIdAsString().hashCode(); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/SimulatorEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/SimulatorEntryPoint.java index 3183e0f3a0f..d8b1421ca53 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/SimulatorEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/simulator/SimulatorEntryPoint.java @@ -11,7 +11,7 @@ import com.google.gwt.user.client.ui.RootLayoutPanel; import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.gwt.common.authentication.FixedSailingAuthentication; import com.sap.sailing.gwt.common.authentication.SAPSailingHeaderWithAuthentication; -import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint; +import com.sap.sailing.gwt.ui.client.AbstractSailingReadEntryPoint; import com.sap.sailing.gwt.ui.client.RemoteServiceMappingConstants; import com.sap.sailing.gwt.ui.client.SimulatorService; import com.sap.sailing.gwt.ui.client.SimulatorServiceAsync; @@ -23,7 +23,7 @@ import com.sap.sse.security.ui.authentication.decorator.WidgetFactory; import com.sap.sse.security.ui.authentication.generic.GenericAuthentication; import com.sap.sse.security.ui.authentication.generic.GenericAuthorizedContentDecorator; -public class SimulatorEntryPoint extends AbstractSailingEntryPoint { +public class SimulatorEntryPoint extends AbstractSailingReadEntryPoint { private final SimulatorServiceAsync simulatorService = GWT.create(SimulatorService.class); private int xRes = 40; diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/spectator/LeaderboardGroupOverviewPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/spectator/LeaderboardGroupOverviewPanel.java index 65d62708b71..4f39146a01d 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/spectator/LeaderboardGroupOverviewPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/spectator/LeaderboardGroupOverviewPanel.java @@ -548,7 +548,7 @@ public class LeaderboardGroupOverviewPanel extends FormPanel { } private void fillGroupDetails(LeaderboardGroupDTO group) { - groupDescriptionHTML.setHTML(new SafeHtmlBuilder().appendEscapedLines(group.description).toSafeHtml()); + groupDescriptionHTML.setHTML(new SafeHtmlBuilder().appendEscapedLines(group.getDescription()).toSafeHtml()); leaderboardsDataProvider.getList().clear(); leaderboardsDataProvider.getList().addAll(group.leaderboards); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/spectator/LeaderboardGroupPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/spectator/LeaderboardGroupPanel.java index de203583dcd..2a682d12bb3 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/spectator/LeaderboardGroupPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/spectator/LeaderboardGroupPanel.java @@ -189,7 +189,7 @@ public class LeaderboardGroupPanel extends SimplePanel implements HasWelcomeWidg groupNameLabel.setStyleName(STYLE_NAME_PREFIX + "GroupName"); mainPanel.add(groupNameLabel); // Using HTML to display the line breaks in the description - HTML leaderboardGroupDescriptionLabel = new HTML(new SafeHtmlBuilder().appendEscapedLines(leaderboardGroup.description).toSafeHtml()); + HTML leaderboardGroupDescriptionLabel = new HTML(new SafeHtmlBuilder().appendEscapedLines(leaderboardGroup.getDescription()).toSafeHtml()); leaderboardGroupDescriptionLabel.setStyleName(STYLE_NAME_PREFIX + "GroupDescription"); mainPanel.add(leaderboardGroupDescriptionLabel); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/spectator/SpectatorEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/spectator/SpectatorEntryPoint.java index 7977aaa8c9c..f59bb89866e 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/spectator/SpectatorEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/spectator/SpectatorEntryPoint.java @@ -13,7 +13,7 @@ import com.sap.sailing.gwt.common.authentication.FixedSailingAuthentication; import com.sap.sailing.gwt.common.authentication.SAPSailingHeaderWithAuthentication; import com.sap.sailing.gwt.settings.client.spectator.SpectatorContextDefinition; import com.sap.sailing.gwt.settings.client.spectator.SpectatorSettings; -import com.sap.sailing.gwt.ui.client.AbstractSailingEntryPoint; +import com.sap.sailing.gwt.ui.client.AbstractSailingReadEntryPoint; import com.sap.sailing.gwt.ui.client.RegattaRefresher; import com.sap.sailing.gwt.ui.client.shared.panels.SimpleWelcomeWidget; import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO; @@ -25,7 +25,7 @@ import com.sap.sse.gwt.shared.ClientConfiguration; * @author Lennart Hensler (D054527) * */ -public class SpectatorEntryPoint extends AbstractSailingEntryPoint implements RegattaRefresher { +public class SpectatorEntryPoint extends AbstractSailingReadEntryPoint implements RegattaRefresher { @Override protected void doOnModuleLoad() { @@ -57,7 +57,7 @@ public class SpectatorEntryPoint extends AbstractSailingEntryPoint implements Re FlowPanel groupOverviewPanel = new FlowPanel(); groupOverviewPanel.addStyleName("contentOuterPanel"); // DON'T DELETE -> the EventOverviewPanel will replace the LeaderboardGroupOverviewPanel later on -// EventOverviewPanel eventOverviewPanel = new EventOverviewPanel(sailingService, this, stringMessages, showRaceDetails); +// EventOverviewPanel eventOverviewPanel = new EventOverviewPanel(sailingServiceWrite, this, stringMessages, showRaceDetails); // groupOverviewPanel.add( eventOverviewPanel); LeaderboardGroupOverviewPanel leaderboardGroupOverviewPanel = new LeaderboardGroupOverviewPanel(getSailingService(), this, getStringMessages(), settings.isShowRaceDetails()); groupOverviewPanel.add(leaderboardGroupOverviewPanel); diff --git a/java/com.sap.sailing.kiworesultimport/src/com/sap/sailing/kiworesultimport/impl/StartImpl.java b/java/com.sap.sailing.kiworesultimport/src/com/sap/sailing/kiworesultimport/impl/StartImpl.java index 7f6fa78d1c9..0dde7117388 100755 --- a/java/com.sap.sailing.kiworesultimport/src/com/sap/sailing/kiworesultimport/impl/StartImpl.java +++ b/java/com.sap.sailing.kiworesultimport/src/com/sap/sailing/kiworesultimport/impl/StartImpl.java @@ -46,7 +46,9 @@ public class StartImpl extends AbstractNodeWrapper implements Start { @Override public TimePoint getTimePoint() throws ParseException { - return new MillisecondsTimePoint(df.parse(getStartTimeAsString())); + synchronized (df) { + return new MillisecondsTimePoint(df.parse(getStartTimeAsString())); + } } @Override diff --git a/java/com.sap.sailing.kiworesultimport/src/com/sap/sailing/kiworesultimport/impl/StartReportImpl.java b/java/com.sap.sailing.kiworesultimport/src/com/sap/sailing/kiworesultimport/impl/StartReportImpl.java index 99b440f8f18..eceff91384f 100755 --- a/java/com.sap.sailing.kiworesultimport/src/com/sap/sailing/kiworesultimport/impl/StartReportImpl.java +++ b/java/com.sap.sailing.kiworesultimport/src/com/sap/sailing/kiworesultimport/impl/StartReportImpl.java @@ -38,7 +38,9 @@ public class StartReportImpl extends AbstractNodeWrapper implements StartReport @Override public TimePoint getTimePoint() throws ParseException { String datum = getDateAsString(); - return datum == null || datum.trim().length() == 0 ? null : new MillisecondsTimePoint(df.parse(datum)); + synchronized (df) { + return datum == null || datum.trim().length() == 0 ? null : new MillisecondsTimePoint(df.parse(datum)); + } } @Override diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java index 436a8660a94..425d39a54d5 100644 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/StoreAndLoadCompetitorsTest.java @@ -1,6 +1,7 @@ package com.sap.sailing.mongodb.test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import java.io.Serializable; import java.net.URI; @@ -120,18 +121,29 @@ public class StoreAndLoadCompetitorsTest extends AbstractMongoDBTest { assertEquals(competitorShortName2, loadedCompetitor.getShortName()); } + @Test + public void testCompetitorDoesNotAcceptInfiniteTimeOnTimeFactor() { + final DynamicCompetitor c = (DynamicCompetitor) createCompetitor("Hasso", UUID.randomUUID()); + final double infinity = 100./0.; + try { + c.setTimeOnTimeFactor(infinity); // see how we handle a 0 Yardstick number; see bug 5297 + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // expected + } + } + @Test public void testStoreAndUpdateCompetitorWithUUIDAsId() { MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); dropCompetitorAndBoatsCollection(); - DynamicCompetitor c = (DynamicCompetitor) createCompetitor("Hasso", UUID.randomUUID()); mongoObjectFactory.storeCompetitor(c); assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors())); c.setName("Hasso Plattner"); - mongoObjectFactory.storeCompetitor(c); - assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors())); + final Collection reloadedCompetitors = domainObjectFactory.loadAllCompetitors(); + assertEquals(1, reloadedCompetitors.size()); } @Test @@ -139,11 +151,9 @@ public class StoreAndLoadCompetitorsTest extends AbstractMongoDBTest { MongoObjectFactory mongoObjectFactory = PersistenceFactory.INSTANCE.getMongoObjectFactory(getMongoService()); DomainObjectFactory domainObjectFactory = PersistenceFactory.INSTANCE.getDomainObjectFactory(getMongoService(), domainFactory); dropCompetitorAndBoatsCollection(); - DynamicCompetitor c = (DynamicCompetitor) createCompetitor("Hasso"); mongoObjectFactory.storeCompetitor(c); assertEquals(1, Util.size(domainObjectFactory.loadAllCompetitors())); - mongoObjectFactory.removeCompetitor(c); assertEquals(0, Util.size(domainObjectFactory.loadAllCompetitors())); } diff --git a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java index 60545577ed4..c9a98c449e4 100755 --- a/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java +++ b/java/com.sap.sailing.mongodb.test/src/com/sap/sailing/mongodb/test/TestStoringAndRetrievingLeaderboardGroups.java @@ -400,23 +400,18 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe public void testGetLeaderboardsNotInGroup() { final String[] leaderboardNames = {"Leaderboard 0", "Leaderboard 1"}; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - final String groupName = "Leaderboard Group"; final String groupDescription = "A leaderboard group"; final ArrayList leaderboards = new ArrayList<>(); - Leaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); leaderboards.add(leaderboard); leaderboard = new FlexibleLeaderboardImpl(leaderboardNames[1], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); leaderboards.add(leaderboard); - final LeaderboardGroup leaderboardGroup = new LeaderboardGroupImpl(groupName, groupDescription, /* displayName */ null, false, leaderboards); mongoObjectFactory.storeLeaderboardGroup(leaderboardGroup); - final String[] ungroupedLeaderboardNames = {"Ungrouped Leaderboard 0", "Ungrouped Leaderboard 1", "Ungrouped Leaderboard 2"}; - final FlexibleLeaderboard[] ungroupedLeaderboards = { new FlexibleLeaderboardImpl(ungroupedLeaderboardNames[0], new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null), @@ -427,12 +422,9 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[0]); mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[1]); mongoObjectFactory.storeLeaderboard(ungroupedLeaderboards[2]); - Iterable loadedUngroupedLeaderboards = domainObjectFactory.getLeaderboardsNotInGroup(/* regattaRegistry */ null, /* leaderboardRegistry */ null); - Assert.assertTrue(loadedUngroupedLeaderboards.iterator().hasNext()); - int c = 0; for (int i = 0; i < ungroupedLeaderboardNames.length; i++) { boolean loadedBoardsContainsName = false; @@ -445,50 +437,35 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe } Assert.assertTrue(loadedBoardsContainsName); } - Assert.assertTrue(c == ungroupedLeaderboards.length); } @Test public void testLeaderboardReferenceBreak() { - //Set up + // Set up final String leaderboardName = "Leaderboard 0"; final String columnName = "Column"; final int[] discardIndexResultsStartingWithHowManyRaces = new int[] { 5, 8 }; - final String groupName = "Leaderboard Group"; final String groupDescription = "A leaderboard group"; final ArrayList leaderboards = new ArrayList<>(); - final FlexibleLeaderboard leaderboard = new FlexibleLeaderboardImpl(leaderboardName, new ThresholdBasedResultDiscardingRuleImpl(discardIndexResultsStartingWithHowManyRaces), new LowPoint(), null); final Fleet fleet = leaderboard.getFleet(null); final RaceColumn race = leaderboard.addRaceColumn(columnName, false); leaderboards.add(leaderboard); - final LeaderboardGroup group = new LeaderboardGroupImpl(groupName, groupDescription, /* displayName */ null, false, leaderboards); mongoObjectFactory.storeLeaderboardGroup(group); - - //Name change test - final String newLeaderboardName = "Leaderboard ChangedName"; - mongoObjectFactory.renameLeaderboard(leaderboardName, newLeaderboardName); - leaderboard.setName(newLeaderboardName); - LeaderboardGroup loadedGroup = domainObjectFactory.loadLeaderboardGroup(groupName, /* regattaRegistry */ null, /* leaderboardRegistry */ null); - String loadedLeaderboardName = loadedGroup.getLeaderboards().iterator().next().getName(); - Assert.assertEquals(newLeaderboardName, loadedLeaderboardName); - - //RaceIdentifier change test + // RaceIdentifier change test final String regattaName = "Event"; final String raceName = "Race"; leaderboard.getRaceColumnByName(columnName).setRaceIdentifier(fleet, new RegattaNameAndRaceName(regattaName, raceName)); mongoObjectFactory.storeLeaderboard(leaderboard); - - //Check if the leaderboard updated correctly + // Check if the leaderboard updated correctly final Leaderboard loadedLeaderboard = domainObjectFactory.loadLeaderboard(leaderboard.getName(), /* regattaRegistry */ null, /* leaderboardRegistry */ null); final RaceColumn loadedRaceColumnByName = loadedLeaderboard.getRaceColumnByName(columnName); Fleet loadedFleet = loadedRaceColumnByName.getFleetByName(fleet.getName()); Assert.assertEquals(race.getRaceIdentifier(fleet), loadedRaceColumnByName.getRaceIdentifier(loadedFleet)); - // Check if the group received the changes loadedGroup = domainObjectFactory.loadLeaderboardGroup(groupName, /* regattaRegistry */ null, /* leaderboardRegistry */ null); final RaceColumn loadedRaceColumnFromGroupByName = loadedGroup.getLeaderboards().iterator().next().getRaceColumnByName(columnName); @@ -496,5 +473,4 @@ public class TestStoringAndRetrievingLeaderboardGroups extends AbstractMongoDBTe RaceIdentifier loadedIdentifier = loadedRaceColumnFromGroupByName.getRaceIdentifier(loadedGroupFleet); Assert.assertEquals(race.getRaceIdentifier(fleet), loadedIdentifier); } - } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/coursetemplate/DeviceMapping.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/coursetemplate/DeviceMapping.java index c66fa1daaca..80cbd44b469 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/coursetemplate/DeviceMapping.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/coursetemplate/DeviceMapping.java @@ -2,6 +2,8 @@ package com.sap.sailing.selenium.api.coursetemplate; import org.json.simple.JSONObject; +import com.sap.sailing.domain.common.Position; +import com.sap.sailing.domain.common.impl.DegreePosition; import com.sap.sailing.selenium.api.core.JsonWrapper; import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.MillisecondsTimePoint; @@ -11,11 +13,14 @@ public class DeviceMapping extends JsonWrapper { public static final String FIELD_TRACKING_DEVICE_HASH = "trackingDeviceHash"; public static final String FIELD_MAPPED_FROM = "trackingDeviceMappedFromMillis"; public static final String FIELD_MAPPED_TO = "trackingDeviceMappedToMillis"; + public static final String FIELD_TRACKING_DEVICE_LAST_KNOWN_POSITION = "trackingDeviceLastKnownPosition"; + private static final String FIELD_LATITUDE_DEG = "lat_deg"; + private static final String FIELD_LONGITUDE_DEG = "lon_deg"; public DeviceMapping(JSONObject json) { super(json); } - + public String getHash() { return get(FIELD_TRACKING_DEVICE_HASH); } @@ -23,14 +28,22 @@ public class DeviceMapping extends JsonWrapper { public String getType() { return get(FIELD_DEVICE_TYPE); } - + public TimePoint getMappedFrom() { final Number mappedFromMillis = get(FIELD_MAPPED_FROM); return mappedFromMillis == null ? null : new MillisecondsTimePoint(mappedFromMillis.longValue()); } - + public TimePoint getMappedTo() { final Number mappedToMillis = get(FIELD_MAPPED_TO); return mappedToMillis == null ? null : new MillisecondsTimePoint(mappedToMillis.longValue()); } + + public Position getLastKnownPosition() { + final JSONObject positionJson = (JSONObject) get(FIELD_TRACKING_DEVICE_LAST_KNOWN_POSITION); + return positionJson != null + ? new DegreePosition(((Number) positionJson.get(FIELD_LATITUDE_DEG)).doubleValue(), + ((Number) positionJson.get(FIELD_LONGITUDE_DEG)).doubleValue()) + : null; + } } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/PreferencesApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/PreferencesApi.java index 22a01effbf2..e7de56b9d3e 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/PreferencesApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/PreferencesApi.java @@ -8,7 +8,7 @@ import com.sap.sailing.selenium.api.core.ApiContext; public class PreferencesApi { - private static final String PREFERENCES_URL = "/api/v1/preferences/"; + private static final String PREFERENCES_URL = "/api/restsecurity/preferences/"; public JSONObject createPreference(ApiContext ctx, String key, Map value) { JSONObject json = new JSONObject(); diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java index 1483d46e4b5..20b303aa8cd 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/TrackedEventsApi.java @@ -49,19 +49,20 @@ public class TrackedEventsApi { json.put(KEY_EVENT_BASE_URL, eventBaseUrl); final JSONArray elements = new JSONArray(); - for (Triple trackedId : trackedIds) { - final JSONObject elem = new JSONObject(); - elem.put(KEY_TRACKED_ELEMENT_DEVICE_ID, deviceId); - if (trackedId.getA() != null) { - elem.put(KEY_TRACKED_ELEMENT_COMPETITOR_ID, trackedId.getA()); - } else if (trackedId.getB() != null) { - elem.put(KEY_TRACKED_ELEMENT_BOAT_ID, trackedId.getB()); - } else if (trackedId.getC() != null) { - elem.put(KEY_TRACKED_ELEMENT_MARK_ID, trackedId.getC()); + if (trackedIds != null) { + for (Triple trackedId : trackedIds) { + final JSONObject elem = new JSONObject(); + elem.put(KEY_TRACKED_ELEMENT_DEVICE_ID, deviceId); + if (trackedId.getA() != null) { + elem.put(KEY_TRACKED_ELEMENT_COMPETITOR_ID, trackedId.getA()); + } else if (trackedId.getB() != null) { + elem.put(KEY_TRACKED_ELEMENT_BOAT_ID, trackedId.getB()); + } else if (trackedId.getC() != null) { + elem.put(KEY_TRACKED_ELEMENT_MARK_ID, trackedId.getC()); + } + elements.add(elem); } - elements.add(elem); } - json.put(KEY_EVENT_REGATTA_SECRET, regattaSecret); json.put(KEY_EVENT_TRACKED_ELEMENTS, elements); json.put(KEY_EVENT_IS_ARCHIVED, false); diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/UserGroupApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/UserGroupApi.java index 980a7ab3068..02af78a9b78 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/UserGroupApi.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/event/UserGroupApi.java @@ -5,6 +5,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.UUID; +import java.util.stream.Collectors; import org.json.simple.JSONArray; import org.json.simple.JSONObject; @@ -17,11 +18,17 @@ public class UserGroupApi { private static final String KEY_GROUP_NAME = "groupName"; private static final String KEY_GROUP_ID = "groupId"; + private static final String KEY_USER_NAME = "userName"; private static final String KEY_USERS = "users"; private static final String KEY_ROLES = "roles"; private static final String KEY_FOR_ALL = "forAll"; + private static final String KEY_TENANT_GROUP_UUID = "tenantGroup"; + private static final String KEY_READABLE_GROUPS = "readableGroups"; private static final String USERGROUP_URL = "/api/restsecurity/usergroup/"; + private static final String SET_DEFAULT_TENANT_FOR_CURRENT_USER = USERGROUP_URL + + "setDefaultTenantForCurrentServerAndUser"; + private static final String ADD_USER_TO_USERGROUP_URL = USERGROUP_URL + "addAnyUserToGroup"; public UserGroup getUserGroup(ApiContext ctx, UUID groupId) { return new UserGroup(ctx.get(USERGROUP_URL + groupId.toString())); @@ -51,6 +58,18 @@ public class UserGroupApi { ctx.delete(USERGROUP_URL + groupId.toString() + "/user/" + userName); } + public Iterable getReadableGroupsOfUser(ApiContext ctx, String userName) { + final Map queryParams = new HashMap<>(); + queryParams.put(KEY_USER_NAME, userName); + JSONObject result = ctx.get(USERGROUP_URL + "list/readable", queryParams); + return ((JSONArray) result.get(KEY_READABLE_GROUPS)).stream().map(UserGroup::new).collect(Collectors.toList()); + } + + public Iterable getReadableGroupsOfCurrentUser(ApiContext ctx) { + JSONObject result = ctx.get(USERGROUP_URL + "list/readable/"); + return ((JSONArray) result.get(KEY_READABLE_GROUPS)).stream().map(UserGroup::new).collect(Collectors.toList()); + } + public void addRoleToGroup(ApiContext ctx, UUID groupId, UUID roleId, boolean forAll) { final JSONObject jsonBody = new JSONObject(); jsonBody.put(KEY_FOR_ALL, Boolean.toString(forAll)); @@ -61,13 +80,33 @@ public class UserGroupApi { ctx.delete(USERGROUP_URL + groupId.toString() + "/role/" + roleId.toString()); } + public void setDefaultTenantForCurrentServerAndUser(ApiContext ctx, UUID tenantUuid) { + final Map queryParams = new HashMap<>(); + queryParams.put(KEY_TENANT_GROUP_UUID, tenantUuid.toString()); + ctx.post(SET_DEFAULT_TENANT_FOR_CURRENT_USER, queryParams); + } + + public void addUserToUserGroupWithoutPermissionOnUser(ApiContext ctx, String userName, UUID userGroupId) { + final Map queryParams = new HashMap<>(); + queryParams.put(KEY_USER_NAME, userName); + queryParams.put(KEY_GROUP_ID, userGroupId != null ? userGroupId.toString() : null); + ctx.post(ADD_USER_TO_USERGROUP_URL, queryParams); + } + public class UserGroup extends JsonWrapper { public UserGroup(JSONObject json) { super(json); } + public UserGroup(Object object) { + super((JSONObject) object); + } + public UUID getGroupId() { + if (getJson().containsKey("uuid")) { + return UUID.fromString(get("uuid")); + } return UUID.fromString(get(KEY_GROUP_ID)); } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/regatta/Competitor.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/regatta/Competitor.java index c34cfa5a904..8f508292d95 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/regatta/Competitor.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/regatta/Competitor.java @@ -24,6 +24,10 @@ public class Competitor extends JsonWrapper { return get("shortName"); } + public String getColor() { + return get("displayColor"); + } + public String getNationality() { return get("nationality"); } @@ -36,6 +40,18 @@ public class Competitor extends JsonWrapper { return get("nationalityISO3"); } + public String getFlagImageUri() { + return get("flagImageUri"); + } + + public Number getTimeOnTimeFactor() { + return get("timeOnTimeFactor"); + } + + public Number getTimeOnDistanceAllowanceInSecondsPerNauticalMile() { + return get("timeOnDistanceAllowanceInSecondsPerNauticalMile"); + } + public Team getTeam() { return new Team(get("team")); } @@ -51,13 +67,16 @@ public class Competitor extends JsonWrapper { } public String getName() { - return get("name"); + return getJson() != null ? get("name") : null; } public String getNationality() { - return (String) ((JSONObject) get("nationality")).get("IOC"); + return getJson() != null ? (String) ((JSONObject) get("nationality")).get("IOC") : null; } + public String getTeamImageUri() { + return getJson() != null ? get("imageUri") : null; + } } public class Boat extends JsonWrapper { diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/regatta/CompetitorsApi.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/regatta/CompetitorsApi.java new file mode 100644 index 00000000000..db98c4dd100 --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/regatta/CompetitorsApi.java @@ -0,0 +1,23 @@ +package com.sap.sailing.selenium.api.regatta; + +import java.util.Map; +import java.util.UUID; + +import org.json.simple.JSONObject; + +import com.sap.sailing.selenium.api.core.ApiContext; + +public class CompetitorsApi { + + private static final String COMPETITORS = "/api/v1/competitors"; + + public Competitor getCompetitor(ApiContext ctx, UUID competitorId) { + return new Competitor(ctx.get(COMPETITORS + "/" + competitorId.toString())); + } + + public Competitor updateCompetitor(ApiContext ctx, UUID competitorId, Map valuesToUpdate) { + JSONObject body = new JSONObject(); + body.putAll(valuesToUpdate); + return new Competitor(ctx.put(COMPETITORS + "/" + competitorId.toString(), null, body)); + } +} diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/CompetitorApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/CompetitorApiTest.java new file mode 100644 index 00000000000..a16e7d068a3 --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/CompetitorApiTest.java @@ -0,0 +1,156 @@ +package com.sap.sailing.selenium.api.test; + +import static com.sap.sailing.selenium.api.core.ApiContext.SERVER_CONTEXT; +import static com.sap.sailing.selenium.api.core.ApiContext.createAdminApiContext; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.domain.common.CompetitorRegistrationType; +import com.sap.sailing.selenium.api.core.ApiContext; +import com.sap.sailing.selenium.api.event.EventApi; +import com.sap.sailing.selenium.api.regatta.Competitor; +import com.sap.sailing.selenium.api.regatta.CompetitorsApi; +import com.sap.sailing.selenium.api.regatta.RegattaApi; +import com.sap.sailing.selenium.test.AbstractSeleniumTest; + +public class CompetitorApiTest extends AbstractSeleniumTest { + + private static final String EVENT_NAME = "Competitor Test Regatta"; + private static final String BOAT_CLASS = "GC 32"; + private static final String COMPETITOR_NAME = "Donald Duck"; + + private final EventApi eventApi = new EventApi(); + private final RegattaApi regattaApi = new RegattaApi(); + private final CompetitorsApi competitorApi = new CompetitorsApi(); + + private ApiContext adminCtx; + + @Before + public void setUp() { + clearState(getContextRoot()); + super.setUp(); + adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); + eventApi.createEvent(adminCtx, EVENT_NAME, BOAT_CLASS, CompetitorRegistrationType.CLOSED, "Some special place"); + } + + @Test + public void testGetCompetitorWithOldSerializer() { + final Competitor competitor = regattaApi.createAndAddCompetitor(adminCtx, EVENT_NAME, BOAT_CLASS, "test@test", + COMPETITOR_NAME, "USA"); + final Competitor competitorReloaded = competitorApi.getCompetitor(adminCtx, competitor.getId()); + assertEquals(competitor.getId(), competitorReloaded.getId()); + assertEquals(competitor.getName(), competitorReloaded.getName()); + assertEquals(competitor.getNationality(), competitorReloaded.getNationality()); + assertEquals(competitor.getColor(), competitorReloaded.getColor()); + assertEquals(competitor.getFlagImageUri(), competitorReloaded.getFlagImageUri()); + assertEquals(competitor.getTeam().getTeamImageUri(), competitorReloaded.getTeam().getTeamImageUri()); + assertEquals(competitor.getShortName(), competitorReloaded.getShortName()); + assertEquals(competitor.getTimeOnTimeFactor(), competitorReloaded.getTimeOnTimeFactor()); + assertEquals(competitor.getTimeOnDistanceAllowanceInSecondsPerNauticalMile(), + competitorReloaded.getTimeOnDistanceAllowanceInSecondsPerNauticalMile()); + assertEquals(competitor.getNationalityISO2(), competitorReloaded.get("countryCode")); + assertEquals(competitor.getColor(), competitorReloaded.get("color")); + assertEquals(competitor.getFlagImageUri(), competitorReloaded.get("flagImage")); + assertEquals(competitor.getTeam().getTeamImageUri(), competitorReloaded.get("teamImageUri")); + } + + @Test + public void testUpdateCompetitor() { + final Competitor competitor = regattaApi.createAndAddCompetitor(adminCtx, EVENT_NAME, BOAT_CLASS, "test@test", + COMPETITOR_NAME, "USA"); + Competitor competitorU1 = competitorApi.updateCompetitor(adminCtx, competitor.getId(), + mapOf("displayColor", "#ABCDEF")); + assertEquals(competitor.getId(), competitorU1.getId()); + assertEquals("#ABCDEF", competitorU1.getColor()); + assertEquals(competitor.getName(), competitorU1.getName()); + Competitor competitorU2 = competitorApi.updateCompetitor(adminCtx, competitor.getId(), + mapOf("name", "Dagobert", "shortName", "D")); + assertEquals("#ABCDEF", competitorU2.getColor()); + assertEquals("Dagobert", competitorU2.getName()); + assertEquals("D", competitorU2.getShortName()); + Competitor competitorU3 = competitorApi.updateCompetitor(adminCtx, competitor.getId(), mapOf("nationality", + "GER", "flagImageUri", "http://flagimage.url", "teamImageUri", "http://teamimage.url")); + assertEquals("#ABCDEF", competitorU3.getColor()); + assertEquals("Dagobert", competitorU3.getName()); + assertEquals("D", competitorU2.getShortName()); + assertEquals("GER", competitorU3.getNationality()); + assertEquals("http://flagimage.url", competitorU3.getFlagImageUri()); + assertEquals("http://teamimage.url", competitorU3.getTeam().getTeamImageUri()); + Competitor competitorU4 = competitorApi.updateCompetitor(adminCtx, competitor.getId(), + mapOf("timeOnTimeFactor", 2.4, "timeOnDistanceAllowanceInSecondsPerNauticalMile", 10000)); + assertEquals("#ABCDEF", competitorU4.getColor()); + assertEquals("Dagobert", competitorU4.getName()); + assertEquals("D", competitorU2.getShortName()); + assertEquals("GER", competitorU4.getNationality()); + assertEquals("http://flagimage.url", competitorU4.getFlagImageUri()); + assertEquals("http://teamimage.url", competitorU4.getTeam().getTeamImageUri()); + assertEquals(2.4, competitorU4.getTimeOnTimeFactor()); + assertEquals(10000.0, competitorU4.getTimeOnDistanceAllowanceInSecondsPerNauticalMile()); + Competitor competitorU5 = competitorApi.updateCompetitor(adminCtx, competitor.getId(), + mapOf("searchTag", "atag")); + assertEquals("#ABCDEF", competitorU5.getColor()); + assertEquals("Dagobert", competitorU5.getName()); + assertEquals("D", competitorU2.getShortName()); + assertEquals("GER", competitorU5.getNationality()); + assertEquals("http://flagimage.url", competitorU5.getFlagImageUri()); + assertEquals("http://teamimage.url", competitorU5.getTeam().getTeamImageUri()); + assertEquals(2.4, competitorU5.getTimeOnTimeFactor()); + assertEquals(10000.0, competitorU5.getTimeOnDistanceAllowanceInSecondsPerNauticalMile()); + // check final state by reloading competitor + Competitor competitorReloaded = competitorApi.getCompetitor(adminCtx, competitor.getId()); + assertEquals("#ABCDEF", competitorReloaded.getColor()); + assertEquals("Dagobert", competitorReloaded.getName()); + assertEquals("D", competitorReloaded.getShortName()); + assertEquals("GER", competitorReloaded.getNationality()); + assertEquals("http://flagimage.url", competitorReloaded.getFlagImageUri()); + assertEquals("http://teamimage.url", competitorReloaded.getTeam().getTeamImageUri()); + assertEquals(2.4, competitorReloaded.getTimeOnTimeFactor()); + assertEquals(10000.0, competitorU5.getTimeOnDistanceAllowanceInSecondsPerNauticalMile()); + } + + @Test + public void testUpdateCompetitorValuesToNull() { + final Competitor competitor = regattaApi.createAndAddCompetitor(adminCtx, EVENT_NAME, BOAT_CLASS, "test@test", + COMPETITOR_NAME, "USA"); + Competitor competitorU1 = competitorApi.updateCompetitor(adminCtx, competitor.getId(), + mapOf("name", "Dagobert", "shortName", "D", "email", "test@test2", "nationality", "GER", "flagImageUri", + "http://flagimage.url", "teamImageUri", "http://teamimage.url", "timeOnTimeFactor", 2.4, "displayColor", "#ABCDEF", + "timeOnDistanceAllowanceInSecondsPerNauticalMile", 10000, "searchTag", "atag")); + assertNotNull(competitorU1.getName()); + assertNotNull(competitorU1.getShortName()); + assertNotNull(competitorU1.getFlagImageUri()); + assertNotNull(competitorU1.getTeam().getTeamImageUri()); + assertNotNull(competitorU1.getNationality()); + assertNotNull(competitorU1.getTimeOnTimeFactor()); + assertNotNull(competitorU1.getTimeOnDistanceAllowanceInSecondsPerNauticalMile()); + assertNotNull(competitorU1.getColor()); + Competitor competitorU2 = competitorApi.updateCompetitor(adminCtx, competitor.getId(), + mapOf("name", null, "shortName", null, "email", null, "nationality", null, "flagImageUri", null, + "teamImageUri", null, "timeOnTimeFactor", null, "displayColor", null, + "timeOnDistanceAllowanceInSecondsPerNauticalMile", null, "searchTag", null)); + assertNull(competitorU2.getName()); + assertNull(competitorU2.getShortName()); + assertNull(competitorU2.getFlagImageUri()); + assertNull(competitorU2.getTeam().getTeamImageUri()); + assertNull(competitorU2.getTimeOnTimeFactor()); + assertNull(competitorU2.getTimeOnDistanceAllowanceInSecondsPerNauticalMile()); + assertNull(competitorU2.getColor()); + } + + private Map mapOf(Object... args) { + assertTrue(args.length % 2 == 0); + Map map = new HashMap<>(); + for (int i = 0; i < args.length; i += 2) { + map.put((String) args[i], args[i + 1]); + } + return map; + } +} diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/CourseConfigurationTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/CourseConfigurationTest.java index 62856c1e3a9..b3ca56274c9 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/CourseConfigurationTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/CourseConfigurationTest.java @@ -26,6 +26,7 @@ import java.util.concurrent.atomic.LongAdder; import java.util.logging.Logger; import java.util.stream.Collectors; +import org.json.JSONException; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -335,17 +336,49 @@ public class CourseConfigurationTest extends AbstractSeleniumTest { } @Test - public void testCreateCourseWithLessNoOfLapsThanRepeatableParts() { - createCourseFromTemplateBasedCourseConfiguration(10, 8, 1, 3); + public void testCreateCourseWithLessNoOfLapsThanRepeatablePartOccurences() { + createCourseFromTemplateBasedCourseConfiguration(/* numberOfLaps */ 10, /* numberOfLapsForCOurse */ 8, + /* repeatable part start */ 1, /* repeatable part end */ 3, true); } @Test - public void testCreateCourseWithMoreNoOfLapsThanRepeatableParts() { + public void testCreateCourseWithMoreNoOfLapsThanRepeatablePartOccurences() { + final int numberOfLaps = 2; + final int numberOfLapsForCourse = 50; + final int repeatablePartStart = 1; + final int repeatablePartEnd = 3; + final int repeatablePartLength = repeatablePartEnd - repeatablePartStart; final Pair result = createCourseFromTemplateBasedCourseConfiguration( - 10, 12, 1, 3); - logger.info(result.getA().getJson().toJSONString()); - logger.info(result.getB().getJson().toJSONString()); - // todo check the fill up + numberOfLaps, numberOfLapsForCourse, repeatablePartStart, repeatablePartEnd, true); + // get repeatable part sequence from template configuration + List repeatablePartWpsA = new ArrayList<>( + repeatablePartEnd - repeatablePartStart); + for (int i = repeatablePartStart; i < repeatablePartEnd; i++) { + repeatablePartWpsA.add(Util.get(result.getA().getWaypoints(), i)); + } + // compare each waypoint of the course configuration against the repeatable part of the template configuration + for (int lap = numberOfLaps; lap < numberOfLapsForCourse; lap++) { + for (int i = repeatablePartStart; i < repeatablePartEnd; i++) { + final WaypointWithMarkConfiguration wpA = repeatablePartWpsA.get(i - repeatablePartStart); + final WaypointWithMarkConfiguration wpB = Util.get(result.getB().getWaypoints(), + (lap - 1) * repeatablePartLength + i); + assertEquals(wpA.getPassingInstruction(), wpB.getPassingInstruction()); + assertEquals(Util.get(Util.get(result.getB().getWaypoints(), i).getMarkConfigurationIds(), 0), + Util.get(wpB.getMarkConfigurationIds(), 0)); + } + } + } + + @Test + public void testCreateCourseLineup() { + createCourseFromTemplateBasedCourseConfiguration(/* numberOfLaps */ 2, /* numberOfLapsForCourse */ 2, + /* repeatable part start */ 0, /* repeatable part end */ 1, /* strict */ true); + createCourseFromTemplateBasedCourseConfiguration(/* numberOfLaps */ 2, /* numberOfLapsForCourse */ 1, + /* repeatable part start */ 0, /* repeatable part end */ 5, true); + createCourseFromTemplateBasedCourseConfiguration(/* numberOfLaps */ 10, /* numberOfLapsForCourse */ 1, + /* repeatable part start */ 0, /* repeatable part end */ 5, true); + createCourseFromTemplateBasedCourseConfiguration(/* numberOfLaps */ 10000, /* numberOfLapsForCourse */ 20000, + /* repeatable part start */ 0, /* repeatable part end */ 5, true); } /** @@ -362,12 +395,14 @@ public class CourseConfigurationTest extends AbstractSeleniumTest { * start index of repeatable part * @param zeroBasedIndexOfRepeatablePartEnd * end index of repeatable part + * @param strict + * if false, no asserts are checked * @return Pair of (A) source course configuration based on the template and (B) the result course configuration of * the created regatta course */ private Pair createCourseFromTemplateBasedCourseConfiguration( final int numberOfLaps, final int numberOfLapsForCourse, final int zeroBasedIndexOfRepeatablePartStart, - final int zeroBasedIndexOfRepeatablePartEnd) { + final int zeroBasedIndexOfRepeatablePartEnd, final boolean strict) { final CourseTemplateDataFactory ctdf = new CourseTemplateDataFactory(sharedServerCtx); final CourseTemplate template = courseTemplateApi.createCourseTemplate(sharedServerCtx, ctdf.constructCourseTemplate( @@ -377,34 +412,119 @@ public class CourseConfigurationTest extends AbstractSeleniumTest { final CourseConfiguration courseConfiguration = courseConfigurationApi .createCourseConfigurationFromCourseTemplate(ctx, template.getId(), /* optionalRegattaName */ null, /* tags */ null, /* optional number of laps */ null); - assertEquals(courseConfiguration.getRepeatablePart().getZeroBasedIndexOfRepeatablePartStart().intValue(), - zeroBasedIndexOfRepeatablePartStart); - assertEquals(courseConfiguration.getRepeatablePart().getZeroBasedIndexOfRepeatablePartEnd().intValue(), - zeroBasedIndexOfRepeatablePartEnd); + if (strict) { + assertEquals(courseConfiguration.getRepeatablePart().getZeroBasedIndexOfRepeatablePartStart().intValue(), + zeroBasedIndexOfRepeatablePartStart); + assertEquals(courseConfiguration.getRepeatablePart().getZeroBasedIndexOfRepeatablePartEnd().intValue(), + zeroBasedIndexOfRepeatablePartEnd); + final int expectedNumberOfWaypoints = (numberOfLaps - 1) + * (zeroBasedIndexOfRepeatablePartEnd - zeroBasedIndexOfRepeatablePartStart) + + Util.size(template.getWaypoints()) + - (zeroBasedIndexOfRepeatablePartEnd - zeroBasedIndexOfRepeatablePartStart); + assertEquals(expectedNumberOfWaypoints, Util.size(courseConfiguration.getWaypoints())); + } - final int expectedNumberOfWaypoints = numberOfLaps - * (zeroBasedIndexOfRepeatablePartEnd - zeroBasedIndexOfRepeatablePartStart) - + Util.size(template.getWaypoints()) - zeroBasedIndexOfRepeatablePartEnd - - zeroBasedIndexOfRepeatablePartStart; - assertEquals(expectedNumberOfWaypoints, Util.size(courseConfiguration.getWaypoints())); - - // reduce number of laps in the course configuration an create a course out of it + // set number of laps in the course configuration an create a course out of it courseConfiguration.setNumberOfLaps(numberOfLapsForCourse); - final String regattaName = "test"; + final String regattaName = UUID.randomUUID().toString(); eventApi.createEvent(ctx, regattaName, "", CompetitorRegistrationType.CLOSED, ""); final RaceColumn race = regattaApi.addRaceColumn(ctx, regattaName, null, 1)[0]; - final CourseConfiguration course = courseConfigurationApi.createCourse(ctx, courseConfiguration, "test", + final CourseConfiguration course = courseConfigurationApi.createCourse(ctx, courseConfiguration, regattaName, race.getRaceName(), "Default"); - - final int expectedNumberOfWaypointsOfCourse = numberOfLapsForCourse - * (zeroBasedIndexOfRepeatablePartEnd - zeroBasedIndexOfRepeatablePartStart) - + Util.size(template.getWaypoints()) - zeroBasedIndexOfRepeatablePartEnd - - zeroBasedIndexOfRepeatablePartStart; - assertEquals(expectedNumberOfWaypointsOfCourse, Util.size(course.getWaypoints())); + if (strict) { + final int expectedNumberOfWaypointsOfCourse = (numberOfLapsForCourse - 1) + * (zeroBasedIndexOfRepeatablePartEnd - zeroBasedIndexOfRepeatablePartStart) + + Util.size(template.getWaypoints()) + - (zeroBasedIndexOfRepeatablePartEnd - zeroBasedIndexOfRepeatablePartStart); + assertEquals(expectedNumberOfWaypointsOfCourse, Util.size(course.getWaypoints())); + } return new Pair<>(courseConfiguration, course); } - @Test @Ignore + @Test + public void testMarkPropertiesWithPositioning() throws JSONException { + final double MP_LAT_DEG = 49.097487; + final double MP_LNG_DEG = 8.648631; + final MarkProperties mp1 = markPropertiesApi.createMarkProperties(sharedServerCtx, "mpWithPos", "mpWithPos", + /* deviceUuid */ null, "#ffffff", "shape", "pattern", MarkType.LANDMARK.name(), + /* tags */ Collections.emptyList(), MP_LAT_DEG, MP_LNG_DEG); + assertEquals(MP_LAT_DEG, mp1.getLatDeg().doubleValue(), .1); + assertEquals(MP_LNG_DEG, mp1.getLonDeg().doubleValue(), .1); + final MarkConfiguration mc1 = MarkConfiguration.createMarkPropertiesBased(mp1.getId(), + markRoleApi.createMarkRole(sharedServerCtx, "role_mc1_1", /* shortName */ null).getId()); + final WaypointWithMarkConfiguration wp1 = new WaypointWithMarkConfiguration("landmark", "landmark", + PassingInstruction.Single_Unknown, Arrays.asList(mc1.getId())); + final CourseConfiguration courseConfiguration = new CourseConfiguration("test1", Arrays.asList(mc1), + Arrays.asList(wp1)); + final String regattaName = "Regatta1"; + eventApi.createEvent(ctx, regattaName, "", CompetitorRegistrationType.CLOSED, ""); + final RaceColumn race = regattaApi.addRaceColumn(ctx, regattaName, null, 1)[0]; + final CourseConfiguration course = courseConfigurationApi.createCourse(ctx, courseConfiguration, regattaName, + race.getRaceName(), "Default"); + final MarkConfiguration mc1_1 = course.getMarkConfigurationByEffectiveName("mpWithPos"); + assertEquals(MP_LAT_DEG, mc1_1.getLastKnownPosition().getLatDeg(), .1); + assertEquals(MP_LNG_DEG, mc1_1.getLastKnownPosition().getLngDeg(), .1); + for (final DeviceMapping dm : mc1_1.getDeviceMappings()) { + boolean hasPingDevice = false; + if ("PING".equals(dm.getType())) { + hasPingDevice = true; + assertEquals(MP_LAT_DEG, dm.getLastKnownPosition().getLatDeg(), .1); + assertEquals(MP_LNG_DEG, dm.getLastKnownPosition().getLngDeg(), .1); + } + assertTrue(hasPingDevice); + } + } + + @Test + public void testMarkPropertiesWithPositiongWithMarkTemplateUsage() throws JSONException { + final double MP_LAT_DEG = 49.097487; + final double MP_LNG_DEG = 8.648631; + final String regattaName2 = "Regatta2"; + eventApi.createEvent(ctx, regattaName2, "", CompetitorRegistrationType.CLOSED, ""); + final RaceColumn race = regattaApi.addRaceColumn(ctx, regattaName2, null, 1)[0]; + + // Creating a mark configuration based on a new mark template + final MarkTemplate mtb2 = markTemplateApi.createMarkTemplate(sharedServerCtx, "mark template 1", "mt1", + "#FFFFFF", "Cylinder", "Checkered", MarkType.BUOY.name()); + final MarkConfiguration b2 = MarkConfiguration.createMarkTemplateBased(mtb2.getId(), + markRoleApi.createMarkRole(sharedServerCtx, "role_b2", /* shortName */ "mc1").getId()); + b2.setStoreToInventory(true); + + // Creating a new course configuration with the created mark configuration + final WaypointWithMarkConfiguration wp3 = new WaypointWithMarkConfiguration(null, null, + PassingInstruction.Single_Unknown, Arrays.asList(b2.getId())); + final CourseConfiguration courseConfiguration = new CourseConfiguration("my-course", Arrays.asList(b2), + Arrays.asList(wp3)); + + // Creating a course template and set mark properties position + final CourseConfiguration courseTemplate = courseConfigurationApi.createCourseTemplate(ctx, courseConfiguration, + regattaName2); + for (MarkProperties mp : markPropertiesApi.getAllMarkProperties(sharedServerCtx, Collections.emptyList())) { + if (mp.getShortName().equals("mt1")) { + markPropertiesApi.updateMarkPropertiesPositioning(sharedServerCtx, mp.getId(), /* deviceUuid */ null, + MP_LAT_DEG, MP_LNG_DEG); + } + } + + // Creating a course from the course template + final CourseConfiguration course = courseConfigurationApi.createCourse(ctx, courseTemplate, regattaName2, + race.getRaceName(), "Default"); + + final MarkConfiguration mc1_1 = course.getMarkConfigurationByEffectiveName("mark template 1"); + assertEquals(MP_LAT_DEG, mc1_1.getLastKnownPosition().getLatDeg(), .1); + assertEquals(MP_LNG_DEG, mc1_1.getLastKnownPosition().getLngDeg(), .1); + for (final DeviceMapping dm : mc1_1.getDeviceMappings()) { + boolean hasPingDevice = false; + if ("PING".equals(dm.getType())) { + hasPingDevice = true; + assertEquals(MP_LAT_DEG, dm.getLastKnownPosition().getLatDeg(), .1); + assertEquals(MP_LNG_DEG, dm.getLastKnownPosition().getLngDeg(), .1); + } + assertTrue(hasPingDevice); + } + } + + @Ignore //TODO: Need to clarify this test. The two course template don't seem to get merged by // MarkRole. Perhaps the cause is, that the MarkTemplate/MarkRole-map of the first // MarkTemplate is passed to the creation of the second one, so the MarkTemplate-IDs are diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/EventApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/EventApiTest.java index aa977b2b403..e93750f07b4 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/EventApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/EventApiTest.java @@ -44,8 +44,7 @@ public class EventApiTest extends AbstractSeleniumTest { assertEquals("read: event.description is different", eventName, foundEvent.get("description")); assertEquals("read: event.officialWebsiteURL is different", null, (String) foundEvent.get("officialWebsiteURL")); - assertEquals("read: event.baseUrl is different", getContextRoot() + ApiContext.SERVER_CONTEXT + "/api/", - foundEvent.get("baseURL")); + assertEquals("read: event.baseUrl is different", removeTrailingSlash(getContextRoot()), removeTrailingSlash(foundEvent.get("baseURL"))); assertNotNull("read: event.startDate is missing", foundEvent.getStartDate()); assertNotNull("read: event.endDate is missing", foundEvent.getEndDate()); assertEquals("read: event.images should be empty", 0, ((JSONArray) foundEvent.get("images")).size()); @@ -72,4 +71,8 @@ public class EventApiTest extends AbstractSeleniumTest { assertEquals("read: event.leaderboardGroups[0].hasOverallLeaderboard is different", false, foundEventLeaderBoardGroupsFirst.get("hasOverallLeaderboard")); } + + private String removeTrailingSlash(String url) { + return url.endsWith("/")?url.substring(0, url.length()-1):url; + } } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/MarkTemplateTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/MarkTemplateTest.java index 07d48f18266..2202f3a881a 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/MarkTemplateTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/MarkTemplateTest.java @@ -72,7 +72,6 @@ public class MarkTemplateTest extends AbstractSeleniumTest { final Iterable markTemplateResult = markTemplateApi.getAllMarkTemplates(ctx); for (MarkTemplate markTemplate : markTemplateResult) { - System.out.println(markTemplate.getId()); assertTrue(markTemplate.getId().equals(markTemplate1.getId()) || markTemplate.getId().equals(markTemplate2.getId())); } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/PreferencesApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/PreferencesApiTest.java index b1360de82e4..37abdce22b9 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/PreferencesApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/PreferencesApiTest.java @@ -24,7 +24,7 @@ public class PreferencesApiTest extends AbstractSeleniumTest { @Test public void createAndGetPreferencesTest() { - final ApiContext ctx = createAdminApiContext(getContextRoot(), ApiContext.SERVER_CONTEXT); + final ApiContext ctx = createAdminApiContext(getContextRoot(), ApiContext.SECURITY_CONTEXT); Map prefObjectAttr = new HashMap(); prefObjectAttr.put("key1", "value1"); @@ -40,7 +40,7 @@ public class PreferencesApiTest extends AbstractSeleniumTest { @Test public void createAndDeletePreferencesTest() { - final ApiContext ctx = createAdminApiContext(getContextRoot(), ApiContext.SERVER_CONTEXT); + final ApiContext ctx = createAdminApiContext(getContextRoot(), ApiContext.SECURITY_CONTEXT); Map prefObjectAttr = new HashMap(); prefObjectAttr.put("key1", "value1"); diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RoleApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RoleApiTest.java index b01f66021b0..64d98dbf7d5 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RoleApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/RoleApiTest.java @@ -26,7 +26,7 @@ public class RoleApiTest extends AbstractSeleniumTest { @Before public void setUp() { - clearState(getContextRoot()); + clearState(getContextRoot(), /* headless */ true); } @Test @@ -107,4 +107,17 @@ public class RoleApiTest extends AbstractSeleniumTest { roleApi.deleteRole(adminCtx, roleCreated.getId()); } + + @Test + public void createRoleWithDuplicateNameShouldFailTest() { + final String roleName = "DUPLICATE_CHECK_ROLE"; + final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SECURITY_CONTEXT); + roleApi.createRole(adminCtx, roleName); + try { + roleApi.createRole(adminCtx, roleName); + fail(); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java index 8fb509279a9..6bf2279aa16 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/TrackedEventsResourceApiTest.java @@ -3,11 +3,22 @@ package com.sap.sailing.selenium.api.test; import static com.sap.sailing.selenium.api.core.ApiContext.SERVER_CONTEXT; import static com.sap.sailing.selenium.api.core.ApiContext.createAdminApiContext; import static com.sap.sailing.selenium.api.core.ApiContext.createApiContext; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.iterableWithSize; +import static org.junit.Assert.assertThat; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.stream.StreamSupport; import org.junit.Assert; import org.junit.Before; @@ -26,6 +37,8 @@ import com.sap.sailing.selenium.test.AbstractSeleniumTest; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Triple; +import junit.framework.AssertionFailedError; + public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { private final TrackedEventsApi trackedEventsApi = new TrackedEventsApi(); @@ -58,61 +71,103 @@ public class TrackedEventsResourceApiTest extends AbstractSeleniumTest { final Event evt = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, "Mannheim"); - final String eventId = evt.getId(); - final String leaderboardName = evt.getName(); - final String regattaSecret = evt.getSecret(); final Event evt2 = eventApi.createEvent(adminCtx, "TestEvent-" + UUID.randomUUID().toString(), "75QMNATIONALEKREUZER", CompetitorRegistrationType.CLOSED, "Mannheim"); - final String eventId2 = evt2.getId(); - final String leaderboardName2 = evt2.getName(); - final String regattaSecret2 = evt.getSecret(); final Set> trackedIds = new HashSet<>(); trackedIds.add(new Triple<>(competitorId, null, null)); trackedIds.add(new Triple<>(null, boatId, null)); - trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId, leaderboardName, eventBaseUrl, deviceId, - trackedIds, regattaSecret); - trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, eventId2, leaderboardName2, eventBaseUrl, deviceId, - new HashSet<>(Arrays.asList(new Triple<>(null, null, markId))), regattaSecret2); + trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, evt.getId(), evt.getName(), eventBaseUrl, deviceId, + trackedIds, evt.getSecret()); + trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, evt2.getId(), evt2.getName(), eventBaseUrl, deviceId, + new HashSet<>(Arrays.asList(new Triple<>(null, null, markId))), evt2.getSecret()); - trackedEventsApi.setArchived(adminCtx, evt.getId(), leaderboardName, true); - trackedEventsApi.setArchived(adminCtx, evt2.getId(), leaderboardName2, false); + trackedEventsApi.setArchived(adminCtx, evt.getId(), evt.getName(), true); + trackedEventsApi.setArchived(adminCtx, evt2.getId(), evt2.getName(), false); // check if created event is still there final TrackedEvents trackedEvents = trackedEventsApi.getTrackedEvents(adminCtx, false); - int cntEvents = 0; - for (final TrackedEvent event : trackedEvents.getEvents()) { - cntEvents++; - Assert.assertEquals("Unexpected event base url", eventBaseUrl, event.getEventBaseUrl()); - if (eventId.equals(event.getEventId())) { - Assert.assertEquals("Unexpected event ID", eventId, event.getEventId()); - Assert.assertEquals("Unexpected leaderboard name", leaderboardName, event.getLeaderboardName()); - Assert.assertEquals("Unexpected regatta secret", regattaSecret, event.getRegattaSecret()); - Assert.fail("Expected event 1 to not be shown anymore."); - } else if (eventId2.equals(event.getEventId())) { - Assert.assertEquals("Unexpected event ID", eventId2, event.getEventId()); - Assert.assertEquals("Unexpected leaderboard name", leaderboardName2, event.getLeaderboardName()); - Assert.assertEquals("Unexpected regatta secret", regattaSecret2, event.getRegattaSecret()); - } else { - Assert.fail("Invalid event id."); - } + validateTrackedEvent(trackedEvents, evt2); + validateTrackedElements(trackedEvents, evt2, null, null, markId, deviceId, 1); + assertThat(trackedEvents.getEvents(), iterableWithSize(1)); + } - int cntElements = 0; - for (final TrackedElement elem : event.getTrackedElements()) { - cntElements++; - final boolean correctBoatId = boatId.equals(elem.getBoatId()); - final boolean correctCompetitorId = competitorId.equals(elem.getCompetitorId()); - final boolean correctMarkId = markId.equals(elem.getMarkId()); + @Test + public void testCreateUpdateTrackingEventsMultiThreaded() throws InterruptedException { + final ExecutorService threadPool = Executors.newFixedThreadPool(20); + final List> executions = new ArrayList<>(); + final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SERVER_CONTEXT); + final String eventBaseUrl = "testUrl"; + final String deviceId = UUID.randomUUID().toString(); - Assert.assertEquals("Unexpected device ID", deviceId, elem.getDeviceId()); - Assert.assertTrue("More than one or zero items tracked in this element", - correctBoatId ^ correctCompetitorId ^ correctMarkId); + List events = new ArrayList<>(); + for (int i = 0; i < 2000; i++) { + Event event = eventApi.createEvent(adminCtx, "TestEvent_" + i, "75QMNATIONALEKREUZER", + CompetitorRegistrationType.CLOSED, "Mannheim" + i); + events.add(event); + if (i % 2 == 0) { + executions.add((Future) threadPool.submit(() -> trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, + event.getId(), event.getName(), eventBaseUrl, deviceId, null, event.getSecret()))); } - Assert.assertEquals("Invalid numer of elements in this event", 1, cntElements); } - Assert.assertEquals("Expected 1 events", 1, cntEvents); + for (int i = 0; i < 2000; i++) { + Event event = events.get(i); + if (i % 2 == 0) { + // A:competitor id B:boat id C:mark id + Set> trackedIds = new HashSet<>(); + for (int j = 0; j < 10; j++) { + trackedIds.add( + new Triple("competitor" + i + "_" + j, "boat" + i + "_" + j, null)); + } + final int ii = i; + executions.add((Future) threadPool.submit(() -> { + trackedEventsApi.updateOrCreateTrackedEvent(adminCtx, event.getId(), event.getName(), + eventBaseUrl + ii, deviceId + ii, null, event.getSecret()); + })); + + executions.add(threadPool.submit(() -> { + trackedEventsApi.getTrackedEvents(adminCtx, false); + })); + } + } + threadPool.awaitTermination(60, SECONDS); + executions.forEach(future -> { + try { + future.get(); + } catch (InterruptedException e) { + Assert.fail("interrupted exception occurred"); + } catch (ExecutionException e) { + Assert.fail("execution exception:" + e.getCause()); + } + }); + } + + private void validateTrackedElements(TrackedEvents actualEvents, Event expected, String expectedBoatId, + String expectedCompetitorId, String expectedMarkId, String expectedDeviceId, long expectedElementCount) { + TrackedEvent actual = StreamSupport.stream(actualEvents.getEvents().spliterator(), false) + .filter(evt -> evt.getEventId().equals(expected.getId())).findFirst() + .orElseThrow(AssertionFailedError::new); + + for (final TrackedElement actualElement : actual.getTrackedElements()) { + assertThat(actualElement.getBoatId(), equalTo(expectedBoatId)); + assertThat(actualElement.getCompetitorId(), equalTo(expectedCompetitorId)); + assertThat(actualElement.getMarkId(), equalTo(expectedMarkId)); + assertThat("Unexpected device ID", actualElement.getDeviceId(), equalTo(expectedDeviceId)); + } + assertThat(expectedElementCount, + equalTo(StreamSupport.stream(actual.getTrackedElements().spliterator(), false).count())); + } + + private TrackedEvent validateTrackedEvent(TrackedEvents actualEvents, Event expected) { + TrackedEvent actual = StreamSupport.stream(actualEvents.getEvents().spliterator(), false) + .filter(evt -> evt.getEventId().equals(expected.getId())).findFirst() + .orElseThrow(AssertionFailedError::new); + assertThat("Unexpected event ID", actual.getEventId(), equalTo(expected.getId())); + assertThat("Unexpected leaderboard name", actual.getLeaderboardName(), equalTo(expected.getName())); + assertThat("Unexpected regatta secret", actual.getRegattaSecret(), equalTo(expected.getSecret())); + return actual; } @Test diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/UserGroupApiTest.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/UserGroupApiTest.java index 8f4e88c7cdb..214e6e08580 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/UserGroupApiTest.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/api/test/UserGroupApiTest.java @@ -1,23 +1,32 @@ package com.sap.sailing.selenium.api.test; import static com.sap.sailing.selenium.api.core.ApiContext.SECURITY_CONTEXT; +import static com.sap.sailing.selenium.api.core.ApiContext.SERVER_CONTEXT; import static com.sap.sailing.selenium.api.core.ApiContext.createAdminApiContext; +import static com.sap.sailing.selenium.api.core.ApiContext.createApiContext; +import static com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage.goToPage; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.Arrays; +import java.util.concurrent.atomic.LongAdder; import org.junit.Before; import org.junit.Test; +import com.sap.sailing.domain.common.CompetitorRegistrationType; import com.sap.sailing.selenium.api.core.ApiContext; +import com.sap.sailing.selenium.api.core.HttpException; +import com.sap.sailing.selenium.api.event.EventApi; +import com.sap.sailing.selenium.api.event.EventApi.Event; import com.sap.sailing.selenium.api.event.RoleApi; import com.sap.sailing.selenium.api.event.RoleApi.Role; import com.sap.sailing.selenium.api.event.SecurityApi; import com.sap.sailing.selenium.api.event.UserGroupApi; import com.sap.sailing.selenium.api.event.UserGroupApi.UserGroup; +import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage; import com.sap.sailing.selenium.test.AbstractSeleniumTest; import com.sap.sse.common.Util; @@ -25,10 +34,12 @@ public class UserGroupApiTest extends AbstractSeleniumTest { private final UserGroupApi userGroupApi = new UserGroupApi(); private final RoleApi roleApi = new RoleApi(); + private final SecurityApi securityApi = new SecurityApi(); @Before public void setUp() { - clearState(getContextRoot()); + clearState(getContextRoot(), /* headless */ true); + super.setUp(); } @Test @@ -106,6 +117,48 @@ public class UserGroupApiTest extends AbstractSeleniumTest { } } + @Test + public void testGetReadableUserGroups() { + final ApiContext adminSecurityCtx = createAdminApiContext(getContextRoot(), SECURITY_CONTEXT); + final String user1Name = "user1"; + securityApi.createUser(adminSecurityCtx, user1Name, "test", "company", "password"); + final ApiContext user1Ctx = ApiContext.createApiContext(getContextRoot(), SECURITY_CONTEXT, user1Name, + "password"); + final ApiContext user1SecurityCtx = ApiContext.createApiContext(getContextRoot(), SECURITY_CONTEXT, user1Name, + "password"); + assertEquals(1, Util.size(userGroupApi.getReadableGroupsOfUser(user1Ctx, user1Name))); + + // admin creates new group and adds user -> does not mean the user is allowed to read the group + final LongAdder counter = new LongAdder(); + final UserGroup group1ToAdd = userGroupApi.createUserGroup(adminSecurityCtx, "group1ToAdd"); + userGroupApi.addUserToGroup(adminSecurityCtx, group1ToAdd.getGroupId(), user1Name); + userGroupApi.getReadableGroupsOfUser(user1Ctx, user1Name).forEach(ug -> { + if (group1ToAdd.getGroupId().equals(ug.getGroupId())) { + counter.increment(); + } + }); + assertEquals(0, counter.intValue()); + + // user1 creates new group -> this group is readable by user1 + counter.reset(); + final UserGroup group2ToAdd = userGroupApi.createUserGroup(user1SecurityCtx, "group2ToAdd"); + userGroupApi.getReadableGroupsOfUser(user1Ctx, user1Name).forEach(ug -> { + if (group2ToAdd.getGroupId().equals(ug.getGroupId())) { + counter.increment(); + } + }); + assertEquals(1, counter.intValue()); + + // if passing null for the username, implying the current user, should return the same result + counter.reset(); + userGroupApi.getReadableGroupsOfCurrentUser(user1Ctx).forEach(ug -> { + if (group2ToAdd.getGroupId().equals(ug.getGroupId())) { + counter.increment(); + } + }); + assertEquals(1, counter.intValue()); + } + @Test public void testChangeUsersInUserGroup() { final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SECURITY_CONTEXT); @@ -148,6 +201,77 @@ public class UserGroupApiTest extends AbstractSeleniumTest { assertSameElements(userGroupCreated.getUsers(), userGroupAfterUserRemove.getUsers()); } + @Test + public void setDefaultTenantForCurrentServerAndUserTest() { + final String defaultTenantGroup = "NewGroup"; + final String eventName = "testevent"; + final String eventName2 = "testevent2"; + final ApiContext adminSecurityCtx = createAdminApiContext(getContextRoot(), SECURITY_CONTEXT); + securityApi.createUser(adminSecurityCtx, "donald", "Donald Duck", null, "daisy0815"); + final ApiContext ownerCtx = createApiContext(getContextRoot(), SERVER_CONTEXT, "donald", "daisy0815"); + final ApiContext ownerSecurityCtx = createApiContext(getContextRoot(), SECURITY_CONTEXT, "donald", "daisy0815"); + final AdminConsolePage adminConsole = goToPage(getWebDriver(), getContextRoot()); + adminConsole.goToLocalServerPanel().setSelfServiceServer(true); + + final EventApi eventApi = new EventApi(); + final Event eventCreatedWithDefaultTenant = eventApi.createEvent(ownerCtx, eventName, "GC 32", + CompetitorRegistrationType.CLOSED, "somewhere"); + assertEquals("testevent", eventCreatedWithDefaultTenant.getName()); + + final UserGroup newUserGroup = userGroupApi.createUserGroup(adminSecurityCtx, defaultTenantGroup); + userGroupApi.setDefaultTenantForCurrentServerAndUser(ownerSecurityCtx, newUserGroup.getGroupId()); + + final Event eventCreatedWithNewGroupTenant = eventApi.createEvent(ownerCtx, eventName2, "GC 32", + CompetitorRegistrationType.CLOSED, "somewhere"); + assertEquals(eventName2, eventCreatedWithNewGroupTenant.getName()); + final String groupOfEvent = adminConsole.goToEvents().getEventEntry(eventName2).getColumnContent("Group"); + assertEquals(defaultTenantGroup, groupOfEvent); + } + + @Test + public void addUserToOwnGroupWithoutPermissionOnUserTest() { + final ApiContext adminSecurityCtx = createAdminApiContext(getContextRoot(), SECURITY_CONTEXT); + final String userToAdd = "usertoadd"; + securityApi.createUser(adminSecurityCtx, "groupowner", "groupowner", null, "daisy0815"); + securityApi.createUser(adminSecurityCtx, userToAdd, "", null, "daisy0815"); + + final ApiContext groupownerSecurityCtx = createApiContext(getContextRoot(), SECURITY_CONTEXT, "groupowner", + "daisy0815"); + // create group owned by "groupowner" + final UserGroup privateUserGroup = userGroupApi.createUserGroup(groupownerSecurityCtx, "mygroup"); + + // add user "usertoadd" to private user group + final ApiContext groupownerCtx = createApiContext(getContextRoot(), SECURITY_CONTEXT, "groupowner", "daisy0815"); + userGroupApi.addUserToUserGroupWithoutPermissionOnUser(groupownerCtx, userToAdd, + privateUserGroup.getGroupId()); + final UserGroup privateUserGroupToCheck = userGroupApi.getUserGroup(adminSecurityCtx, + privateUserGroup.getGroupId()); + boolean userExistsInGroup = false; + for (final String user : privateUserGroupToCheck.getUsers()) { + userExistsInGroup = userExistsInGroup || user.equals(userToAdd); + } + assertTrue("User does not exist in group", userExistsInGroup); + + // create group by admin and try to add user to it + final UserGroup adminUserGroup = userGroupApi.createUserGroup(adminSecurityCtx, "admingroup"); + try { + userGroupApi.addUserToUserGroupWithoutPermissionOnUser(groupownerCtx, "usertoadd", + adminUserGroup.getGroupId()); + fail(); + } catch (HttpException he) { + assertEquals(401, he.getHttpStatusCode()); + } + + // try to add user again to privateUserGroup + try { + userGroupApi.addUserToUserGroupWithoutPermissionOnUser(groupownerCtx, "usertoadd", + privateUserGroup.getGroupId()); + fail(); + } catch (HttpException he) { + assertEquals(400, he.getHttpStatusCode()); + } + } + @Test public void changeRolesAssociatedToUserGroup() { final ApiContext adminCtx = createAdminApiContext(getContextRoot(), SECURITY_CONTEXT); diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/TestEnvironmentConfiguration.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/TestEnvironmentConfiguration.java index 9891de7b908..d7e1b65025c 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/TestEnvironmentConfiguration.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/TestEnvironmentConfiguration.java @@ -143,7 +143,7 @@ public class TestEnvironmentConfiguration { private static synchronized Document readTestConfiguration() throws ParserConfigurationException, SAXException, IOException { - String path = System.getProperty(TEST_ENVIRONMENT_CONFIGURATION); + String path = System.getProperty(TEST_ENVIRONMENT_CONFIGURATION, "local-test-environment.xml"); SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = schemaFactory.newSchema(new StreamSource(TEST_ENVIRONMENT_SCHEMA)); DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/PageObject.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/PageObject.java index 0358bfe5374..53a352c21d0 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/PageObject.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/PageObject.java @@ -210,7 +210,6 @@ public class PageObject { public PageObject(WebDriver driver, SearchContext context) { this.driver = driver; this.context = context; - verify(); initElements(); } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorEditDialogPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorEditDialogPO.java index 8da5ae7fc10..5a3e9cf9d71 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorEditDialogPO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorEditDialogPO.java @@ -1,11 +1,14 @@ package com.sap.sailing.selenium.pages.adminconsole.tracking; +import java.util.List; + import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import com.sap.sailing.selenium.core.BySeleniumId; import com.sap.sailing.selenium.core.FindBy; import com.sap.sailing.selenium.pages.common.DataEntryDialogPO; +import com.sap.sailing.selenium.pages.gwt.CheckBoxPO; public class TrackedRacesCompetitorEditDialogPO extends DataEntryDialogPO { @FindBy(how = BySeleniumId.class, using = "NameTextBox") @@ -17,8 +20,16 @@ public class TrackedRacesCompetitorEditDialogPO extends DataEntryDialogPO { @FindBy(how = BySeleniumId.class, using = "OkButton") private WebElement okButton; + private final CheckBoxPO withBoatCheckBox; + public TrackedRacesCompetitorEditDialogPO(WebDriver driver, WebElement element) { super(driver, element); + final List withBoatCheckBoxElement = driver.findElements(new BySeleniumId("WithBoatCheckBox")); + if (withBoatCheckBoxElement.isEmpty()) { + withBoatCheckBox = null; + } else { + withBoatCheckBox = CheckBoxPO.create(driver, withBoatCheckBoxElement.get(0)); + } } public void setNameTextBox(String name) { @@ -30,4 +41,10 @@ public class TrackedRacesCompetitorEditDialogPO extends DataEntryDialogPO { this.shortNameTextBox.clear(); this.shortNameTextBox.sendKeys(name); } + + public void setWithBoat(boolean withBoat) { + if (withBoatCheckBox != null) { + this.withBoatCheckBox.setSelected(withBoat); + } + } } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorsPanelPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorsPanelPO.java index 8dfb2de64ad..80d5e95454b 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorsPanelPO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesCompetitorsPanelPO.java @@ -27,7 +27,7 @@ public class TrackedRacesCompetitorsPanelPO extends PageArea { public TrackedRacesCompetitorEditDialogPO pushAddCompetitorButton() { this.addCompetitorButton.click(); waitForAjaxRequests(); - WebElement dialog = findElementBySeleniumId(this.driver, "CompetitorEditDialog"); + WebElement dialog = findElementBySeleniumId(this.driver, "CompetitorWithBoatAddDialog"); return new TrackedRacesCompetitorEditDialogPO(this.driver, dialog); } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestCompetitorCreation.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestCompetitorCreation.java index d17cffa2bf1..aebe4bddd58 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestCompetitorCreation.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestCompetitorCreation.java @@ -42,6 +42,7 @@ public class TestCompetitorCreation extends AbstractSeleniumTest { final String shortName = "NRV"; dialog.setNameTextBox(name); dialog.setShortNameTextBox(shortName); + dialog.setWithBoat(false); dialog.pressOk(); boolean found = false; for (final CompetitorEntry it : competitorsPanel.getCompetitorTable().getEntries()) { diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestLeaderboardConfigSelectionModel.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestLeaderboardConfigSelectionModel.java index 86a509d83b9..4c7dc31e5d1 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestLeaderboardConfigSelectionModel.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestLeaderboardConfigSelectionModel.java @@ -16,12 +16,12 @@ import com.sap.sailing.selenium.test.AbstractSeleniumTest; public class TestLeaderboardConfigSelectionModel extends AbstractSeleniumTest { private static final String LEADERBOARDNAME = "Test"; + @Override @Before public void setUp() { clearState(getContextRoot()); super.setUp(); - AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration(); leaderboardConfiguration.createFlexibleLeaderboard(LEADERBOARDNAME); diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestRefreshableSelectionModel.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestRefreshableSelectionModel.java index 2429cb47649..0e3c318314d 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestRefreshableSelectionModel.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestRefreshableSelectionModel.java @@ -76,21 +76,20 @@ public class TestRefreshableSelectionModel extends AbstractSeleniumTest { setUpAuthenticatedSession(windowForEditDriver); final TrackedRacesCompetitorsPanelPO competitorsPanel = goToCompetitorsPanel( windowForEditDriver); - for (int i = 0; i < 2; i++) { TrackedRacesCompetitorEditDialogPO dialog = competitorsPanel.pushAddCompetitorButton(); dialog.setNameTextBox("" + System.currentTimeMillis()); dialog.setShortNameTextBox("" + System.currentTimeMillis()); + dialog.setWithBoat(false); dialog.pressOk(); } - TrackedRacesCompetitorEditDialogPO dialog = competitorsPanel.pushAddCompetitorButton(); final String name = "" + System.currentTimeMillis(); dialog.setNameTextBox(name); final String shortName = "" + System.currentTimeMillis(); dialog.setShortNameTextBox(shortName); + dialog.setWithBoat(false); dialog.pressOk(); - boolean found = false; for (final CompetitorEntry it : competitorsPanel.getCompetitorTable().getEntries()) { String itName = it.getName(); @@ -101,7 +100,6 @@ public class TestRefreshableSelectionModel extends AbstractSeleniumTest { } } assertTrue(found); - TrackedRacesCompetitorsPanelPO competitorPanelForSelection = goToCompetitorsPanel( windowForSelection.switchToWindow()); found = false; @@ -115,7 +113,6 @@ public class TestRefreshableSelectionModel extends AbstractSeleniumTest { } assertTrue(found); competitorPanelForSelection.getCompetitorTable().selectEntry(competitorEntryToSelect); - assertEquals(1, competitorPanelForSelection.getCompetitorTable().getSelectedEntries().size()); assertEquals(name, competitorPanelForSelection.getCompetitorTable().getSelectedEntries().get(0).getName()); assertEquals(shortName, competitorPanelForSelection.getCompetitorTable().getSelectedEntries().get(0).getShortName()); @@ -127,10 +124,8 @@ public class TestRefreshableSelectionModel extends AbstractSeleniumTest { final String changedShortName = "" + System.currentTimeMillis(); dialog.setShortNameTextBox(changedShortName); dialog.pressOk(); - // assert selection windowForSelection.switchToWindow(); - competitorPanelForSelection.pushRefreshButton(); WebDriverWait waitTimer = new WebDriverWait(competitorPanelForSelection.driver, 10); ExpectedCondition condition = new ExpectedCondition() { @@ -140,7 +135,6 @@ public class TestRefreshableSelectionModel extends AbstractSeleniumTest { } }; waitTimer.until(condition); - assertEquals(1, competitorPanelForSelection.getCompetitorTable().getSelectedEntries().size()); for (final CompetitorEntry it : competitorPanelForSelection.getCompetitorTable().getEntries()) { String itName = it.getName(); diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/ORCCertificateJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/ORCCertificateJsonDeserializer.java index aaa9dd3c48a..38af2385291 100755 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/ORCCertificateJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/deserialization/racelog/impl/ORCCertificateJsonDeserializer.java @@ -37,8 +37,8 @@ public class ORCCertificateJsonDeserializer implements JsonDeserializer { } result.put(CompetitorJsonConstants.FIELD_NAME, competitor.getName()); result.put(CompetitorJsonConstants.FIELD_SHORT_NAME, competitor.getShortName()); + if (competitor.hasBoat()) { + result.put(CompetitorJsonConstants.FIELD_SAIL_ID, ((CompetitorWithBoat) competitor).getBoat().getSailID()); + } Color color = getColor(competitor); result.put(CompetitorJsonConstants.FIELD_DISPLAY_COLOR, color == null ? null : color.getAsHtml()); if (serializeNonPublicFields) { @@ -141,6 +144,16 @@ public class CompetitorJsonSerializer implements JsonSerializer { result.put(CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE, competitor.getTimeOnDistanceAllowancePerNauticalMile() == null ? null : competitor.getTimeOnDistanceAllowancePerNauticalMile().asSeconds()); + // adding redundant values to migrate CompetitorsResource to use this serializer instead of its own; see also bug5289 + result.put(CompetitorJsonConstants.FIELD_COLOR, color == null ? null : color.getAsHtml()); + result.put(CompetitorJsonConstants.FIELD_COUNTRY_CODE, + countryCode == null ? "" : countryCode.getTwoLetterISOCode()); + result.put(CompetitorJsonConstants.FIELD_FLAG_IMAGE, + competitor.getFlagImage() != null ? competitor.getFlagImage().toString() : null); + result.put(CompetitorJsonConstants.FIELD_TEAM_IMAGE_URI, + competitor.getTeam() != null + ? competitor.getTeam().getImage() != null ? competitor.getTeam().getImage().toString() : null + : null); return result; } diff --git a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/ORCCertificateJsonSerializer.java b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/ORCCertificateJsonSerializer.java index 9b43cfc8451..672fab05f7c 100755 --- a/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/ORCCertificateJsonSerializer.java +++ b/java/com.sap.sailing.server.gateway.serialization.shared.android/src/com/sap/sailing/server/gateway/serialization/racelog/impl/ORCCertificateJsonSerializer.java @@ -53,6 +53,11 @@ public class ORCCertificateJsonSerializer implements JsonSerializer>> deserializer = @@ -45,6 +56,82 @@ public class FlatSmartphoneUuidAndGPSFixMovingJsonDeserializerTest { Pair> result = deserializer.deserialize(Helpers.toJSONObjectSafe(JSONValue.parseWithException(json))); assertThat("uuid", result.getA(), equalTo(UUID.fromString("af855a56-9726-4a9c-a77e-da955bd289bf"))); - assertThat("number of fixes", result.getB().size(), equalTo(2)); + assertThat("number of fixes", result.getB().size(), equalTo(3)); + + TimePoint tp3 = result.getB().get(2).getTimePoint(); + assertThat(tp3.asMillis(), equalTo(14144168490000L)); + } + + @Test + public void containsBothTimestampFields() throws JsonDeserializationException, ParseException { + String json = "{\n" + + " \"deviceUuid\" : \"af855a56-9726-4a9c-a77e-da955bd289bf\",\n" + + " \"fixes\" : [\n" + + " {\n" + + " \"timestamp-iso\" : \"2418-03-18T17:34:30Z\",\n" + + " \"timestamp\" : \"14144168490000\",\n" + + " \"latitude\" : -67.672456,\n" + + " \"longitude\" : -2.03456,\n" + + " \"speed\" : 19.3,\n" + + " \"course\" : 359.99,\n" + + " }\n" + + " ]\n" + + "}"; + JsonDeserializer>> deserializer = + new FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer(); + try { + deserializer.deserialize(Helpers.toJSONObjectSafe(JSONValue.parseWithException(json))); + Assert.fail(); + } catch (JsonDeserializationException e) { + assertThat(e.getMessage(),equalTo("two timestamp fields are filled. Please use only one of both.")); + } + } + + @Test + public void wrongFormat_millis() throws JsonDeserializationException, ParseException { + String json = "{\n" + + " \"deviceUuid\" : \"af855a56-9726-4a9c-a77e-da955bd289bf\",\n" + + " \"fixes\" : [\n" + + " {\n" + + " \"timestamp\" : \"2418-03-18T17:34:30Z\",\n" + + " \"latitude\" : -67.672456,\n" + + " \"longitude\" : -2.03456,\n" + + " \"speed\" : 19.3,\n" + + " \"course\" : 359.99,\n" + + " }\n" + + " ]\n" + + "}"; + JsonDeserializer>> deserializer = + new FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer(); + try { + deserializer.deserialize(Helpers.toJSONObjectSafe(JSONValue.parseWithException(json))); + Assert.fail(); + } catch (NumberFormatException e) { + assertThat(e.getMessage(),equalTo("For input string: \"2418-03-18T17:34:30Z\"")); + } + } + + @Test + public void wrongFormat_ISO() throws JsonDeserializationException, ParseException { + String json = "{\n" + + " \"deviceUuid\" : \"af855a56-9726-4a9c-a77e-da955bd289bf\",\n" + + " \"fixes\" : [\n" + + " {\n" + + " \"timestamp-iso\" : \"14144168490000\",\n" + + " \"latitude\" : -67.672456,\n" + + " \"longitude\" : -2.03456,\n" + + " \"speed\" : 19.3,\n" + + " \"course\" : 359.99,\n" + + " }\n" + + " ]\n" + + "}"; + JsonDeserializer>> deserializer = + new FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer(); + try { + deserializer.deserialize(Helpers.toJSONObjectSafe(JSONValue.parseWithException(json))); + Assert.fail(); + } catch (DateTimeParseException e) { + assertThat(e.getMessage(),equalTo("Text '14144168490000' could not be parsed at index 0")); + } } } diff --git a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.java b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.java index 5ab650d5cc5..45b018dc834 100644 --- a/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.java +++ b/java/com.sap.sailing.server.gateway.serialization/src/com/sap/sailing/server/gateway/deserialization/impl/FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer.java @@ -1,5 +1,7 @@ package com.sap.sailing.server.gateway.deserialization.impl; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -34,7 +36,7 @@ public class FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer implements JSONObject fixObject = Helpers.toJSONObjectSafe(jsonFixes.get(i)); double lonDeg = Double.parseDouble(fixObject.get(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.LON_DEG).toString()); double latDeg = Double.parseDouble(fixObject.get(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.LAT_DEG).toString()); - long timeMillis = Long.parseLong(fixObject.get(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.TIME_MILLIS).toString()); + long timeMillis = deserializeTimestamp(fixObject); double speedMperS = Double.parseDouble(fixObject.get(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.SPEED_M_PER_S).toString()); double speedKnots = new MeterPerSecondSpeedImpl(speedMperS).getKnots(); double bearingDeg = Double.parseDouble(fixObject.get(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.BEARING_DEG).toString()); @@ -44,4 +46,26 @@ public class FlatSmartphoneUuidAndGPSFixMovingJsonDeserializer implements return new Pair>(device, fixes); } + + private long deserializeTimestamp(JSONObject fixObject) throws JsonDeserializationException { + long timeMillis; + Object timeMillisObj = fixObject.get(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.TIME_MILLIS); + Object timeIsoObj = fixObject.get(FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.TIME_ISO); + if (timeMillisObj != null && timeIsoObj != null) { + throw new JsonDeserializationException("two timestamp fields are filled. Please use only one of both."); + } + if (timeMillisObj != null) { + timeMillis = Long.parseLong(timeMillisObj.toString()); + } else if (timeIsoObj != null) { + String strIsoTimestamp = timeIsoObj.toString(); + DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_DATE_TIME; + OffsetDateTime offsetDateTime = OffsetDateTime.parse(strIsoTimestamp, timeFormatter); + timeMillis = offsetDateTime.toInstant().toEpochMilli(); + } else { + throw new JsonDeserializationException("no timestamp field provided. Please provide one of these fields: " + + FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.TIME_MILLIS + ", " + + FlatSmartphoneUuidAndGPSFixMovingJsonSerializer.TIME_ISO); + } + return timeMillis; + } } diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/RegattasResourceClient.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/RegattasResourceClient.java deleted file mode 100644 index b97017b11f4..00000000000 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/RegattasResourceClient.java +++ /dev/null @@ -1,260 +0,0 @@ -package com.sap.sailing.server.gateway.test.jaxrs; - -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.JSONValue; - -import com.sap.sailing.domain.common.CompetitorRegistrationType; -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.UniformInterfaceException; -import com.sun.jersey.api.client.WebResource; -import com.sun.jersey.api.representation.Form; - -@SuppressWarnings("unused") -public class RegattasResourceClient { - - private static final String REGATTA_NAME = "TestTwiese"; - private static final String REGATTA_SECRET = "6e318fa0-fece-11e8-8d04-1d7aaf7786a1"; - private static final String COMPETITOR_DEVICE_UUID1 = "00000001-1111-2222-3333-444444444444"; - private static final String COMPETITOR_DEVICE_UUID2 = "00000002-1111-2222-3333-444444444444"; - private static final String COMPETITOR_DEVICE_UUID3 = "944cc19c-9676-5f50-af6e-e3eb4f12886d"; - - - //private String serverUrl = "http://localhost:8888/sailingserver"; - private String serverUrl = "https://my.sapsailing.com/sailingserver"; - private String secServerUrl = "https://my.sapsailing.com/security"; - private final WebResource webResource; - private final WebResource secResource; - - private String token; - - public static void main(String... args) { - RegattasResourceClient client = new RegattasResourceClient(); - //client.auth("admin", "admin"); - client.auth("", "orange"); - //String name = "TestEventOpen_" + createRandomString(5); - //System.out.println(name); - //client.createEvent(name); - //client.updateOrCreateSeries(name, name); - //client.addRaceColumns(name, "Default"); - - //client.token = null; - client.addCompetitorToRegatta(" openRegattaTest1", REGATTA_SECRET, COMPETITOR_DEVICE_UUID3); - - //client.printRegatta(" openRegattaTest1"); - - //client.printEvents(); - //client.printEvent("5af41a71-834d-4f88-a432-fae993a1f3c8"); - //Set competitorIds = client.readCompetitors(REGATTA_NAME); - //competitorIds.forEach(c -> System.out.println(competitorIds)); - //competitorIds.forEach(c -> client.removeCompetitor(REGATTA_NAME, c)); - - //client.auth("admin", "admin"); - //client.addCompetitorToRegatta(REGATTA_NAME, REGATTA_SECRET, COMPETITOR_DEVICE_UUID1); - //client.addCompetitorToRegatta(REGATTA_NAME, REGATTA_SECRET, COMPETITOR_DEVICE_UUID2); - - } - - public RegattasResourceClient() { - Client client = Client.create(); - this.webResource = client.resource(serverUrl); - this.secResource = client.resource(secServerUrl); - } - - public void printEvents() { - String eventsURI = "/api/v1/events"; - WebResource wres = webResource.path(eventsURI); - WebResource.Builder wresBuilder = wres.getRequestBuilder(); - if (token != null) { - wresBuilder.header("Authorization", "Bearer " + token); - } - String result = wresBuilder.get(String.class); - System.out.println(result); - } - - public void printEvent(String id) { - String eventsURI = "/api/v1/events"; - WebResource wres = webResource.path(eventsURI + "/" + id); - WebResource.Builder wresBuilder = wres.getRequestBuilder(); - if (token != null) { - wresBuilder.header("Authorization", "Bearer " + token); - } - String result = wresBuilder.get(String.class); - System.out.println(result); - } - - public void printRegattas() { - String regattasURI = "/api/v1/regattas"; - WebResource wres = webResource.path(regattasURI); - WebResource.Builder wresBuilder = wres.getRequestBuilder(); - if (token != null) { - wresBuilder.header("Authorization", "Bearer " + token); - } - String result = wresBuilder.get(String.class); - System.out.println(result); - } - - public void printRegatta(String name) { - String regattaURI = "api/v1/regattas/{regattaName}"; - WebResource wres = webResource.path(regattaURI.replace("{regattaName}", name)); - WebResource.Builder wresBuilder = wres.getRequestBuilder(); - if (token != null) { - wresBuilder = wresBuilder.header("Authorization", "Bearer " + token); - } - String result = wresBuilder.get(String.class); - System.out.println(result); - } - - public void addCompetitorToRegatta(String regattaName, String regattaSecret, String deviceUuid) { - String addAndCreateCompetitorURI = "api/v1/regattas/{regattaName}/competitors/createandadd"; - WebResource wres = webResource.path(addAndCreateCompetitorURI.replace("{regattaName}", regattaName)) - .queryParam("boatclass", "Cadet") - .queryParam("deviceUuid", deviceUuid) - .queryParam("competitorName", regattaName) //is required, when not authenticated - .queryParam("secret", regattaSecret) - .queryParam("nationalityIOC", "GER") - .queryParam("displayColor", "#00FF00") - .queryParam("flagImageURI", "file:///tmp/flag.jpg") - .queryParam("teamImageURI", "file:///tmp/flag.jpg") - .queryParam("competitorShortName", "xxx") - .queryParam("competitorEmail", "mail@thomaswiese.de"); - WebResource.Builder wresBuilder = wres.getRequestBuilder(); - if (token != null) { - wresBuilder = wresBuilder.header("Authorization", "Bearer " + token); - } - try { - String result = wresBuilder.post(String.class); - System.out.println(result); - } catch (UniformInterfaceException e) { - System.out.println(e.getResponse().getEntity(String.class)); - throw e; - } - } - - public Set readCompetitors(String regattaName) { - String competitorsURI = "api/v1/regattas/{regattaName}/competitors"; - WebResource wres = webResource.path(competitorsURI.replace("{regattaName}", regattaName)); - WebResource.Builder wresBuilder = wres.getRequestBuilder(); - if (token != null) { - wresBuilder = wresBuilder.header("Authorization", "Bearer " + token); - } - String result = wresBuilder.get(String.class); - System.out.println(result); - return getCompetitorIdsFromCompetitorsResponse(result); - } - - public void removeCompetitor(String regattaName, String competitorId) { - System.out.println(competitorId); - String competitorsRemoveURI = "api/v1/regattas/{regattaName}/competitors/{competitorId}/remove"; - WebResource wres = webResource.path(competitorsRemoveURI.replace("{regattaName}", regattaName).replace("{competitorId}", competitorId)) - .queryParam("secret", REGATTA_SECRET); - WebResource.Builder wresBuilder = wres.getRequestBuilder(); - if (token != null) { - wresBuilder = wresBuilder.header("Authorization", "Bearer " + token); - } - String result = wresBuilder.post(String.class); - System.out.println(result); - } - - public void hello() { - String helloURI = "/api/restsecurity/hello"; - String result = secResource.path(helloURI).get(String.class); - System.out.println(result); - } - - public void auth(String username, String password) { - //String loginURI = "/api/restsecurity/login"; - String tokenURI = "/api/restsecurity/access_token"; - Form form = new Form(); - form.putSingle("username", username); - form.putSingle("password", password); - String tokenJson = secResource.path(tokenURI).entity(form).post(String.class); - JSONObject obj = (JSONObject) JSONValue.parse(tokenJson); - String token = (String) obj.get("access_token"); - System.out.println(token); - this.token = token; - } - - public Set getCompetitorIdsFromCompetitorsResponse(String comeptitorsJson) { - JSONArray arr = (JSONArray) JSONValue.parse(comeptitorsJson); - return arr.stream().map(a -> ((JSONObject) a).get("id").toString()).collect(Collectors.toSet()); - } - - public String getCompetitorsIdFromCompetitorJson(JSONObject competitorJson) { - return (String) competitorJson.get("id"); - } - - public void createEvent(String name) { - String createEventURI = "api/v1/events/createEvent"; - WebResource wres = webResource.path(createEventURI); - WebResource.Builder wresBuilder = wres.getRequestBuilder(); - if (token != null) { - wresBuilder = wresBuilder.header("Authorization", "Bearer " + token); - } - - Form form = new Form(); - form.putSingle("eventName", name); - form.putSingle("venuename", "Test"); - form.putSingle("ispublic", "true"); - form.putSingle("createleaderboardgroup", "true"); - form.putSingle("createregatta", "true"); - form.putSingle("boatclassname", "TP52"); - form.putSingle("numberofraces", "1"); - form.putSingle("canBoatsOfCompetitorsChangePerRace", "false"); - form.putSingle("competitorRegistrationType", CompetitorRegistrationType.OPEN_UNMODERATED.name()); - form.putSingle("secret", REGATTA_SECRET); - try { - String result = wresBuilder.entity(form).post(String.class); - System.out.println(result); - } catch (UniformInterfaceException e) { - System.out.println(e.getResponse().toString()); - throw e; - } - - } - - - public void addRaceColumns(String regattaname, String seriesname) { - - String createEventURI = "api/v1/regatta/{regattaname}/addracecolumns"; - WebResource wres = webResource.path(createEventURI.replace("{regattaname}", regattaname)) - .queryParam("numberofraces", "1") - .queryParam("toseries", seriesname); - WebResource.Builder wresBuilder = wres.getRequestBuilder(); - if (token != null) { - wresBuilder = wresBuilder.header("Authorization", "Bearer " + token); - } - try { - String result = wresBuilder.post(String.class); - System.out.println(result); - } catch (UniformInterfaceException e) { - System.out.println(e.getResponse().getEntity(String.class)); - throw e; - } - } - - public void updateOrCreateSeries(String reaggataName, String seriesname) { - String json = "{'regattaName': '" + reaggataName + "', 'seriesName': '" + seriesname + "', 'seriesNameNew': '" + seriesname + "', 'isMedal': 'false', 'isFleetsCanRunInParallel': 'false', 'startsWithZeroScore': 'false', 'firstColumnIsNonDiscardableCarryForward': 'false', 'hasSplitFleetContiguousScoring': 'false', fleets: []}"; - System.out.println(json); - String createEventURI = "api/v1/regatta/updateOrCreateSeries"; - WebResource wres = webResource.path(createEventURI); - WebResource.Builder wresBuilder = wres.getRequestBuilder(); - if (token != null) { - wresBuilder = wresBuilder.header("Authorization", "Bearer " + token); - } - String result = wresBuilder.entity(json).post(String.class); - System.out.println(result); - } - - - public static String createRandomString(int length) { - String randomString = Stream.generate(Math::random).map(r -> (int) (r * 100)) - .filter(i -> (i > 47 && i < 58 || i > 64 && i < 90)).limit(length) - .map(i -> String.valueOf((char) i.intValue())).collect(Collectors.joining()); - return randomString; - } -} diff --git a/java/com.sap.sailing.server.gateway/main.css b/java/com.sap.sailing.server.gateway/main.css index fee583e3b81..da919ea2eb4 100644 --- a/java/com.sap.sailing.server.gateway/main.css +++ b/java/com.sap.sailing.server.gateway/main.css @@ -81,3 +81,8 @@ a:hover { ul { padding-left: 20px; } + +.deprecationMessage { + font-weight: bold; + color: red; +} \ No newline at end of file diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/FileUploadServlet.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/FileUploadServlet.java index 9e12d424a01..bf00595e3c8 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/FileUploadServlet.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/impl/FileUploadServlet.java @@ -13,11 +13,9 @@ import javax.servlet.http.HttpServletResponse; import javax.ws.rs.core.Response.Status; import org.apache.commons.fileupload.FileItem; -import org.apache.shiro.authz.UnauthorizedException; import org.json.simple.JSONArray; import org.json.simple.JSONObject; -import com.sap.sse.common.NoCorrespondingServiceRegisteredException; import com.sap.sse.common.fileupload.FileUploadConstants; import com.sap.sse.filestorage.InvalidPropertiesException; import com.sap.sse.filestorage.OperationFailedException; @@ -78,8 +76,7 @@ public class FileUploadServlet extends AbstractFileUploadServlet { result.put(FileUploadConstants.FILE_NAME, fileName); result.put(FileUploadConstants.FILE_URI, fileUri.toString()); } - } catch (IOException | OperationFailedException | InvalidPropertiesException - | NoCorrespondingServiceRegisteredException | UnauthorizedException e) { + } catch (IOException | OperationFailedException | RuntimeException | InvalidPropertiesException e) { final String errorMessage = "Could not store file"+ (e.getMessage()==null?"":(": " + e.getMessage())); logger.log(Level.WARNING, "Could not store file", e); result.put(FileUploadConstants.STATUS, Status.INTERNAL_SERVER_ERROR.name()); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java index 28a3174c403..0357376d5e5 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java @@ -5,6 +5,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URI; +import java.net.URISyntaxException; import java.util.logging.Level; import java.util.logging.Logger; @@ -12,6 +13,7 @@ import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.POST; +import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @@ -24,22 +26,29 @@ import javax.ws.rs.core.Response.Status; import org.apache.commons.fileupload.util.Streams; import org.apache.commons.lang.StringEscapeUtils; import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; import com.sap.sailing.domain.base.Competitor; import com.sap.sailing.domain.base.CompetitorAndBoatStore; -import com.sap.sailing.domain.base.CompetitorWithBoat; import com.sap.sailing.domain.base.Nationality; import com.sap.sailing.domain.base.Regatta; import com.sap.sailing.domain.base.Team; +import com.sap.sailing.domain.base.impl.NationalityImpl; import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants; import com.sap.sailing.domain.common.tracking.impl.CompetitorJsonConstants; import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.NationalityJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.PersonJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.TeamJsonSerializer; import com.sap.sailing.server.interfaces.RacingEventService; import com.sap.sailing.server.operationaltransformation.UpdateCompetitor; +import com.sap.sse.common.Color; +import com.sap.sse.common.Duration; import com.sap.sse.common.Util; +import com.sap.sse.common.impl.RGBColor; +import com.sap.sse.common.impl.SecondsDurationImpl; import com.sap.sse.filestorage.InvalidPropertiesException; import com.sap.sse.filestorage.OperationFailedException; import com.sap.sse.security.shared.impl.SecuredSecurityTypes; @@ -53,28 +62,6 @@ public class CompetitorsResource extends AbstractSailingServerResource { */ private static final int MAX_SIZE_IN_MB = 5; - public static JSONObject getCompetitorJSON(Competitor competitor) { - // see http://wiki.sapsailing.com/wiki/info/api/api-v1#tracking-app-api-v1_check-in-information_competitor-information-in-general - JSONObject json = new JSONObject(); - json.put(CompetitorJsonConstants.FIELD_ID, competitor.getId().toString()); - json.put(CompetitorJsonConstants.FIELD_NAME, competitor.getName()); - if (competitor.hasBoat()) { - json.put(CompetitorJsonConstants.FIELD_SAIL_ID, ((CompetitorWithBoat) competitor).getBoat().getSailID()); - } - json.put(CompetitorJsonConstants.FIELD_SHORT_NAME, competitor.getShortName()); - final Nationality nationality = competitor.getTeam().getNationality(); - json.put(CompetitorJsonConstants.FIELD_NATIONALITY, nationality==null?null:nationality.getThreeLetterIOCAcronym()); - json.put(CompetitorJsonConstants.FIELD_COUNTRY_CODE, nationality==null?null:nationality.getCountryCode().getTwoLetterISOCode()); - json.put(CompetitorJsonConstants.FIELD_COLOR, competitor.getColor() != null ? competitor.getColor().getAsHtml() : null); - if (competitor.getFlagImage() != null) { - json.put(CompetitorJsonConstants.FIELD_FLAG_IMAGE, competitor.getFlagImage().toString()); - } - if (competitor.getTeam().getImage() != null) { - json.put(CompetitorJsonConstants.FIELD_TEAM_IMAGE_URI, competitor.getTeam().getImage().toString()); - } - return json; - } - @GET @Produces("application/json;charset=UTF-8") @Path("{competitorId}") @@ -99,11 +86,134 @@ public class CompetitorsResource extends AbstractSailingServerResource { getSecurityService().checkCurrentUserHasOneOfExplicitPermissions(competitor, SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS); } - response = Response.ok(streamingOutput(getCompetitorJSON(competitor))).build(); + response = Response.ok(streamingOutput(CompetitorJsonSerializer.create().serialize(competitor))).build(); } return response; } + @PUT + @Produces("application/json;charset=UTF-8") + @Path("{competitorId}") + public Response updateCompetitor(@PathParam("competitorId") String competitorIdAsString, String json) { + if (json == null || json.isEmpty()) { + return Response.status(Status.BAD_REQUEST).entity("Missing competitor data.").type(MediaType.TEXT_PLAIN) + .build(); + } + Object competitorObject; + try { + competitorObject = new JSONParser().parse(json); + if (competitorObject == null || !(competitorObject instanceof JSONObject)) { + throw new IllegalArgumentException(); + } + } catch (ParseException | IllegalArgumentException pe) { + return Response.status(Status.BAD_REQUEST).entity("Competitor data is required to be given as json object") + .type(MediaType.TEXT_PLAIN).build(); + } + final JSONObject competitorJson = (JSONObject) competitorObject; + Response response; + final Competitor competitor = getService().getCompetitorAndBoatStore() + .getExistingCompetitorByIdAsString(competitorIdAsString); + if (competitor == null) { + response = Response + .status(Status.NOT_FOUND).entity("Could not find a competitor with id '" + + StringEscapeUtils.escapeHtml(competitorIdAsString) + "'.") + .type(MediaType.TEXT_PLAIN).build(); + } else { + if (getSecurityService().hasCurrentUserUpdatePermission(competitor)) { + final Color color; + try { + color = competitorJson.containsKey(CompetitorJsonConstants.FIELD_DISPLAY_COLOR) + ? createColorFromString((String) competitorJson.get(CompetitorJsonConstants.FIELD_DISPLAY_COLOR)) + : competitor.getColor(); + } catch (IllegalArgumentException iae) { + return Response.status(Status.BAD_REQUEST) + .entity(String.format("invalid color %s", iae.getMessage())).type(MediaType.TEXT_PLAIN) + .build(); + } + final URI flagImageUri; + try { + flagImageUri = competitorJson.containsKey(CompetitorJsonConstants.FIELD_FLAG_IMAGE_URI) + ? createURIFromString( + (String) competitorJson.get(CompetitorJsonConstants.FIELD_FLAG_IMAGE_URI)) + : competitor.getFlagImage(); + } catch (URISyntaxException use) { + return Response.status(Status.BAD_REQUEST) + .entity(String.format("invalid %s %s", CompetitorJsonConstants.FIELD_FLAG_IMAGE_URI, + competitorJson.get(CompetitorJsonConstants.FIELD_FLAG_IMAGE_URI))) + .type(MediaType.TEXT_PLAIN).build(); + } + final URI teamImageUri; + try { + teamImageUri = competitorJson.containsKey(CompetitorJsonConstants.FIELD_TEAM_IMAGE_URI) + ? createURIFromString( + (String) competitorJson.get(CompetitorJsonConstants.FIELD_TEAM_IMAGE_URI)) + : competitor.getTeam() != null ? competitor.getTeam().getImage() : null; + } catch (URISyntaxException use) { + return Response.status(Status.BAD_REQUEST) + .entity(String.format("invalid %s %s", CompetitorJsonConstants.FIELD_TEAM_IMAGE_URI, + competitorJson.get(CompetitorJsonConstants.FIELD_TEAM_IMAGE_URI))) + .type(MediaType.TEXT_PLAIN).build(); + } + final Nationality nationality; + try { + nationality = competitorJson.containsKey(CompetitorJsonConstants.FIELD_NATIONALITY) + ? createNationalityFromString( + (String) competitorJson.get(CompetitorJsonConstants.FIELD_NATIONALITY)) + : competitor.getNationality(); + } catch (IllegalArgumentException e) { + return Response.status(Status.BAD_REQUEST) + .entity(String.format("invalid %s %s", CompetitorJsonConstants.FIELD_NATIONALITY, + competitorJson.get(CompetitorJsonConstants.FIELD_NATIONALITY))) + .type(MediaType.TEXT_PLAIN).build(); + } + final Double timeOnTimeFactor; + try { + timeOnTimeFactor = competitorJson.containsKey(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR) + ? createDoubleFromObject( + competitorJson.get(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR)) + : competitor.getTimeOnTimeFactor(); + } catch (IllegalArgumentException iae) { + return Response.status(Status.BAD_REQUEST) + .entity(String.format("invalid %s %s", CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR, + competitorJson.get(CompetitorJsonConstants.FIELD_TIME_ON_TIME_FACTOR))) + .type(MediaType.TEXT_PLAIN).build(); + } + final Duration duration; + try { + duration = competitorJson.containsKey( + CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE) + ? createDurationFromObject(competitorJson.get( + CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE)) + : competitor.getTimeOnDistanceAllowancePerNauticalMile(); + } catch (IllegalArgumentException iae) { + return Response.status(Status.BAD_REQUEST).entity(String.format("invalid %s %s", + CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE, + competitorJson.get( + CompetitorJsonConstants.FIELD_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE))) + .type(MediaType.TEXT_PLAIN).build(); + } + final Competitor updatedCompetitor = getService().apply(new UpdateCompetitor(competitorIdAsString, + (String) competitorJson.getOrDefault(CompetitorJsonConstants.FIELD_NAME, competitor.getName()), + (String) competitorJson + .getOrDefault(CompetitorJsonConstants.FIELD_SHORT_NAME, competitor.getShortName()), + color, + (String) competitorJson.getOrDefault(CompetitorJsonConstants.FIELD_EMAIL, + competitor.getEmail()), + nationality, teamImageUri, flagImageUri, timeOnTimeFactor, duration, (String) competitorJson + .getOrDefault(CompetitorJsonConstants.FIELD_SEARCHTAG, competitor.getSearchTag()))); + response = Response.ok(streamingOutput(CompetitorJsonSerializer.create().serialize(updatedCompetitor))) + .header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); + } else { + response = Response.status(Status.FORBIDDEN) + .entity("Not allowed to update competitor with id '" + + StringEscapeUtils.escapeHtml(competitorIdAsString) + "'.") + .type(MediaType.TEXT_PLAIN).build(); + } + } + return response; + } + + @GET @Produces("application/json;charset=UTF-8") @Path("{competitor-id}/team") @@ -195,4 +305,48 @@ public class CompetitorsResource extends AbstractSailingServerResource { result.put(DeviceMappingConstants.JSON_TEAM_IMAGE_URI, imageUri.toString()); return result.toString(); } + + private Color createColorFromString(final String colorString) { + if (colorString == null || colorString.length() == 0) { + return null; + } else { + return new RGBColor(colorString); + } + } + + private URI createURIFromString(final String uriString) throws URISyntaxException { + if (uriString == null || uriString.length() == 0) { + return null; + } else { + return new URI(uriString); + } + } + + private Nationality createNationalityFromString(final String nationalityString) { + if (nationalityString == null || nationalityString.length() == 0) { + return null; + } else { + return new NationalityImpl(nationalityString); + } + } + + private Double createDoubleFromObject(final Object number) { + if (number == null) { + return null; + } else if (number instanceof Number) { + return ((Number) number).doubleValue(); + } else { + throw new IllegalArgumentException("invalid double value"); + } + } + + private Duration createDurationFromObject(final Object number) { + if (number == null) { + return null; + } else if (number instanceof Number) { + return new SecondsDurationImpl(((Number) number).doubleValue()); + } else { + throw new IllegalArgumentException("invalid duration in seconds value"); + } + } } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CourseConfigurationResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CourseConfigurationResource.java index 1865b5a5b89..d76d3a4b460 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CourseConfigurationResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CourseConfigurationResource.java @@ -399,7 +399,7 @@ public class CourseConfigurationResource extends AbstractSailingServerResource { raceLog.getCurrentPassId(), course, CourseDesignerMode.BY_MARKS)); final CourseConfiguration courseConfigurationResult = getService().getCourseAndMarkConfigurationFactory() .createCourseConfigurationFromRegatta(course, regatta, raceColumnByName.getTrackedRace(fleetByName), - /* tagsToFilterMarkProperties */ null); + /* tagsToFilterMarkProperties */ Collections.emptyList()); return Response.ok(streamingOutput(getCourseConfigurationJsonSerializer().serialize(courseConfigurationResult))).build(); } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/EventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/EventsResource.java index 2c5db14dc54..1fb11862013 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/EventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/EventsResource.java @@ -2,6 +2,7 @@ package com.sap.sailing.server.gateway.jaxrs.api; import java.io.IOException; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -300,8 +301,7 @@ public class EventsResource extends AbstractSailingServerResource { result.add(eventSerializer.serialize(event)); } } - String json = result.toJSONString(); - return Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); + return Response.ok(streamingOutput(result)).build(); } @GET @@ -481,7 +481,14 @@ public class EventsResource extends AbstractSailingServerResource { final TimePoint startDate = parseTimePoint(startDateParam, startDateAsMillis, now()); final TimePoint endDate = parseTimePoint(endDateParam, endDateAsMillis, new MillisecondsTimePoint(addOneWeek(startDate.asDate()))); URL officialWebsiteURL = officialWebsiteURLParam == null ? null : toURL(officialWebsiteURLParam); - URL baseURL = baseURLParam == null ? uriInfo.getBaseUri().toURL() : toURL(baseURLParam); + final URI baseUri = uriInfo.getBaseUri(); + final int port = baseUri.getPort(); + // guess the protocol; when behind an SSL-offloading reverse proxy or load balancer, all we'll see is a regular HTTP + // request; yet, we'd likely want the client to make requests using HTTPS, unless we see a dedicated port in the request + // that is not the HTTPS default port 443: + final String scheme = (port >= 0 && port != 443) ? "http" : "https"; + URL baseURL = baseURLParam == null ? new URL(scheme+":"+baseUri.getSchemeSpecificPart(). + substring(0, baseUri.getSchemeSpecificPart().length()-baseUri.getPath().length())) : toURL(baseURLParam); List leaderboardGroupIds = leaderboardGroupIdsListParam == null ? new ArrayList() : toUUIDList(leaderboardGroupIdsListParam); UUID eventId = UUID.randomUUID(); // ignoring sailorsInfoWebsiteURLs, images, videos @@ -591,7 +598,9 @@ public class EventsResource extends AbstractSailingServerResource { private String getDefaultEventName() { final String username; username = getCurrentUser().getName(); - return "Session "+username+" "+dateTimeFormat.format(new Date()); + synchronized (dateTimeFormat) { + return "Session "+username+" "+dateTimeFormat.format(new Date()); + } } private User getCurrentUser() { diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardGroupsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardGroupsResource.java index 8b36f2ed604..2f148cf74ba 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardGroupsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardGroupsResource.java @@ -199,7 +199,7 @@ public class LeaderboardGroupsResource extends AbstractSailingServerResource { jsonRaceColumn.put("trackedRaceName", trackedRace.getRace().getName()); final JSONObject raceBoardURLsByEventID = new JSONObject(); for (Event event : eventsReferencingLeaderboardGroup) { - if (Util.contains(event.getVenue().getCourseAreas(), leaderboard.getCourseAreas())) { + if (Util.containsAny(event.getVenue().getCourseAreas(), leaderboard.getCourseAreas())) { raceBoardURLsByEventID.put(event.getId().toString(), RaceBoardLinkFactory.createRaceBoardLink(trackedRace, leaderboard, event, leaderboardGroup, "PLAYER", /* locale */ null)); } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java index 0f6d5af34ae..0c30fea1e37 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResource.java @@ -126,6 +126,7 @@ import com.sap.sailing.server.gateway.serialization.coursedata.impl.GateJsonSeri import com.sap.sailing.server.gateway.serialization.coursedata.impl.MarkJsonSerializer; import com.sap.sailing.server.gateway.serialization.coursedata.impl.WaypointJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.CompetitorAndBoatJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.CompetitorJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.FlatGPSFixJsonSerializer; import com.sap.sailing.server.gateway.serialization.impl.MarkJsonSerializerWithPosition; import com.sap.sailing.server.gateway.serialization.racelog.impl.BaseRaceLogEventSerializer; @@ -312,8 +313,7 @@ public class LeaderboardsResource extends AbstractLeaderboardsResource { } } getService().apply(new UpdateLeaderboard(/* leaderboardName */ leaderboard.getName(), - /* newLeaderboardName */ leaderboard.getName(), newLeaderboardDisplayName, - resultDiscardingThresholds, + newLeaderboardDisplayName, resultDiscardingThresholds, Util.map(leaderboard.getCourseAreas(), CourseArea::getId))); } else { return Response.status(Status.NOT_FOUND).entity( @@ -560,7 +560,7 @@ public class LeaderboardsResource extends AbstractLeaderboardsResource { getSecurityService().checkCurrentUserHasOneOfExplicitPermissions(competitor, SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS); } - JSONObject json = CompetitorsResource.getCompetitorJSON(competitor); + JSONObject json = new CompetitorJsonSerializer().serialize(competitor); json.put("displayName", leaderboard.getDisplayName(competitor)); response = Response.ok(streamingOutput(json)).build(); } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResourceV2.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResourceV2.java index ab11fef4fb2..812d9eda73b 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResourceV2.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/LeaderboardsResourceV2.java @@ -1,7 +1,5 @@ package com.sap.sailing.server.gateway.jaxrs.api; -import java.io.IOException; -import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -103,11 +101,8 @@ public class LeaderboardsResourceV2 extends AbstractLeaderboardsResource { } else { jsonLeaderboard = createEmptyLeaderboardJson(leaderboard, resultState, maxCompetitorsCount, skip); } - StringWriter sw = new StringWriter(); - jsonLeaderboard.writeJSONString(sw); - String json = sw.getBuffer().toString(); - response = Response.ok(json).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); - } catch (NoWindException | InterruptedException | ExecutionException | IOException e) { + response = Response.ok(streamingOutput(jsonLeaderboard)).header("Content-Type", MediaType.APPLICATION_JSON + ";charset=UTF-8").build(); + } catch (NoWindException | InterruptedException | ExecutionException e) { response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()) .type(MediaType.TEXT_PLAIN).build(); } @@ -320,7 +315,9 @@ public class LeaderboardsResourceV2 extends AbstractLeaderboardsResource { DetailType.RACE_CURRENT_LEG, DetailType.OVERALL_MAXIMUM_SPEED_OVER_GROUND_IN_KNOTS, DetailType.LEG_VELOCITY_MADE_GOOD_IN_KNOTS, - DetailType.LEG_WINDWARD_DISTANCE_TO_GO_IN_METERS }; + DetailType.LEG_WINDWARD_DISTANCE_TO_GO_IN_METERS, + DetailType.OVERALL_TIME_ON_TIME_FACTOR, + DetailType.OVERALL_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE }; } private DetailType[] getAvailableOverallDetailColumnTypes() { @@ -454,6 +451,14 @@ public class LeaderboardsResourceV2 extends AbstractLeaderboardsResource { value = currentLegEntry.velocityMadeGoodInKnots; } break; + case OVERALL_TIME_ON_TIME_FACTOR: + name = "timeOnTimeFactor"; + value = competitor.getTimeOnTimeFactor(); + break; + case OVERALL_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE: + name = "timeOnDistanceAllowanceInSecondsPerNauticalMile"; + value = competitor.getTimeOnDistanceAllowancePerNauticalMile() == null ? null : competitor.getTimeOnDistanceAllowancePerNauticalMile().asSeconds(); + break; default: name = null; break; diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java index ad0a5723010..625819a41cb 100755 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RegattasResource.java @@ -1,8 +1,5 @@ package com.sap.sailing.server.gateway.jaxrs.api; -import java.io.BufferedWriter; -import java.io.OutputStream; -import java.io.OutputStreamWriter; import java.io.Serializable; import java.net.URI; import java.net.URISyntaxException; @@ -36,7 +33,6 @@ import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.StreamingOutput; import org.apache.commons.lang.StringEscapeUtils; import org.apache.shiro.SecurityUtils; @@ -93,6 +89,7 @@ import com.sap.sailing.domain.common.security.SecuredDomainType; import com.sap.sailing.domain.common.tracking.GPSFix; import com.sap.sailing.domain.common.tracking.GPSFixMoving; import com.sap.sailing.domain.leaderboard.Leaderboard; +import com.sap.sailing.domain.leaderboard.caching.LeaderboardDTOCalculationReuseCache; import com.sap.sailing.domain.polars.NotEnoughDataHasBeenAddedException; import com.sap.sailing.domain.racelogtracking.DeviceMappingWithRegattaLogEvent; import com.sap.sailing.domain.racelogtracking.impl.SmartphoneUUIDIdentifierImpl; @@ -106,6 +103,7 @@ import com.sap.sailing.domain.tracking.RaceWindCalculator; import com.sap.sailing.domain.tracking.TrackedLeg; import com.sap.sailing.domain.tracking.TrackedLegOfCompetitor; import com.sap.sailing.domain.tracking.TrackedRace; +import com.sap.sailing.domain.tracking.WindLegTypeAndLegBearingAndORCPerformanceCurveCache; import com.sap.sailing.domain.tracking.WindPositionMode; import com.sap.sailing.domain.tracking.WindSummary; import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; @@ -921,7 +919,7 @@ public class RegattasResource extends AbstractSailingServerResource { } } jsonRace.put("competitors", jsonCompetitors); - response = Response.ok((StreamingOutput) (OutputStream output)->jsonRace.writeJSONString(new BufferedWriter(new OutputStreamWriter(output)))).build(); + response = Response.ok(streamingOutput(jsonRace)).build(); } } return response; @@ -1970,7 +1968,8 @@ public class RegattasResource extends AbstractSailingServerResource { TrackedRace trackedRace = findTrackedRace(regattaName, raceName); TimePoint timePoint = trackedRace.getTimePointOfNewestEvent() == null ? MillisecondsTimePoint.now() : trackedRace.getTimePointOfNewestEvent(); - final RankingInfo rankingInfo = trackedRace.getRankingMetric().getRankingInfo(timePoint); + final WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache = new LeaderboardDTOCalculationReuseCache(timePoint); + final RankingInfo rankingInfo = trackedRace.getRankingMetric().getRankingInfo(timePoint, cache); JSONObject jsonRaceResults = new JSONObject(); jsonRaceResults.put("name", trackedRace.getRace().getName()); jsonRaceResults.put("regatta", regatta.getName()); @@ -2080,12 +2079,12 @@ public class RegattasResource extends AbstractSailingServerResource { } } Duration gapToLeaderDuration = trackedLegOfCompetitor.getGapToLeader(timePoint, - rankingInfo, WindPositionMode.LEG_MIDDLE); + WindPositionMode.LEG_MIDDLE, rankingInfo, cache); jsonCompetitorInLeg.put("gapToLeader-s", gapToLeaderDuration != null ? gapToLeaderDuration.asSeconds() : 0.0); Distance gapToLeaderDistance = trackedLegOfCompetitor .getWindwardDistanceToCompetitorFarthestAhead(timePoint, - WindPositionMode.LEG_MIDDLE, rankingInfo); + WindPositionMode.LEG_MIDDLE, rankingInfo, cache); jsonCompetitorInLeg.put("gapToLeader-m", gapToLeaderDistance != null ? gapToLeaderDistance.getMeters() : 0.0); jsonCompetitorInLeg.put("started", trackedLegOfCompetitor.hasStartedLeg(timePoint)); @@ -2131,13 +2130,12 @@ public class RegattasResource extends AbstractSailingServerResource { TrackedRace trackedRace = findTrackedRace(regattaName, raceName); Course course = trackedRace.getRace().getCourse(); Waypoint lastWaypoint = course.getLastWaypoint(); - TimePoint timePoint = MillisecondsTimePoint.now().minus(trackedRace.getDelayToLiveInMillis()); - final RankingInfo rankingInfo = trackedRace.getRankingMetric().getRankingInfo(timePoint); + final WindLegTypeAndLegBearingAndORCPerformanceCurveCache cache = new LeaderboardDTOCalculationReuseCache(timePoint); + final RankingInfo rankingInfo = trackedRace.getRankingMetric().getRankingInfo(timePoint, cache); JSONObject jsonLiveData = new JSONObject(); jsonLiveData.put("name", trackedRace.getRace().getName()); jsonLiveData.put("regatta", regatta.getName()); - if (trackedRace.getStartOfRace() != null) { TimePoint startOfRace = trackedRace.getStartOfRace(); TimePoint now = MillisecondsTimePoint.now(); @@ -2150,10 +2148,10 @@ public class RegattasResource extends AbstractSailingServerResource { } } JSONArray jsonCompetitors = new JSONArray(); - List competitorsFromBestToWorst = trackedRace.getCompetitorsFromBestToWorst(timePoint); + List competitorsFromBestToWorst = trackedRace.getCompetitorsFromBestToWorst(timePoint, cache); Map overallRankPerCompetitor = new HashMap<>(); if (leaderboard != null) { - List overallRanking = leaderboard.getCompetitorsFromBestToWorst(timePoint); + List overallRanking = leaderboard.getCompetitorsFromBestToWorst(timePoint, cache); Integer overallRank = 1; for (Competitor competitor : overallRanking) { if (getSecurityService().hasCurrentUserOneOfExplicitPermissions(competitor, @@ -2167,7 +2165,6 @@ public class RegattasResource extends AbstractSailingServerResource { if (getSecurityService().hasCurrentUserOneOfExplicitPermissions(competitor, SecuredSecurityTypes.PublicReadableActions.READ_AND_READ_PUBLIC_ACTIONS)) { JSONObject jsonCompetitorInLeg = new JSONObject(); - if (topN != null && topN > 0 && rank > topN) { break; } @@ -2199,8 +2196,7 @@ public class RegattasResource extends AbstractSailingServerResource { jsonCompetitorInLeg.put("leg", indexOfWaypoint + 1); Distance distanceTraveled = currentLegOfCompetitor.getDistanceTraveled(timePoint); if (distanceTraveled != null) { - jsonCompetitorInLeg.put("distanceTraveled-m", - roundDouble(distanceTraveled.getMeters(), 2)); + jsonCompetitorInLeg.put("distanceTraveled-m", roundDouble(distanceTraveled.getMeters(), 2)); } Distance distanceTraveledConsideringGateStart = currentLegOfCompetitor .getDistanceTraveledConsideringGateStart(timePoint); @@ -2208,16 +2204,14 @@ public class RegattasResource extends AbstractSailingServerResource { jsonCompetitorInLeg.put("distanceTraveledConsideringGateStart-m", roundDouble(distanceTraveledConsideringGateStart.getMeters(), 2)); } - - Duration gapToLeader = currentLegOfCompetitor.getGapToLeader(timePoint, rankingInfo, - WindPositionMode.LEG_MIDDLE); + Duration gapToLeader = currentLegOfCompetitor.getGapToLeader(timePoint, + WindPositionMode.LEG_MIDDLE, rankingInfo, cache); if (gapToLeader != null) { jsonCompetitorInLeg.put("gapToLeader-s", roundDouble(gapToLeader.asSeconds(), 2)); } - Distance windwardDistanceToCompetitorFarthestAhead = currentLegOfCompetitor .getWindwardDistanceToCompetitorFarthestAhead(timePoint, - WindPositionMode.LEG_MIDDLE, rankingInfo); + WindPositionMode.LEG_MIDDLE, rankingInfo, cache); if (windwardDistanceToCompetitorFarthestAhead != null) { jsonCompetitorInLeg.put("gapToLeader-m", roundDouble(windwardDistanceToCompetitorFarthestAhead.getMeters(), 2)); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java index 3da4882fd37..60c01dd6e2a 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java @@ -31,9 +31,7 @@ public class RestApiApplication extends Application { classes.add(StatisticsResource.class); classes.add(WindResource.class); classes.add(MarkResource.class); - classes.add(PreferencesResource.class); classes.add(TagsResource.class); - classes.add(UserGroupsResource.class); classes.add(StatusResource.class); classes.add(TrackedEventsResource.class); classes.add(TrackingDevicesResource.class); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java index df26cab7eec..99a8a667f76 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TrackedEventsResource.java @@ -5,6 +5,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.UUID; import java.util.function.Function; +import java.util.logging.Logger; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -40,6 +41,8 @@ import com.sap.sse.security.shared.impl.User; @Path("/v1/trackedevents/") public class TrackedEventsResource extends AbstractSailingServerResource { + protected static final Logger logger = Logger.getLogger(TrackedEventsResource.class.getName()); + private static final String KEY_QUERY_INCLUDE_ARCHIVED = "includeArchived"; private static final String KEY_LEADERBOARD_NAME = "leaderboardName"; @@ -69,6 +72,12 @@ public class TrackedEventsResource extends AbstractSailingServerResource { if (prefs != null) { // iterate all stored tracked events for (final TrackedEventPreference pref : prefs.getTrackedEvents()) { + // TODO: Temporary precaution for unexpected null values. + // Note: There should not be any null values in the Collection in the first place. + if (pref == null) { + logger.warning("null entry in TrackedEventPreferences list: " + prefs.toString()); + continue; + } if (!includeArchived && pref.getIsArchived()) { // skip, if event is archived and should be filtered out continue; diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/UserGroupsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/UserGroupsResource.java deleted file mode 100644 index 815c07d9394..00000000000 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/UserGroupsResource.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.sap.sailing.server.gateway.jaxrs.api; - -import java.util.Map.Entry; -import java.util.UUID; - -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Response; - -import org.apache.shiro.authz.AuthorizationException; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.ParseException; - -import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; -import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; -import com.sap.sse.security.shared.RoleDefinition; -import com.sap.sse.security.shared.impl.Ownership; -import com.sap.sse.security.shared.impl.User; -import com.sap.sse.security.shared.impl.UserGroup; - -@Path("/v1/usergroups") -public class UserGroupsResource extends AbstractSailingServerResource { - @GET - @Produces("application/json;charset=UTF-8") - public Response getUserGroupsCurrentUserIsPartOf() - throws ParseException, JsonDeserializationException { - Response response = null; - User user = getService().getSecurityService().getCurrentUser(); - if (user != null) { - JSONObject root = new JSONObject(); - JSONArray groups = new JSONArray(); - root.put("groupsUserIsPartOf", groups); - for (UserGroup group : user.getUserGroups()) { - JSONObject groupJson = new JSONObject(); - groupJson.put("uuid", group.getId().toString()); - groupJson.put("name", group.getName()); - groups.add(groupJson); - } - response = Response.ok(streamingOutput(root)).build(); - } else { - response = Response.status(401).build(); - } - return response; - } - - @GET - @Path("{userGroupId}/roles") - @Produces("application/json;charset=UTF-8") - public Response getUserGroup(@PathParam("userGroupId") UUID userGroupId) - throws ParseException, JsonDeserializationException { - Response response = null; - UserGroup userGroup = getService().getSecurityService().getUserGroup(userGroupId); - getSecurityService().checkCurrentUserReadPermission(userGroup); - if (userGroup != null) { - JSONObject root = new JSONObject(); - root.put("uuid", userGroup.getId().toString()); - root.put("name", userGroup.getName()); - JSONArray roles = new JSONArray(); - for (Entry roleDef : userGroup.getRoleDefinitionMap().entrySet()) { - JSONObject role = new JSONObject(); - role.put("roleId", roleDef.getKey().getId().toString()); - role.put("name", roleDef.getKey().getName()); - role.put("all", roleDef.getValue()); - roles.add(role); - } - root.put("roles", roles); - response = Response.ok(streamingOutput(root)).build(); - } else { - response = Response.status(401).build(); - } - return response; - } - - @DELETE - @Path("{userGroupId}/roles") - @Produces("application/json;charset=UTF-8") - public Response getUserGroup(@PathParam("userGroupId") UUID userGroupId, @QueryParam("roleId") UUID roleId) - throws ParseException, JsonDeserializationException { - Response response = null; - UserGroup userGroup = getService().getSecurityService().getUserGroup(userGroupId); - RoleDefinition roleDefinitions = getSecurityService().getRoleDefinition(roleId); - if (userGroup != null && roleDefinitions != null) { - getSecurityService().checkCurrentUserUpdatePermission(userGroup); - // do not check read on role, to allow removal of not anymore visible roles - getSecurityService().removeRoleDefintionFromUserGroup(userGroup, roleDefinitions); - response = Response.ok().build(); - } else { - response = Response.status(401).build(); - } - return response; - } - - @PUT - @Path("{userGroupId}/roles") - @Produces("application/json;charset=UTF-8") - public Response addRoleToUserGroup(@PathParam("userGroupId") UUID userGroupId, @QueryParam("roleId") UUID roleId, - @QueryParam("forAll") Boolean forAll) throws ParseException, JsonDeserializationException { - Response response = null; - UserGroup userGroup = getService().getSecurityService().getUserGroup(userGroupId); - RoleDefinition roleDefinition = getSecurityService().getRoleDefinition(roleId); - if (userGroup != null && roleDefinition != null) { - getSecurityService().checkCurrentUserUpdatePermission(userGroup); - getSecurityService().checkCurrentUserReadPermission(roleDefinition); - if (!getSecurityService().hasCurrentUserMetaPermissionsOfRoleDefinitionWithQualification(roleDefinition, - new Ownership(null, userGroup))) { - throw new AuthorizationException("Not permitted to add role definition to group"); - } - getSecurityService().putRoleDefinitionToUserGroup(userGroup, roleDefinition, forAll); - response = Response.ok().build(); - } else { - response = Response.status(401).build(); - } - return response; - } -} \ No newline at end of file diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java index 9886c388b04..e15ffc6de4d 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/trackfiles/impl/ExpeditionAllInOneImporter.java @@ -71,6 +71,7 @@ import com.sap.sailing.domain.leaderboard.Leaderboard; import com.sap.sailing.domain.leaderboard.LeaderboardGroup; import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; import com.sap.sailing.domain.leaderboard.ScoringScheme; +import com.sap.sailing.domain.leaderboard.impl.LeaderboardGroupImpl; import com.sap.sailing.domain.racelogtracking.RaceLogTrackingAdapter; import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifier; import com.sap.sailing.domain.trackfiles.TrackFileImportDeviceIdentifierImpl; @@ -772,16 +773,29 @@ public class ExpeditionAllInOneImporter { return regatta; } - private void createLeaderboardGroupAndAddItToTheEvent(final String leaderboardGroupName, final String regattaNameAndleaderboardName, - final String description, final Event event) { + private void createLeaderboardGroupAndAddItToTheEvent(final String leaderboardGroupName, + final String regattaNameAndleaderboardName, final String description, final Event event) { UUID newGroupid = UUID.randomUUID(); - final LeaderboardGroup leaderboardGroup = service - .apply(new CreateLeaderboardGroup(newGroupid, leaderboardGroupName, - description, null, false, Collections.singletonList(regattaNameAndleaderboardName), null, null)); + final LeaderboardGroup leaderboardGroup = securityService + .setOwnershipCheckPermissionForObjectCreationAndRevertOnError(SecuredDomainType.LEADERBOARD_GROUP, + LeaderboardGroupImpl.getTypeRelativeObjectIdentifier(newGroupid), + /* securityDisplayName */ null, new Callable() { + @Override + public LeaderboardGroup call() throws Exception { + CreateLeaderboardGroup createLeaderboardGroup = new CreateLeaderboardGroup(newGroupid, + leaderboardGroupName, description, /* displayName */ null, + /* displayGroupsInReverseOrder */ false, + Collections.singletonList(regattaNameAndleaderboardName), + /* overallLeaderboardDiscardThresholds */ null, + /* overallLeaderboardScoringSchemeType */ null); + return service.apply(createLeaderboardGroup); + } + }); service.apply(new UpdateEvent(event.getId(), event.getName(), event.getDescription(), event.getStartDate(), event.getEndDate(), event.getVenue().getName(), event.isPublic(), Collections.singleton(leaderboardGroup.getId()), event.getOfficialWebsiteURL(), event.getBaseURL(), - event.getSailorsInfoWebsiteURLs(), event.getImages(), event.getVideos(), event.getWindFinderReviewedSpotsCollectionIds())); + event.getSailorsInfoWebsiteURLs(), event.getImages(), event.getVideos(), + event.getWindFinderReviewedSpotsCollectionIds())); } private DynamicTrackedRace createTrackedRaceAndSetupRaceTimes(final List errors, diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorGetDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorGetDoc.html index 7c2421c7645..ed705f0400f 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorGetDoc.html +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorGetDoc.html @@ -10,7 +10,10 @@

    SAP Sailing Analytics Webservices API Version 1.0

    URL: /api/v1/competitors/{id}

    - +

    This API contains deprecated fields. These fields will be removed in near future.
    + The deprecated fields are marked as deprecated in the example below.
    +

    +
    Description:

    Gets the details of a competitor


    @@ -38,8 +41,64 @@ Example: - http://www.sapsailing.com/sailingserver/api/v1/competitors/bba11294-9930-11e0-85be-406186cbf87c - + http://www.sapsailing.com/sailingserver/api/v1/competitors/bba11294-9930-11e0-85be-406186cbf87c
    + Example result:
    +
    +{
    +    "idtype": "java.util.UUID",
    +    "id": "d455db1b-fd52-4144-a8e2-3eed503467b0",
    +    "name": "Dagobert",
    +    "shortName": "D",
    +    "sailID": null,
    +    "displayColor": "#ABCDEF",
    +    "searchTag": "atag",
    +    "nationality": "GER",
    +    "nationalityISO2": "DE",
    +    "nationalityISO3": "DEU",
    +    "flagImageUri": "http:\/\/flagimage.url",
    +    "team": {
    +        "name": "Donald Duck",
    +        "coach": null,
    +        "sailors": [
    +            {
    +                "name": "Donald Duck",
    +                "description": null,
    +                "nationality": {
    +                    "IOC": "GER"
    +                }
    +            }
    +        ],
    +        "imageUri": "http:\/\/teamimage.url"
    +    },
    +    "boat": {
    +        "idtype": "java.util.UUID",
    +        "id": "35712e80-578f-418d-bcbd-9a3d0e391982",
    +        "name": "Donald Duck",
    +        "sailId": null,
    +        "color": null,
    +        "boatClass": {
    +            "name": "GC 32",
    +            "typicallyStartsUpwind": false,
    +            "hullLengthInMeters": 10.0,
    +            "hullBeamInMeters": 6.0,
    +            "displayName": "GC 32",
    +            "iconUrl": "\/gwt\/src\/main\/resources\/com\/sap\/sailing\/gwt\/ui\/client\/images\/boatclass\/GC_32.png",
    +            "aliasNames": [
    +                "GC32",
    +                "GC-32"
    +            ]
    +        }
    +    },
    +    "timeOnTimeFactor": 2.4,
    +    "timeOnDistanceAllowanceInSecondsPerNauticalMile": 10000.0,
    +    deprecated - use "displayColor" instead color": "#ABCDEF",
    +    deprecated - use "nationalityISO2" instead "countryCode": "DE",
    +    deprecated - use "flagImageUri" instead "flagImage": "http:\/\/flagimage.url",
    +    deprecated - use "team"/"imageUri" instead"teamImageUri": "http:\/\/teamimage.url"
    +}
    +    
    + +
    Back to Web Service Overview diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorUpdateDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorUpdateDoc.html new file mode 100644 index 00000000000..df345d5a832 --- /dev/null +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/competitorUpdateDoc.html @@ -0,0 +1,64 @@ + + + + + + + + SAP Sailing Analytics Webservices API Version 1.0 + + +

    SAP Sailing Analytics Webservices API Version 1.0

    +

    URL: /api/v1/competitors/{id}

    +

    This API contains deprecated fields in the result. These fields will be removed in near future.
    + Please see /api/v1/competitors/{id} for detailed information!
    .
    +

    +
    +Description: +

    Updates the details of a competitor. Only optional parameters that are passed by the json payload are updated.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Webservice Type:REST
    Input format:Json
    Output format:Json
    Mandatory parameters:None
    Optional parameters: + name: Name of Competitor
    + shortName: Short name of the competitor
    + email: EMail-Address of the competitor
    + nationality: Three-letter IOC nationality acronym
    + timeOnTimeFactor: default time-on-time handicap factor
    + timeOnDistanceAllowanceInSecondsPerNauticalMile: default time-on-distance time allowance for this competitor, used in handicap regattas
    + flagImageUri: URI of flag image
    + teamImageUri: URI of team image
    + searchTag: Search tag
    +
    Request method:PUT
    Example:http://www.sapsailing.com/sailingserver/api/v1/competitors/bba11294-9930-11e0-85be-406186cbf87c
    +
    +
    +Back to Web Service Overview + + diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/eventsGetDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/eventsGetDoc.html index 5a2860399a7..bb405d73975 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/eventsGetDoc.html +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/eventsGetDoc.html @@ -29,7 +29,7 @@ Optional parameters: - None + showNonPublic: If true the output contains also the non-public events. Request method: diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html index 4773060c584..19b4a11b618 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/index.html @@ -45,7 +45,7 @@ name to make sure you get to the event you're interested in. Migrates an existing event - /api/v1/events + /api/v1/events Gets all events @@ -281,6 +281,10 @@ name to make sure you get to the event you're interested in. /api/v1/competitors/{id} Gets the details of a competitor + + /api/v1/competitors/{id} + Updates the details of a competitor + /api/v1/competitors/{id}/team Gets the details of a competitor's team @@ -348,22 +352,6 @@ name to make sure you get to the event you're interested in. /api/v1/{leaderboard}/{racecolumn}/{fleet}/tags Gets, creates, updates and deletes tags. - - /api/v1/preferences/{SETTINGS_KEY} - Stores a document into the preferences of a user - - - /api/v1/preferences/{SETTINGS_KEY} - Retrives a document that was stored into the preferences of a user - - - /api/v1/preferences/{SETTINGS_KEY} - Removes a document from the preferences of a user - - - /api/v1/usergroups/ - Lists all usergroups and their id's the current user is part of, required to obtain id's for migration for example - /api/v1/status Returns a status description for the "RacingEventService" core service diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCompetitorGetDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCompetitorGetDoc.html index 8f1de4cb239..7b2b182308c 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCompetitorGetDoc.html +++ b/java/com.sap.sailing.server.gateway/webservices/api/v1/leaderboardCompetitorGetDoc.html @@ -10,6 +10,9 @@

    SAP Sailing Analytics Webservices API Version 1.0

    URL: /api/v1/leaderboards/{name}/competitors/{competitorId}

    +

    This API contains deprecated fields. These fields will be removed in near future.
    + The deprecated fields are marked as deprecated in the example below.
    +

    Description:

    Gets the leaderboard-specific version of a competitor

    @@ -37,7 +40,63 @@ Example: - https://www.sapsailing.com/sailingserver/api/v1/leaderboards/505%20Worlds%202013/competitors/ccf89da2-ac8c-11e2-89c0-10bf48d758ce + https://www.sapsailing.com/sailingserver/api/v1/leaderboards/505%20Worlds%202013/competitors/ccf89da2-ac8c-11e2-89c0-10bf48d758ce
    + Example result:
    +
    +{
    +    "idtype": "java.util.UUID",
    +    "id": "d455db1b-fd52-4144-a8e2-3eed503467b0",
    +    "name": "Dagobert",
    +    "shortName": "D",
    +    "sailID": null,
    +    "displayColor": "#ABCDEF",
    +    "searchTag": "atag",
    +    "nationality": "GER",
    +    "nationalityISO2": "DE",
    +    "nationalityISO3": "DEU",
    +    "flagImageUri": "http:\/\/flagimage.url",
    +    "team": {
    +        "name": "Donald Duck",
    +        "coach": null,
    +        "sailors": [
    +            {
    +                "name": "Donald Duck",
    +                "description": null,
    +                "nationality": {
    +                    "IOC": "GER"
    +                }
    +            }
    +        ],
    +        "imageUri": "http:\/\/teamimage.url"
    +    },
    +    "boat": {
    +        "idtype": "java.util.UUID",
    +        "id": "35712e80-578f-418d-bcbd-9a3d0e391982",
    +        "name": "Donald Duck",
    +        "sailId": null,
    +        "color": null,
    +        "boatClass": {
    +            "name": "GC 32",
    +            "typicallyStartsUpwind": false,
    +            "hullLengthInMeters": 10.0,
    +            "hullBeamInMeters": 6.0,
    +            "displayName": "GC 32",
    +            "iconUrl": "\/gwt\/src\/main\/resources\/com\/sap\/sailing\/gwt\/ui\/client\/images\/boatclass\/GC_32.png",
    +            "aliasNames": [
    +                "GC32",
    +                "GC-32"
    +            ]
    +        }
    +    },
    +    "timeOnTimeFactor": 2.4,
    +    "timeOnDistanceAllowanceInSecondsPerNauticalMile": 10000.0,
    +    deprecated - use "displayColor" instead color": "#ABCDEF",
    +    deprecated - use "nationalityISO2" instead "countryCode": "DE",
    +    deprecated - use "flagImageUri" instead "flagImage": "http:\/\/flagimage.url",
    +    deprecated - use "team"/"imageUri" instead"teamImageUri": "http:\/\/teamimage.url"
    +}
    +        
    +
    diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v2/leaderboardGetDoc.html b/java/com.sap.sailing.server.gateway/webservices/api/v2/leaderboardGetDoc.html index a67978b8ac3..dfd6e9a2a5a 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v2/leaderboardGetDoc.html +++ b/java/com.sap.sailing.server.gateway/webservices/api/v2/leaderboardGetDoc.html @@ -29,7 +29,9 @@ The supported race detail constants right now are:
    - CURRENT_LEG
    - LEG_VELOCITY_MADE_GOOD_IN_KNOTS
    - LEG_WINDWARD_DISTANCE_TO_GO_IN_METERS
    -- OVERALL_MAXIMUM_SPEED_OVER_GROUND_IN_KNOTS
    +- OVERALL_MAXIMUM_SPEED_OVER_GROUND_IN_KNOTS +- OVERALL_TIME_ON_TIME_FACTOR
    +- OVERALL_TIME_ON_DISTANCE_ALLOWANCE_IN_SECONDS_PER_NAUTICAL_MILE
    There is also the 'ALL' shortcut constant which can be used to get all available race details without the need to enumerate them.

    @@ -81,7 +83,7 @@ There is also the 'ALL' shortcut constant which can be used to get all available + use "ALL" to get all detail types supported. Specify multiple times to select more than one detail field. diff --git a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/interfaces/RacingEventService.java b/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/interfaces/RacingEventService.java index 9afbb8b2ab6..1eb6bf2212b 100644 --- a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/interfaces/RacingEventService.java +++ b/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/interfaces/RacingEventService.java @@ -73,6 +73,7 @@ import com.sap.sailing.domain.leaderboard.LeaderboardRegistry; import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; import com.sap.sailing.domain.leaderboard.RegattaLeaderboardWithEliminations; import com.sap.sailing.domain.leaderboard.ScoringScheme; +import com.sap.sailing.domain.leaderboard.impl.DelegatingRegattaLeaderboardWithCompetitorElimination; import com.sap.sailing.domain.persistence.DomainObjectFactory; import com.sap.sailing.domain.persistence.MongoObjectFactory; import com.sap.sailing.domain.polars.PolarDataService; @@ -234,16 +235,13 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch RegattaLeaderboardWithEliminations addRegattaLeaderboardWithEliminations(String leaderboardName, String leaderboardDisplayName, RegattaLeaderboard fullRegattaLeaderboard); - void removeLeaderboard(String leaderboardName); - /** - * Renames a leaderboard. If a leaderboard by the name oldName does not exist in {@link #getLeaderboards()}, - * or if a leaderboard with the name newName already exists, an {@link IllegalArgumentException} is thrown. - * If the method completes normally, the rename has been successful, and the leaderboard previously obtained by calling - * {@link #getLeaderboardByName(String) getLeaderboardByName(oldName)} can now be obtained by calling - * {@link #getLeaderboardByName(String) getLeaderboardByName(newName)}. + * Removes the leaderboard specified by {@code leaderboardName} as well as all delegating leaderboards that reference it, + * in particular those {@link DelegatingRegattaLeaderboardWithCompetitorElimination} which which the leaderboard specified + * by {@code leaderboardName} was their underlying regatta leaderboard. If no leaderboard named as specified by the + * {@code leaderboardName} parameter exists, this method has no effect. */ - void renameLeaderboard(String oldName, String newName); + void removeLeaderboard(String leaderboardName); RaceColumn addColumnToLeaderboard(String columnName, String leaderboardName, boolean medalRace); @@ -314,16 +312,6 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch */ void removeLeaderboardGroup(String groupName); - /** - * Renames the group with the name oldName to the newName.
    - * If there's no group with the name oldName or there's already a group with the name - * newName a {@link IllegalArgumentException} is thrown. - * - * @param oldName The old name of the group - * @param newName The new name of the group - */ - void renameLeaderboardGroup(String oldName, String newName); - /** * Updates the group data in the persistant store. */ @@ -736,8 +724,6 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch ClassLoader getCombinedMasterDataClassLoader(); - Iterable getCompetitorInOrderOfWindwardDistanceTraveledFarthestFirst(TrackedRace trackedRace, TimePoint timePoint); - /** * Gets the {@link RaceTracker} associated with a given {@link RegattaAndRaceIdentifier}. If the {@link RaceTracker} * is already available, the {@code callback} is invoked immediately. If the {@link RaceTracker} isn't available @@ -847,15 +833,6 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch */ Map> getKnownAnniversaries(); - /** - * Provides the number, {@link DetailedRaceInfo race} and {@link AnniversaryType type} information for the latest - * anniversary race. - * - * @return {@link Triple} containing the last anniversary number, {@link DetailedRaceInfo race} and - * {@link AnniversaryType type}, or null if there's no anniversary so far - */ - Triple getLastAnniversary(); - /** * Returns the {@link AnniversaryRaceDeterminator} used by this service. This is needed for replication for * anniversary races only. @@ -956,4 +933,8 @@ public interface RacingEventService extends TrackedRegattaRegistry, RegattaFetch final boolean compress, final boolean exportWind, final boolean exportDeviceConfigurations, String targetServerUsername, String targetServerPassword, String targetServerBearerToken, final boolean exportTrackedRacesAndStartTracking, final UUID importOperationId) throws IllegalArgumentException; + + void addOrReplaceExpeditionDeviceConfiguration(UUID deviceConfigurationId, String name, Integer expeditionBoatId); + + void removeExpeditionDeviceConfiguration(UUID deviceUuid); } diff --git a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/AddOrReplaceExpeditionDeviceConfiguration.java b/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/AddOrReplaceExpeditionDeviceConfiguration.java new file mode 100755 index 00000000000..4cbddb85cdd --- /dev/null +++ b/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/AddOrReplaceExpeditionDeviceConfiguration.java @@ -0,0 +1,36 @@ +package com.sap.sailing.server.operationaltransformation; + +import java.util.UUID; + +import com.sap.sailing.server.interfaces.RacingEventService; +import com.sap.sailing.server.interfaces.RacingEventServiceOperation; + +public class AddOrReplaceExpeditionDeviceConfiguration extends AbstractRacingEventServiceOperation { + private static final long serialVersionUID = 2781190033335859683L; + private final UUID deviceUuid; + private final String name; + private final Integer expeditionBoatId; + + public AddOrReplaceExpeditionDeviceConfiguration(UUID deviceUuid, String name, Integer expeditionBoatId) { + super(); + this.deviceUuid = deviceUuid; + this.name = name; + this.expeditionBoatId = expeditionBoatId; + } + + @Override + public Void internalApplyTo(RacingEventService toState) { + toState.addOrReplaceExpeditionDeviceConfiguration(deviceUuid, name, expeditionBoatId); + return null; + } + + @Override + public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { + return null; + } + + @Override + public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { + return null; + } +} diff --git a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/MoveColumnInSeriesDown.java b/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/MoveColumnInSeriesDown.java deleted file mode 100755 index 58524d9f306..00000000000 --- a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/MoveColumnInSeriesDown.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.sap.sailing.server.operationaltransformation; - -import com.sap.sailing.domain.base.Series; -import com.sap.sailing.domain.common.RegattaIdentifier; -import com.sap.sailing.server.interfaces.RacingEventService; -import com.sap.sailing.server.interfaces.RacingEventServiceOperation; - -public class MoveColumnInSeriesDown extends AbstractColumnInSeriesOperation { - private static final long serialVersionUID = 1055871052852494542L; - - public MoveColumnInSeriesDown(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) { - super(regattaIdentifier, seriesName, columnName); - } - - @Override - public Void internalApplyTo(RacingEventService toState) throws Exception { - Series series = getSeries(toState); - if (series != null) { - series.moveRaceColumnDown(getColumnName()); - if (series.getRegatta().isPersistent()) { - toState.updateStoredRegatta(series.getRegatta()); - } - } - return null; - } - - @Override - public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { - // TODO Auto-generated method stub - return null; - } - - @Override - public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/MoveColumnInSeriesUp.java b/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/MoveColumnInSeriesUp.java deleted file mode 100755 index bc6044abcd6..00000000000 --- a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/MoveColumnInSeriesUp.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.sap.sailing.server.operationaltransformation; - -import com.sap.sailing.domain.base.Series; -import com.sap.sailing.domain.common.RegattaIdentifier; -import com.sap.sailing.server.interfaces.RacingEventService; -import com.sap.sailing.server.interfaces.RacingEventServiceOperation; - -public class MoveColumnInSeriesUp extends AbstractColumnInSeriesOperation { - private static final long serialVersionUID = -4111158026632514462L; - - public MoveColumnInSeriesUp(RegattaIdentifier regattaIdentifier, String seriesName, String columnName) { - super(regattaIdentifier, seriesName, columnName); - } - - @Override - public Void internalApplyTo(RacingEventService toState) throws Exception { - Series series = getSeries(toState); - if (series != null) { - series.moveRaceColumnUp(getColumnName()); - if (series.getRegatta().isPersistent()) { - toState.updateStoredRegatta(series.getRegatta()); - } - } - return null; - } - - @Override - public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { - // TODO Auto-generated method stub - return null; - } - - @Override - public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/RemoveExpeditionDeviceConfiguration.java b/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/RemoveExpeditionDeviceConfiguration.java new file mode 100755 index 00000000000..ff40507bd51 --- /dev/null +++ b/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/RemoveExpeditionDeviceConfiguration.java @@ -0,0 +1,32 @@ +package com.sap.sailing.server.operationaltransformation; + +import java.util.UUID; + +import com.sap.sailing.server.interfaces.RacingEventService; +import com.sap.sailing.server.interfaces.RacingEventServiceOperation; + +public class RemoveExpeditionDeviceConfiguration extends AbstractRacingEventServiceOperation { + private static final long serialVersionUID = 2781190033335859683L; + private final UUID deviceUuid; + + public RemoveExpeditionDeviceConfiguration(UUID deviceUuid) { + super(); + this.deviceUuid = deviceUuid; + } + + @Override + public Void internalApplyTo(RacingEventService toState) { + toState.removeExpeditionDeviceConfiguration(deviceUuid); + return null; + } + + @Override + public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { + return null; + } + + @Override + public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { + return null; + } +} diff --git a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/RenameLeaderboard.java b/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/RenameLeaderboard.java deleted file mode 100755 index 5c854b1afd4..00000000000 --- a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/RenameLeaderboard.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.sap.sailing.server.operationaltransformation; - -import com.sap.sailing.server.interfaces.RacingEventService; -import com.sap.sailing.server.interfaces.RacingEventServiceOperation; - -public class RenameLeaderboard extends AbstractLeaderboardOperation { - private static final long serialVersionUID = 8874599127010526971L; - - private final String newLeaderboardName; - - public RenameLeaderboard(String leaderboardName, String newLeaderboardName) { - super(leaderboardName); - this.newLeaderboardName = newLeaderboardName; - } - - @Override - public Void internalApplyTo(RacingEventService toState) { - if (!getLeaderboardName().equals(newLeaderboardName)) { - toState.renameLeaderboard(getLeaderboardName(), newLeaderboardName); - } - return null; - } - - @Override - public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { - // TODO Auto-generated method stub - return null; - } - - @Override - public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/RenameLeaderboardGroup.java b/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/RenameLeaderboardGroup.java deleted file mode 100755 index 5adeb74e8c2..00000000000 --- a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/RenameLeaderboardGroup.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.sap.sailing.server.operationaltransformation; - -import com.sap.sailing.server.interfaces.RacingEventService; -import com.sap.sailing.server.interfaces.RacingEventServiceOperation; - -public class RenameLeaderboardGroup extends AbstractLeaderboardGroupOperation { - private static final long serialVersionUID = -5007784579411727148L; - private final String newLeaderboardGroupName; - - public RenameLeaderboardGroup(String leaderboardGroupName, String newLeaderboardGroupName) { - super(leaderboardGroupName); - this.newLeaderboardGroupName = newLeaderboardGroupName; - } - - @Override - public Void internalApplyTo(RacingEventService toState) { - // TODO see bug 729: try to move addLeaderboardGroup implementation here and synthesize and apply this operation there - if (!getLeaderboardGroupName().equals(newLeaderboardGroupName)) { - toState.renameLeaderboardGroup(getLeaderboardGroupName(), newLeaderboardGroupName); - } - return null; - } - - @Override - public RacingEventServiceOperation transformClientOp(RacingEventServiceOperation serverOp) { - // TODO Auto-generated method stub - return null; - } - - @Override - public RacingEventServiceOperation transformServerOp(RacingEventServiceOperation clientOp) { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/UpdateLeaderboard.java b/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/UpdateLeaderboard.java index 6be9f9785ca..0eae043eafa 100755 --- a/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/UpdateLeaderboard.java +++ b/java/com.sap.sailing.server.interface/src/com/sap/sailing/server/operationaltransformation/UpdateLeaderboard.java @@ -1,7 +1,9 @@ package com.sap.sailing.server.operationaltransformation; import java.io.Serializable; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import com.sap.sailing.domain.leaderboard.FlexibleLeaderboard; import com.sap.sailing.domain.leaderboard.Leaderboard; @@ -13,18 +15,17 @@ import com.sap.sse.common.Util; public class UpdateLeaderboard extends AbstractLeaderboardOperation { private static final long serialVersionUID = -8040361040050151768L; - private final String newLeaderboardName; private final String newLeaderboardDisplayName; private final int[] newDiscardingThresholds; - private final Iterable newCourseAreaIds; + private final Collection newCourseAreaIds; - public UpdateLeaderboard(String leaderboardName, String newLeaderboardName, String newLeaderboardDisplayName, - int[] newDiscardingThresholds, Iterable newCourseAreaIds) { + public UpdateLeaderboard(String leaderboardName, String newLeaderboardDisplayName, int[] newDiscardingThresholds, + Iterable newCourseAreaIds) { super(leaderboardName); - this.newLeaderboardName = newLeaderboardName; this.newLeaderboardDisplayName = newLeaderboardDisplayName; this.newDiscardingThresholds = newDiscardingThresholds; - this.newCourseAreaIds = newCourseAreaIds; + this.newCourseAreaIds = new ArrayList<>(); + Util.addAll(newCourseAreaIds, this.newCourseAreaIds); } @Override @@ -41,10 +42,7 @@ public class UpdateLeaderboard extends AbstractLeaderboardOperation @Override public Leaderboard internalApplyTo(RacingEventService toState) { - if (!getLeaderboardName().equals(newLeaderboardName)) { - toState.renameLeaderboard(getLeaderboardName(), newLeaderboardName); - } - Leaderboard leaderboard = toState.getLeaderboardByName(newLeaderboardName); + Leaderboard leaderboard = toState.getLeaderboardByName(getLeaderboardName()); // If the new thresholds are null this means that the leaderboard is expected to obtain its result discarding // configuration from somewhere else implicitly, e.g., an underlying regatta, and we'll leave it alone; // Otherwise, a new threshold-based result discarding rule will be set based on the newDiscardingThresholds @@ -56,7 +54,6 @@ public class UpdateLeaderboard extends AbstractLeaderboardOperation leaderboard.setCrossLeaderboardResultDiscardingRule(new ThresholdBasedResultDiscardingRuleImpl(newDiscardingThresholds)); } leaderboard.setDisplayName(newLeaderboardDisplayName); - if (leaderboard instanceof FlexibleLeaderboard) { FlexibleLeaderboard flexibleLeaderboard = (FlexibleLeaderboard) leaderboard; flexibleLeaderboard.setCourseAreas(Util.map(newCourseAreaIds, toState::getCourseArea)); @@ -64,5 +61,4 @@ public class UpdateLeaderboard extends AbstractLeaderboardOperation updateStoredLeaderboard(toState, leaderboard); return leaderboard; } - } diff --git a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java index 1da9b53ef8f..70ccd76ac25 100755 --- a/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java +++ b/java/com.sap.sailing.server.replication.test/src/com/sap/sailing/server/replication/test/RaceLogReplicationTest.java @@ -8,7 +8,6 @@ import java.util.UUID; import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; @@ -42,7 +41,6 @@ import com.sap.sailing.domain.leaderboard.RegattaLeaderboard; import com.sap.sailing.server.operationaltransformation.AddColumnToLeaderboard; import com.sap.sailing.server.operationaltransformation.AddColumnToSeries; import com.sap.sailing.server.operationaltransformation.CreateRegattaLeaderboard; -import com.sap.sailing.server.operationaltransformation.RenameLeaderboard; import com.sap.sse.common.TimePoint; import com.sap.sse.common.Util; import com.sap.sse.common.impl.AbstractColor; @@ -186,22 +184,6 @@ public class RaceLogReplicationTest extends AbstractLogReplicationTest properties = new Hashtable(); + // it's okay to re-use the properties Dictionary for several registrations because the registry clones its contents properties.put(PreferenceConverter.KEY_PARAMETER_NAME, CompetitorNotificationPreferences.PREF_NAME); registrations.add(context.registerService(PreferenceConverter.class, new GenericJSONPreferenceConverter<>(() -> new CompetitorNotificationPreferences(racingEventService)), diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/LeaderboardMXBeanImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/LeaderboardMXBeanImpl.java index c9a2489b818..0fcdf3186be 100755 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/LeaderboardMXBeanImpl.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/LeaderboardMXBeanImpl.java @@ -11,9 +11,8 @@ import com.sap.sailing.server.LeaderboardMXBean; import com.sap.sse.common.Duration; import com.sap.sse.common.Util; import com.sap.sse.common.Util.Pair; -import com.sap.sse.util.AbstractMXBeanImpl; -public class LeaderboardMXBeanImpl extends AbstractMXBeanImpl implements LeaderboardMXBean { +public class LeaderboardMXBeanImpl implements LeaderboardMXBean { private static final long serialVersionUID = -8420830339429971378L; private final Leaderboard leaderboard; @@ -29,7 +28,7 @@ public class LeaderboardMXBeanImpl extends AbstractMXBeanImpl implements Leaderb @Override public ObjectName getObjectName() throws MalformedObjectNameException { - return new ObjectName("com.sap.sailing:type=Leaderboard,name="+escapeIllegalObjectNameCharacters(leaderboard.getName())); + return new ObjectName("com.sap.sailing:type=Leaderboard,name="+ObjectName.quote((leaderboard.getName()))); } @Override diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java index ae4c8d923b9..bb92d3a2717 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/RacingEventServiceImpl.java @@ -128,6 +128,7 @@ import com.sap.sailing.domain.common.CompetitorRegistrationType; import com.sap.sailing.domain.common.DataImportProgress; import com.sap.sailing.domain.common.DataImportSubProgress; import com.sap.sailing.domain.common.DeviceIdentifier; +import com.sap.sailing.domain.common.LeaderboardType; import com.sap.sailing.domain.common.MasterDataImportObjectCreationCount; import com.sap.sailing.domain.common.MaxPointsReason; import com.sap.sailing.domain.common.Position; @@ -185,8 +186,6 @@ import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver; import com.sap.sailing.domain.racelog.RaceLogIdentifier; import com.sap.sailing.domain.racelog.RaceLogStore; import com.sap.sailing.domain.racelog.tracking.SensorFixStore; -import com.sap.sailing.domain.ranking.RankingMetric.CompetitorRankingInfo; -import com.sap.sailing.domain.ranking.RankingMetric.RankingInfo; import com.sap.sailing.domain.ranking.RankingMetricConstructor; import com.sap.sailing.domain.regattalike.HasRegattaLike; import com.sap.sailing.domain.regattalike.IsRegattaLike; @@ -221,6 +220,7 @@ import com.sap.sailing.domain.tracking.impl.AbstractRaceChangeListener; import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl; import com.sap.sailing.domain.tracking.impl.TrackedRaceImpl; import com.sap.sailing.domain.windestimation.WindEstimationFactoryService; +import com.sap.sailing.expeditionconnector.ExpeditionDeviceConfiguration; import com.sap.sailing.expeditionconnector.ExpeditionTrackerFactory; import com.sap.sailing.resultimport.ResultUrlRegistry; import com.sap.sailing.server.Replicator; @@ -295,10 +295,8 @@ import com.sap.sailing.server.util.EventUtil; import com.sap.sailing.shared.server.SharedSailingData; import com.sap.sse.MasterDataImportClassLoaderService; import com.sap.sse.ServerInfo; -import com.sap.sse.common.Distance; import com.sap.sse.common.Duration; import com.sap.sse.common.PairingListCreationException; -import com.sap.sse.common.Renamable; import com.sap.sse.common.TimePoint; import com.sap.sse.common.TypeBasedServiceFinder; import com.sap.sse.common.TypeBasedServiceFinderFactory; @@ -1418,36 +1416,6 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes } } - @Override - public void renameLeaderboard(String oldName, String newName) { - final Leaderboard toRename = leaderboardsByName.get(oldName); - LockUtil.lockForWrite(leaderboardsByNameLock); - try { - if (toRename == null) { - throw new IllegalArgumentException("No leaderboard with name " + oldName + " found"); - } - if (leaderboardsByName.containsKey(newName)) { - throw new IllegalArgumentException("Leaderboard with name " + newName + " already exists"); - } - if (toRename instanceof Renamable) { - removeMBeanForLeaderboard(toRename); - ((Renamable) toRename).setName(newName); - leaderboardsByName.remove(oldName); - leaderboardsByName.put(newName, toRename); - tryToRegisterMBeanForLeaderboard(toRename); - } else { - throw new IllegalArgumentException("Leaderboard with name " + newName + " is of type " - + toRename.getClass().getSimpleName() + " and therefore cannot be renamed"); - } - } finally { - LockUtil.unlockAfterWrite(leaderboardsByNameLock); - } - // don't need the lock anymore to update DB - if (toRename instanceof Renamable) { - mongoObjectFactory.renameLeaderboard(oldName, newName); - } - } - @Override public void updateStoredLeaderboard(Leaderboard leaderboard) { getMongoObjectFactory().storeLeaderboard(leaderboard); @@ -1462,23 +1430,46 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes @Override public void removeLeaderboard(String leaderboardName) { - Leaderboard leaderboard = removeLeaderboardFromLeaderboardsByName(leaderboardName); + final Leaderboard leaderboard = getLeaderboardByName(leaderboardName); if (leaderboard != null) { - leaderboard.removeRaceColumnListener(raceLogReplicator); - leaderboard.removeRaceColumnListener(raceLogScoringReplicator); - final ScoreCorrectionListener scoreCorrectionListener = scoreCorrectionListenersByLeaderboard.remove(leaderboard); - if (scoreCorrectionListener != null) { - leaderboard.getScoreCorrection().removeScoreCorrectionListener(scoreCorrectionListener); + final Set leaderboardsToRemove = new HashSet<>(); + leaderboardsToRemove.add(leaderboard); + if (leaderboard.getLeaderboardType() == LeaderboardType.RegattaLeaderboard) { + final Regatta regatta = ((RegattaLeaderboard) leaderboard).getRegatta(); + for (final Leaderboard candidateForRemoval : getLeaderboards().values()) { + if (candidateForRemoval != leaderboard && candidateForRemoval instanceof RegattaLeaderboard) { + final Regatta candidatesRegatta = ((RegattaLeaderboard) candidateForRemoval).getRegatta(); + if (candidatesRegatta == regatta) { + leaderboardsToRemove.add(candidateForRemoval); + } + } + } } - mongoObjectFactory.removeLeaderboard(leaderboardName); - syncGroupsAfterLeaderboardRemove(leaderboardName, true); - if (leaderboard instanceof FlexibleLeaderboard) { - onRegattaLikeRemoved(((FlexibleLeaderboard) leaderboard).getRegattaLike()); + for (final Leaderboard toRemove : leaderboardsToRemove) { + removeSingleLeaderboardInternal(toRemove); } - leaderboard.destroy(); } } + /** + * Removes only {@code leaderboard} and not implicitly all other leaderboards delegating to it + */ + private void removeSingleLeaderboardInternal(final Leaderboard leaderboard) { + removeLeaderboardFromLeaderboardsByName(leaderboard.getName()); + leaderboard.removeRaceColumnListener(raceLogReplicator); + leaderboard.removeRaceColumnListener(raceLogScoringReplicator); + final ScoreCorrectionListener scoreCorrectionListener = scoreCorrectionListenersByLeaderboard.remove(leaderboard); + if (scoreCorrectionListener != null) { + leaderboard.getScoreCorrection().removeScoreCorrectionListener(scoreCorrectionListener); + } + mongoObjectFactory.removeLeaderboard(leaderboard.getName()); + syncGroupsAfterLeaderboardRemove(leaderboard.getName(), true); + if (leaderboard instanceof FlexibleLeaderboard) { + onRegattaLikeRemoved(((FlexibleLeaderboard) leaderboard).getRegattaLike()); + } + leaderboard.destroy(); + } + private Leaderboard removeLeaderboardFromLeaderboardsByName(String leaderboardName) { LockUtil.lockForWrite(leaderboardsByNameLock); try { @@ -2641,17 +2632,9 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes @Override public void removeRegatta(Regatta regatta) throws MalformedURLException, IOException, InterruptedException { - Set leaderboardsToRemove = new HashSet<>(); - for (Leaderboard leaderboard : getLeaderboards().values()) { - if (leaderboard instanceof RegattaLeaderboard) { - RegattaLeaderboard regattaLeaderboard = (RegattaLeaderboard) leaderboard; - if (regattaLeaderboard.getRegatta() == regatta) { - leaderboardsToRemove.add(regattaLeaderboard); - } - } - } - for (RegattaLeaderboard regattaLeaderboardToRemove : leaderboardsToRemove) { - removeLeaderboard(regattaLeaderboardToRemove.getName()); + final String regattaLeaderboardName = RegattaLeaderboardImpl.getLeaderboardNameForRegatta(regatta); + if (getLeaderboardByName(regattaLeaderboardName) != null) { + removeLeaderboard(regattaLeaderboardName); // removes regatta leaderboard and all that delegate to it } // avoid ConcurrentModificationException by copying the races to remove: Set racesToRemove = new HashSet<>(); @@ -3108,8 +3091,15 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes mongoObjectFactory.removeLeaderboardGroup(groupName); } - @Override - public void renameLeaderboardGroup(String oldName, String newName) { + /** + * Renames the group with the name oldName to the newName.
    + * If there's no group with the name oldName or there's already a group with the name + * newName a {@link IllegalArgumentException} is thrown. + * + * @param oldName The old name of the group + * @param newName The new name of the group + */ + private void renameLeaderboardGroup(String oldName, String newName) { LockUtil.lockForWrite(leaderboardGroupsByNameLock); try { final LeaderboardGroup toRename = leaderboardGroupsByName.get(oldName); @@ -4090,16 +4080,47 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes if (bundleContext == null) { // the non-OSGi case result = Collections.singleton((WindTrackerFactory) ExpeditionTrackerFactory.getInstance()); } else { - ServiceTracker tracker = new ServiceTracker( + ServiceTracker tracker = new ServiceTracker<>( bundleContext, WindTrackerFactory.class, null); tracker.open(); result = new HashSet<>(); for (WindTrackerFactory factory : tracker.getServices(new WindTrackerFactory[0])) { result.add(factory); } + tracker.close(); } return result; } + + @Override + public void addOrReplaceExpeditionDeviceConfiguration(UUID deviceConfigurationId, String name, Integer expeditionBoatId) { + ServiceTracker tracker = new ServiceTracker<>( + bundleContext, ExpeditionTrackerFactory.class, null); + tracker.open(); + final ExpeditionTrackerFactory expeditionTrackerFactory = tracker.getService(); + if (expeditionTrackerFactory != null) { + expeditionTrackerFactory.addOrReplaceDeviceConfiguration(new ExpeditionDeviceConfiguration(name, deviceConfigurationId, expeditionBoatId)); + } else { + logger.severe("Addition or update of Expedition device configuration "+deviceConfigurationId+" was requested, "+ + "but no Expedition connector was found. Request not fulfilled."); + } + tracker.close(); + } + + @Override + public void removeExpeditionDeviceConfiguration(UUID deviceUuid) { + ServiceTracker tracker = new ServiceTracker<>( + bundleContext, ExpeditionTrackerFactory.class, null); + tracker.open(); + final ExpeditionTrackerFactory expeditionTrackerFactory = tracker.getService(); + if (expeditionTrackerFactory != null) { + expeditionTrackerFactory.removeDeviceConfiguration(deviceUuid); + } else { + logger.severe("Addition or update of Expedition device configuration "+deviceUuid+" was requested, "+ + "but no Expedition connector was found. Request not fulfilled."); + } + tracker.close(); + } @Override public SensorFixStore getSensorFixStore() { @@ -4379,22 +4400,6 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes } } - @Override - public Iterable getCompetitorInOrderOfWindwardDistanceTraveledFarthestFirst(TrackedRace trackedRace, TimePoint timePoint) { - final RankingInfo rankingInfo = trackedRace.getRankingMetric().getRankingInfo(timePoint); - final List result = new ArrayList<>(); - final Map windwardDistanceSailedPerCompetitor = new HashMap<>(); - for (final Competitor competitor : trackedRace.getRace().getCompetitors()) { - result.add(competitor); - final CompetitorRankingInfo competitorRankingInfo = rankingInfo.getCompetitorRankingInfo().apply(competitor); - windwardDistanceSailedPerCompetitor.put(competitor, competitorRankingInfo == null ? null : competitorRankingInfo.getWindwardDistanceSailed()); - } - final Comparator durationComparatorNullsLast = Comparator.nullsLast(Comparator.naturalOrder()); - result.sort((c1, c2) -> durationComparatorNullsLast.compare(windwardDistanceSailedPerCompetitor.get(c2), - windwardDistanceSailedPerCompetitor.get(c1))); - return result; - } - /** * A {@link SimpleRaceLogIdentifier} in particular has a {@link SimpleRaceLogIdentifier#getRegattaLikeParentName()} * which identifies either a regatta by name or a flexible leaderboard by name. Here is why this can luckily be @@ -4740,21 +4745,6 @@ public class RacingEventServiceImpl implements RacingEventService, ClearStateTes return anniversaryRaceDeterminator.getNextAnniversary(); } - @Override - public Triple getLastAnniversary() { - Map> allAnniversaries = anniversaryRaceDeterminator - .getKnownAnniversaries(); - Triple lastAnniversary = null; - if (!allAnniversaries.isEmpty()) { - ArrayList list = new ArrayList<>(allAnniversaries.keySet()); - list.sort(Integer::compare); - Integer anniversary = list.get(list.size() - 1); - Pair info = allAnniversaries.get(anniversary); - lastAnniversary = new Triple<>(anniversary, info.getA(), info.getB()); - } - return lastAnniversary; - } - @Override public int getCurrentRaceCount() { return anniversaryRaceDeterminator.getCurrentRaceCount(); diff --git a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreferences.java b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreferences.java index d4745dee645..f0c9803c86f 100644 --- a/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreferences.java +++ b/java/com.sap.sailing.server/src/com/sap/sailing/server/impl/preferences/model/TrackedEventPreferences.java @@ -7,7 +7,6 @@ public class TrackedEventPreferences extends AbstractGenericSerializableSettings private static final long serialVersionUID = -290209497308646446L; - // TODO: setting preference title public static final String PREF_NAME = SailingPreferences.TRACKED_EVENTS_PREFERENCES; private transient SettingsList trackedEvents; diff --git a/java/com.sap.sailing.simulator/src/com/sap/sailing/simulator/impl/PathImpl.java b/java/com.sap.sailing.simulator/src/com/sap/sailing/simulator/impl/PathImpl.java index b1e6deceaba..53162d8bddc 100644 --- a/java/com.sap.sailing.simulator/src/com/sap/sailing/simulator/impl/PathImpl.java +++ b/java/com.sap.sailing.simulator/src/com/sap/sailing/simulator/impl/PathImpl.java @@ -377,24 +377,19 @@ public class PathImpl implements Path, Serializable { } public static boolean saveToGpxFile(Path path, String fileName) { - if (path == null) { return false; } - List pathPoints = path.getPathPoints(); if (pathPoints == null || pathPoints.isEmpty()) { return false; } - TimedPositionWithSpeed timedPoint = null; Position point = null; int noOfPoints = pathPoints.size(); Format formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); StringBuffer buffer = new StringBuffer(); - buffer.append("\r\n\r\n\t\r\n\t\tGPSPolyPath\r\n\t\t"); - for (int index = 0; index < noOfPoints; index++) { timedPoint = pathPoints.get(index); point = timedPoint.getPosition(); @@ -402,23 +397,17 @@ public class PathImpl implements Path, Serializable { + "\">\r\n\t\t\t\t0\r\n\t\t\t\t\r\n\t\t\t"); } - buffer.append("\r\n\t\t\r\n\t\r\n\r\n"); - String content = buffer.toString(); - try { - FileWriter writer = new FileWriter(fileName); BufferedWriter output = new BufferedWriter(writer, 32768); - try { output.write(content); } finally { output.close(); writer.close(); } - } catch (IOException e) { return false; } diff --git a/java/com.sap.sailing.www/release_notes.css b/java/com.sap.sailing.www/release_notes.css index 6fd32bf9ab5..b56e38c6390 100644 --- a/java/com.sap.sailing.www/release_notes.css +++ b/java/com.sap.sailing.www/release_notes.css @@ -37,4 +37,12 @@ background: url(images/bkg-footer1.png); padding: 10px; font-size: 11px; +} + +tr:nth-child(even) { + background: #eee +} + +tr:nth-child(odd) { + background: white; } \ No newline at end of file diff --git a/java/com.sap.sailing.www/release_notes_admin.html b/java/com.sap.sailing.www/release_notes_admin.html index b26a1c60c89..61064a60356 100755 --- a/java/com.sap.sailing.www/release_notes_admin.html +++ b/java/com.sap.sailing.www/release_notes_admin.html @@ -23,6 +23,50 @@

    Release Notes - Administration Console

    +

    June 2020

    +
      +
    +
      +
    • The REST endpoints /sailingserver/api/v1/competitors/{competitorId},
      + /sailingsserver/api/v1/leaderboards/{leaderboardName}/competitors/{competitorId},
      + /sailingserver/api/v1/regattas/{regattaname}/competitors and
      + /sailingserver/api/v1/regattas/{regattaname}/entries
      + have been brought to the same set of comeptitor attributes in the JSON result object.
      + For backward compatibility of the endpoints /sailingserver/api/v1/competitors/{competitorId} and + sailingsserver/api/v1/leaderboards/{leaderboardName}/competitors/{competitorId} + the JSON result object was extended by the attributes +
      • color (replaced by displayColor)
      • +
      • countryCode (replaced by nationalityISO2)
      • +
      • flagImage (replaced by flagImageUri)
      • +
      • teamImageUri (replaced by team/imageUri)
      • +

      + These attributes are deprecated and will be removed in one of the next releases. + For more information see the API documentation of /sailingserver/api/v1/competitors/{competitorId} + and sailingsserver/api/v1/leaderboards/{leaderboardName}/competitors/{competitorId} +
    • +
    • The following REST endpoint URLs of the Usergroups-API and the Preferences-API have been replaced and are now deprecated. The deprecated URLs will be removed in + one of the next releases. +
      raceDetails [Default = RACE_GAP_TO_LEADER_IN_SECONDS, RACE_AVERAGE_SPEED_OVER_GROUND_IN_KNOTS, RACE_CURRENT_SPEED_OVER_GROUND_IN_KNOTS, RACE_DISTANCE_TO_COMPETITOR_FARTHEST_AHEAD_IN_METERS, CURRENT_LEG]; - use "ALL" to get all detail types supported.
     
    + + + + + + + + + + + +
    HTTP MethodDeprecated Endpoint URLReplaced by URL
    GET/sailingserver/api/v1/usergroups/security/api/restsecurity/usergroup/list/groupsUserIsPartOfsee docs
    GET/sailingserver/api/v1/usergroups/readable/security/api/restsecurity/usergroup/list/readablesee docs
    POST/sailingserver/api/v1/usergroups/setDefaultTenantForCurrentServerAndUser/security/api/restsecurity/usergroup/setDefaultTenantForCurrentServerAndUsersee docs
    POST/sailingserver/api/v1/usergroups/addAnyUserToGroup/security/api/restsecurity/usergroup/addAnyUserToGroupsee docs
    GET/sailingserver/api/v1/usergroups/{userGroupId}/roles/security/api/restsecurity/usergroup/{groupId}see docs
    DELETE/sailingserver/api/v1/usergroups/{userGroupId}/roles/security/api/restsecurity/{groupId}/role/{roleId}see docs
    PUT/sailingserver/api/v1/usergroups/{userGroupId}/roles/security/api/restsecurity/usergroup/{groupId}/role/{roleId}see docs
    GET/sailingserver/api/v1/preferences/{settings_key}/security/api/restsecurity//preferences/{settings_key}see docs
    PUT/sailingserver/api/v1/preferences/{settings_key}/security/api/restsecurity//preferences/{settings_key}see docs
    DELETE/sailingserver/api/v1/preferences/{settings_key}/security/api/restsecurity/preferences/{settings_key}see docs
    +
  • +
  • Fixed a regression with the /security/api/restsecurity/ownership and the + {regattaname}/races/{racename}/competitors/positions resource which produced empty + output documents. +
  • +
  • Fixed a concurrency/synchronization issue with the WindFinder connector
  • +
  • Fixed production of the "raceViewerUrl" attribute in the leaderboardgroups REST endpoint.
  • +

May 2020

  • There are new Java Management Beans (MX Beans) for the thread pool executors @@ -58,6 +102,14 @@ of such IDs is provided in the courseAreaIds field as an array that is always present but may be empty.
  • +
  • "Flexible" leaderboards can no longer be renamed. The background of this change is that renaming was + always flawed, particularly regarding the race logs attached to those leaderboards. +
  • +
  • The sailingserver/api/v1/events/createEvents REST endpoint now generates the event's default base URL + by guessing the protocol (http/https) from any port seen in the request's scheme-specific part, if any, defaulting + to https, assuming that even if the request arrives by HTTP it may likely have passed through an SSL-offloading + reverse proxy or load balancer. Use the baseurl form parameter for the request to set this explicitly. +

April 2020

    diff --git a/java/com.sap.sailing.xrr.structureimport/META-INF/MANIFEST.MF b/java/com.sap.sailing.xrr.structureimport/META-INF/MANIFEST.MF index 9a9cbcfa2b4..9452dd27561 100644 --- a/java/com.sap.sailing.xrr.structureimport/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.xrr.structureimport/META-INF/MANIFEST.MF @@ -9,8 +9,8 @@ Export-Package: ., com.sap.sailing.xrr.structureimport.buildstructure;uses:="com.sap.sailing.xrr.resultimport.schema", com.sapsailing.xrr.structureimport.eventimport Bundle-ActivationPolicy: lazy -Require-Bundle: com.google.gwt.user;bundle-version="2.8.2";resolution:=optional, - com.google.gwt.servlet;bundle-version="2.8.2", +Require-Bundle: com.google.gwt.user;bundle-version="2.9.0";resolution:=optional, + com.google.gwt.servlet;bundle-version="2.9.0", com.sap.sailing.domain.common;bundle-version="1.0.0", com.sap.sailing.domain, com.sap.sailing.xrr.schema;bundle-version="1.0.0", diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/AbstractGenericSerializableSettings.java b/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/AbstractGenericSerializableSettings.java index 42c2d7adc56..76534f3722b 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/AbstractGenericSerializableSettings.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/AbstractGenericSerializableSettings.java @@ -3,7 +3,6 @@ package com.sap.sse.common.settings.generic; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -91,7 +90,7 @@ public abstract class AbstractGenericSerializableSettings extends AbstractSettin public AbstractGenericSerializableSettings(String name, AbstractGenericSerializableSettings settings) { super(name, settings); value = (SettingsValue) settings.getValue(name); - if(value == null) { + if (value == null) { value = new SettingsValue(); settings.setValue(name, value); } @@ -103,18 +102,18 @@ public abstract class AbstractGenericSerializableSettings extends AbstractSettin */ protected void adoptValue(SettingsValue value) { this.value = value; - if(childSettings != null) { - for(Map.Entry entry : childSettings.entrySet()) { + if (childSettings != null) { + for (Map.Entry entry : childSettings.entrySet()) { Setting childSetting = entry.getValue(); - if(childSetting instanceof AbstractGenericSerializableSettings) { + if (childSetting instanceof AbstractGenericSerializableSettings) { Value childValue = value.getValue(entry.getKey()); - if(childValue != null) { + if (childValue != null) { ((AbstractGenericSerializableSettings) childSetting).adoptValue((SettingsValue) childValue); } } - if(childSetting instanceof SettingsList) { + if (childSetting instanceof SettingsList) { Value childValue = value.getValue(entry.getKey()); - if(childValue != null) { + if (childValue != null) { ((SettingsList) childSetting).adoptValue(); } } @@ -140,8 +139,7 @@ public abstract class AbstractGenericSerializableSettings extends AbstractSettin * TODO make abstract when all Settings are ported to the new system * */ - protected void addChildSettings() { - } + protected abstract void addChildSettings(); // TODO make protected public Value getValue(String settingName) { @@ -184,7 +182,9 @@ public abstract class AbstractGenericSerializableSettings extends AbstractSettin @Override public Map getChildSettings() { - return Collections.unmodifiableMap(childSettings); + synchronized(childSettings) { + return new HashMap(childSettings); + } } @GwtIncompatible diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/AbstractSetting.java b/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/AbstractSetting.java index b83b7849b36..dc82148aba0 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/AbstractSetting.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/AbstractSetting.java @@ -1,7 +1,5 @@ package com.sap.sse.common.settings.generic; - - public abstract class AbstractSetting implements Setting { protected transient final AbstractGenericSerializableSettings settings; @@ -10,7 +8,7 @@ public abstract class AbstractSetting implements Setting { public AbstractSetting(String settingName, AbstractGenericSerializableSettings settings) { this.settingName = settingName; this.settings = settings; - if(settings != null) { + if (settings != null) { settings.addSetting(settingName, this); } } diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/CollectionSetting.java b/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/CollectionSetting.java index 78f047ee039..034982acd4b 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/CollectionSetting.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/CollectionSetting.java @@ -5,6 +5,10 @@ public interface CollectionSetting extends Setting { void setValues(Iterable values); + /** + * Obtains a non-live copy of the values in this collection setting. Changes to this setting + * will not reflect in the iterable returned. + */ Iterable getValues(); void addValue(T value); diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/SettingsList.java b/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/SettingsList.java index 7fa5f4ab54a..5510177936a 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/SettingsList.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/SettingsList.java @@ -13,6 +13,13 @@ import com.sap.sse.common.settings.value.ValueListValue; public class SettingsList extends AbstractSetting implements SettingsListSetting { private SettingsFactory settingsFactory; + + /** + * All access to this list must be {@code synchronized}. Unfortunately, GWT does not offer + * {@link Collections#synchronizedList(List)} in its JRE emulation, so we have to + * make sure to consistently wrap all methods that access this list with a {@code synchronized} + * block that obtains this list's monitor. + */ private final List values = new ArrayList<>(); public SettingsList(String name, AbstractGenericSerializableSettings settings, SettingsFactory settingsFactory) { @@ -22,13 +29,15 @@ public class SettingsList extends } protected void adoptValue() { - values.clear(); - ValueListValue value = getValue(); - if(value != null) { - for(Value val : value.getValueObjects()) { - T childSettingsInstance = settingsFactory.newInstance(); - childSettingsInstance.adoptValue((SettingsValue)val); - values.add(childSettingsInstance); + synchronized (values) { + values.clear(); + ValueListValue value = getValue(); + if(value != null) { + for(Value val : value.getValueObjects()) { + T childSettingsInstance = settingsFactory.newInstance(); + childSettingsInstance.adoptValue((SettingsValue)val); + values.add(childSettingsInstance); + } } } } @@ -40,7 +49,7 @@ public class SettingsList extends private ValueCollectionValue> ensureValue() { ValueListValue result = getValue(); - if(result == null) { + if (result == null) { result = new ValueListValue(); settings.setValue(settingName, result); } @@ -58,65 +67,80 @@ public class SettingsList extends @Override public boolean isDefaultValue() { - // explicit default values are possible to implement - // currently, empty is always default - return values.isEmpty(); + synchronized (values) { + // explicit default values are possible to implement + // currently, empty is always default + return values.isEmpty(); + } } @Override public void resetToDefault() { - this.values.clear(); - settings.setValue(settingName, null); + synchronized (values) { + this.values.clear(); + settings.setValue(settingName, null); + } } @Override public Iterable getValues() { - return Collections.unmodifiableCollection(values); + synchronized (values) { + final List result = new ArrayList<>(values); + return result; + } } @Override public void setValues(Iterable values) { - this.values.clear(); - ValueCollectionValue> valueObject = ensureValue(); - valueObject.clear(); - if(values != null) { - for(T value : values) { - this.values.add(value); - valueObject.addValue(value.getInnerValueObject()); + synchronized (this.values) { + this.values.clear(); + ValueCollectionValue> valueObject = ensureValue(); + valueObject.clear(); + if (values != null) { + for (T value : values) { + this.values.add(value); + valueObject.addValue(value.getInnerValueObject()); + } } } } @Override public void addValue(T value) { - ValueCollectionValue> valueObject = ensureValue(); - this.values.add(value); - valueObject.addValue(value.getInnerValueObject()); + synchronized (values) { + ValueCollectionValue> valueObject = ensureValue(); + this.values.add(value); + valueObject.addValue(value.getInnerValueObject()); + } } @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((values == null) ? 0 : values.hashCode()); - return result; + synchronized (values) { + final int prime = 31; + int result = 1; + result = prime * result + ((values == null) ? 0 : values.hashCode()); + return result; + } } @Override public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - @SuppressWarnings("rawtypes") - SettingsList other = (SettingsList) obj; - if (values == null) { - if (other.values != null) + synchronized (values) { + if (this == obj) + return true; + if (obj == null) return false; - } else if (!values.equals(other.values)) - return false; - return true; + if (getClass() != obj.getClass()) + return false; + @SuppressWarnings("rawtypes") + SettingsList other = (SettingsList) obj; + if (values == null) { + if (other.values != null) + return false; + } else if (!values.equals(other.values)) + return false; + return true; + } } } diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/ValueCollectionSetting.java b/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/ValueCollectionSetting.java index 2f499594467..64a173d8c07 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/ValueCollectionSetting.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/ValueCollectionSetting.java @@ -3,6 +3,11 @@ package com.sap.sse.common.settings.generic; public interface ValueCollectionSetting extends HasValueSetting, CollectionSetting { void setDefaultValues(Iterable defaultValues); + + /** + * Obtains a non-live copy of the default values. Modification to this object's default values hence will + * not reflect into the iterable returned. + */ Iterable getDefaultValues(); boolean isValuesEmpty(); void setDiff(Iterable removedValues, Iterable addedValues); diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/base/AbstractValueCollectionSetting.java b/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/base/AbstractValueCollectionSetting.java index 0354eca632b..b95767959c4 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/base/AbstractValueCollectionSetting.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/settings/generic/base/AbstractValueCollectionSetting.java @@ -21,7 +21,7 @@ public abstract class AbstractValueCollectionSetting ensureValue() { ValueCollectionValue result = getValue(); - if(result == null) { + if (result == null) { result = createValue(); settings.setValue(settingName, result); } @@ -48,10 +48,15 @@ public abstract class AbstractValueCollectionSetting getValues() { ValueCollectionValue value = getValue(); - if(emptyIsDefault && (value == null || value.isEmpty())) { - return Collections.unmodifiableCollection(getDefaultValuesCollectionInternal()); + if (emptyIsDefault && (value == null || value.isEmpty())) { + final D defaultVal = getDefaultValuesCollectionInternal(); + synchronized (defaultVal) { + final D result = createDefaultValuesCollection(); + result.addAll(defaultVal); + return result; + } } - if(value == null) { + if (value == null) { return Collections.emptyList(); } return value.getValues(getValueConverter()); @@ -78,33 +83,45 @@ public abstract class AbstractValueCollectionSetting value = getValue(); final D defaultVal = getDefaultValuesCollectionInternal(); - return ((emptyIsDefault || defaultVal.isEmpty()) && (value == null || value.isEmpty())) - || (value != null && value.size() == defaultVal.size() && defaultVal.containsAll(value.getValues(getValueConverter()))); + synchronized (defaultVal) { + return ((emptyIsDefault || defaultVal.isEmpty()) && (value == null || value.isEmpty())) + || (value != null && value.size() == defaultVal.size() && defaultVal.containsAll(value.getValues(getValueConverter()))); + } } @Override public final void setDefaultValues(Iterable defaultValues) { final boolean wasDefault = isDefaultValue(); final D defaultVal = getDefaultValuesCollectionInternal(); - defaultVal.clear(); - if(defaultValues != null) { - Util.addAll(defaultValues, defaultVal); - } - if(wasDefault) { - resetToDefault(); + synchronized (defaultVal) { + defaultVal.clear(); + if (defaultValues != null) { + Util.addAll(defaultValues, defaultVal); + } + if (wasDefault) { + resetToDefault(); + } } } @Override public Iterable getDefaultValues() { - return Collections.unmodifiableCollection(getDefaultValuesCollectionInternal()); + final D result = createDefaultValuesCollection(); + final D localDefaultValues = getDefaultValuesCollectionInternal(); + synchronized (localDefaultValues) { + result.addAll(localDefaultValues); + return result; + } } @Override @@ -135,7 +152,7 @@ public abstract class AbstractValueCollectionSetting value = getValue(); - if(value == null) { + if (value == null) { return "[]"; } return value.toString(); diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/settings/value/SettingsListValue.java b/java/com.sap.sse.common/src/com/sap/sse/common/settings/value/SettingsListValue.java index decbc97a900..04c8871c40d 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/settings/value/SettingsListValue.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/settings/value/SettingsListValue.java @@ -3,21 +3,24 @@ package com.sap.sse.common.settings.value; import java.util.HashMap; public class SettingsListValue { - private HashMap values = new HashMap<>(); public SettingsListValue() { } public Value getValue(String name) { - return values.get(name); + synchronized (values) { + return values.get(name); + } } public void setValue(String name, Value value) { - if(value == null) { - values.remove(name); - } else { - values.put(name, value); + synchronized (values) { + if (value == null) { + values.remove(name); + } else { + values.put(name, value); + } } } } diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/settings/value/SettingsValue.java b/java/com.sap.sse.common/src/com/sap/sse/common/settings/value/SettingsValue.java index 3b5f984465b..98e1ed5cbd5 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/settings/value/SettingsValue.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/settings/value/SettingsValue.java @@ -1,53 +1,71 @@ package com.sap.sse.common.settings.value; +import java.util.Collections; import java.util.HashMap; public class SettingsValue implements Value { private static final long serialVersionUID = -3407605464729611500L; + + /** + * All access to this map must be {@code synchronized}. Unfortunately, GWT does not offer + * {@link Collections#synchronizedMap(java.util.Map)} in its JRE emulation, so we have to + * make sure to consistently wrap all methods that access this map with a {@code synchronized} + * block that obtains this map's monitor. + */ private HashMap values = new HashMap<>(); public SettingsValue() { } public Value getValue(String name) { - return values.get(name); + synchronized (values) { + return values.get(name); + } } public void setValue(String name, Value value) { - if(value == null) { - values.remove(name); - } else { - values.put(name, value); + synchronized (values) { + if (value == null) { + values.remove(name); + } else { + values.put(name, value); + } } } @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((values == null) ? 0 : values.hashCode()); - return result; + synchronized (values) { + final int prime = 31; + int result = 1; + result = prime * result + ((values == null) ? 0 : values.hashCode()); + return result; + } } @Override public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - SettingsValue other = (SettingsValue) obj; - if (values == null) { - if (other.values != null) + synchronized (values) { + if (this == obj) + return true; + if (obj == null) return false; - } else if (!values.equals(other.values)) - return false; - return true; + if (getClass() != obj.getClass()) + return false; + SettingsValue other = (SettingsValue) obj; + if (values == null) { + if (other.values != null) + return false; + } else if (!values.equals(other.values)) + return false; + return true; + } } @Override public String toString() { - return values.toString(); + synchronized (values) { + return values.toString(); + } } } diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/settings/value/ValueCollection.java b/java/com.sap.sse.common/src/com/sap/sse/common/settings/value/ValueCollection.java index 66f273a1e54..fb151da9c40 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/settings/value/ValueCollection.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/settings/value/ValueCollection.java @@ -3,6 +3,10 @@ package com.sap.sse.common.settings.value; import com.sap.sse.common.settings.generic.ValueConverter; public interface ValueCollection extends Value { + /** + * Obtains a non-live copy of the values in this collection. Modifications to this value collection + * will not reflect in the result of this method, and vice versa. + */ Iterable getValues(ValueConverter converter); void setValues(Iterable values, ValueConverter converter); diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/settings/value/ValueCollectionValue.java b/java/com.sap.sse.common/src/com/sap/sse/common/settings/value/ValueCollectionValue.java index 72ec892fe92..cd5332ac609 100644 --- a/java/com.sap.sse.common/src/com/sap/sse/common/settings/value/ValueCollectionValue.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/settings/value/ValueCollectionValue.java @@ -7,6 +7,13 @@ import com.sap.sse.common.settings.generic.ValueConverter; public abstract class ValueCollectionValue> implements ValueCollection { private static final long serialVersionUID = -5820765644801217519L; + + /** + * All access to this collection must be {@code synchronized}. Unfortunately, GWT does not offer + * {@link Collections#synchronizedCollection(Collection)} in its JRE emulation, so we have to + * make sure to consistently wrap all methods that access this collection with a {@code synchronized} + * block that obtains this collection's monitor. + */ private C values; protected ValueCollectionValue(C values) { @@ -17,75 +24,99 @@ public abstract class ValueCollectionValue> implemen @Override public Collection getValues(ValueConverter converter) { - Collection result = emptyCollection(); - for (Value value : values) { - result.add(converter.fromValue(value)); + final Collection result = emptyCollection(); + synchronized (values) { + for (Value value : values) { + result.add(converter.fromValue(value)); + } + return result; + } + } + + public Iterable getValueObjects() { + final Collection result = emptyCollection(); + synchronized (values) { + result.addAll(values); } return result; } - public Iterable getValueObjects() { - return Collections.unmodifiableCollection(values); - } - @Override public void setValues(Iterable values, ValueConverter converter) { - clear(); - if(values != null) { - for (T value : values) { - addValue(value, converter); + synchronized (this.values) { + clear(); + if (values != null) { + for (T value : values) { + addValue(value, converter); + } } } } @Override public void clear() { - this.values.clear(); + synchronized (values) { + this.values.clear(); + } } public void addValue(T value, ValueConverter converter) { - this.values.add(converter.toValue(value)); + synchronized (values) { + addValue(converter.toValue(value)); + } } public void addValue(Value value) { - this.values.add(value); + synchronized (values) { + this.values.add(value); + } } public boolean isEmpty() { - return values.isEmpty(); + synchronized (values) { + return values.isEmpty(); + } } public int size() { - return values.size(); + synchronized (values) { + return values.size(); + } } @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((values == null) ? 0 : values.hashCode()); - return result; + synchronized (values) { + final int prime = 31; + int result = 1; + result = prime * result + ((values == null) ? 0 : values.hashCode()); + return result; + } } @Override public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - ValueCollectionValue other = (ValueCollectionValue) obj; - if (values == null) { - if (other.values != null) + synchronized (values) { + if (this == obj) + return true; + if (obj == null) return false; - } else if (!values.equals(other.values)) - return false; - return true; + if (getClass() != obj.getClass()) + return false; + ValueCollectionValue other = (ValueCollectionValue) obj; + if (values == null) { + if (other.values != null) + return false; + } else if (!values.equals(other.values)) + return false; + return true; + } } @Override public String toString() { - return values.toString(); + synchronized (values) { + return values.toString(); + } } } diff --git a/java/com.sap.sse.datamining.ui.test/META-INF/MANIFEST.MF b/java/com.sap.sse.datamining.ui.test/META-INF/MANIFEST.MF index fa71dc3af04..bda99a673b0 100644 --- a/java/com.sap.sse.datamining.ui.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.datamining.ui.test/META-INF/MANIFEST.MF @@ -7,7 +7,7 @@ Bundle-Vendor: SAP Automatic-Module-Name: com.sap.sse.datamining.ui.test Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.junit, - com.google.gwt.user;bundle-version="2.8.2", + com.google.gwt.user;bundle-version="2.9.0", com.sap.sse.datamining.ui, com.sap.sse.gwt;bundle-version="1.0.0", slf4j.api;bundle-version="1.6.4", diff --git a/java/com.sap.sse.datamining.ui/META-INF/MANIFEST.MF b/java/com.sap.sse.datamining.ui/META-INF/MANIFEST.MF index 2b013ef864f..b01a0a8fb41 100644 --- a/java/com.sap.sse.datamining.ui/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.datamining.ui/META-INF/MANIFEST.MF @@ -9,8 +9,8 @@ Require-Bundle: com.sap.sse.gwt, com.sap.sse.common, com.sap.sse.datamining.shared, org.moxieapps.gwt.highcharts, - com.google.gwt.servlet;bundle-version="2.8.2", - com.google.gwt.user;bundle-version="2.8.2";resolution:=optional, + com.google.gwt.servlet;bundle-version="2.9.0", + com.google.gwt.user;bundle-version="2.9.0";resolution:=optional, org.apache.shiro.core Export-Package: com.sap.sse.datamining.ui.client, com.sap.sse.datamining.ui.client.developer, diff --git a/java/com.sap.sse.feature/feature.xml b/java/com.sap.sse.feature/feature.xml index cfb50303089..f4396a4cd1c 100755 --- a/java/com.sap.sse.feature/feature.xml +++ b/java/com.sap.sse.feature/feature.xml @@ -42,7 +42,7 @@ Computes leaderboard information for sailing races and offers RESTful APIs to al id="com.google.gwt.servlet" download-size="0" install-size="0" - version="2.8.2" + version="2.9.0" unpack="false"/> { + + private final StringMessages stringMessages; + private final ServerInfoDTO serverInfo; + + public AdditionalServerInformationDialog(StringMessages stringMessages, ServerInfoDTO serverInfo) { + super(stringMessages.serverInformation(), /* text */ null, stringMessages.ok(), stringMessages.cancel(), + /* validator */ null, /* animationEnabled */ false, /* callback */null); + this.stringMessages = stringMessages; + this.serverInfo = serverInfo; + } + + @Override + protected Widget getAdditionalWidget() { + VerticalPanel mainPanel = new VerticalPanel(); + Label nameLabel = new Label(stringMessages.serverName(serverInfo.getName())); + Label versionLabel = new Label(stringMessages.version(serverInfo.getBuildVersion())); + mainPanel.add(nameLabel); + mainPanel.add(versionLabel); + return mainPanel; + } + + @Override + protected String getResult() { + return null; + } +} diff --git a/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/AdminConsolePanel.java b/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/AdminConsolePanel.java index a51563ecefc..eae85eced62 100644 --- a/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/AdminConsolePanel.java +++ b/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/AdminConsolePanel.java @@ -203,13 +203,18 @@ public class AdminConsolePanel extends HeaderPanel implements HandleTabSelectabl final DockPanel informationPanel = new DockPanel(); informationPanel.setWidth("100%"); informationPanel.setSpacing(10); - informationPanel.add(errorReporter.getPersistentInformationWidget(), DockPanel.CENTER); + Widget persistentInformationWidget = errorReporter.getPersistentInformationWidget(); + persistentInformationWidget.addStyleName("footerInfoPanel"); + informationPanel.add(persistentInformationWidget, DockPanel.CENTER); SystemInformationPanel sysinfoPanel = new SystemInformationPanel(serverInfo, errorReporter, stringMessages); + sysinfoPanel.addStyleName("systemInformationPanel"); sysinfoPanel.ensureDebugId("SystemInformation"); if (ClientConfiguration.getInstance().isBrandingActive()) { final Anchor releaseNotesLink = new Anchor( new SafeHtmlBuilder().appendEscaped(releaseNotesAnchorLabel).toSafeHtml(), releaseNotesURL); + releaseNotesLink.addStyleName("releaseNotesAnchor"); sysinfoPanel.add(releaseNotesLink); + informationPanel.add(releaseNotesLink, DockPanel.EAST); } informationPanel.add(sysinfoPanel, DockPanel.EAST); informationPanel.setCellHorizontalAlignment(sysinfoPanel, HasHorizontalAlignment.ALIGN_RIGHT); diff --git a/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/StringMessages.java b/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/StringMessages.java index aecd978db1b..19e84e3c258 100755 --- a/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/StringMessages.java +++ b/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/StringMessages.java @@ -107,4 +107,8 @@ public interface StringMessages extends Messages { String explainPassword(); String additionalInformation(); + + String serverInformation(); + + String serverName(String buildVersion); } diff --git a/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/SystemInformationPanel.java b/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/SystemInformationPanel.java index b0ee583b7cb..36aa8ec8131 100644 --- a/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/SystemInformationPanel.java +++ b/java/com.sap.sse.gwt.adminconsole/src/com/sap/sse/gwt/adminconsole/SystemInformationPanel.java @@ -1,29 +1,48 @@ package com.sap.sse.gwt.adminconsole; -import com.google.gwt.dom.client.Style; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.Widget; import com.sap.sse.gwt.client.ErrorReporter; import com.sap.sse.gwt.client.ServerInfoDTO; public class SystemInformationPanel extends FlowPanel { private final Label buildVersionText; - - public SystemInformationPanel(final ServerInfoDTO serverInfo, final ErrorReporter errorReporter, final StringMessages stringMessages) { + private String fullVersionText; + private boolean buildVersionCut; + private Anchor additionalInformation; + + public SystemInformationPanel(final ServerInfoDTO serverInfo, final ErrorReporter errorReporter, + final StringMessages stringMessages) { super(); - buildVersionText = new Label(""); - addFloatingWidget(buildVersionText); + buildVersionText = new Label(); if (serverInfo != null) { - buildVersionText.setText(stringMessages.version(serverInfo.getBuildVersion())); + fullVersionText = serverInfo.getBuildVersion(); + if (fullVersionText.length() > 70) { + buildVersionCut = true; + final int toIndex = fullVersionText.indexOf(" ") - 1; + buildVersionText.setText(stringMessages.version(fullVersionText.substring(0, toIndex) + "...")); + } else { + buildVersionText.setText(stringMessages.version(fullVersionText)); + } } else { buildVersionText.setText(stringMessages.version(stringMessages.unknown())); } - } - - private void addFloatingWidget(Widget w) { - w.getElement().getStyle().setFloat(Style.Float.LEFT); - add(w); + add(buildVersionText); + if (buildVersionCut) { + additionalInformation = new Anchor(stringMessages.additionalInformation()); + additionalInformation.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + AdditionalServerInformationDialog additionalInformationDialog = new AdditionalServerInformationDialog( + stringMessages, serverInfo); + additionalInformationDialog.show(); + } + }); + add(additionalInformation); + } } } diff --git a/java/com.sap.sse.gwt.test/META-INF/MANIFEST.MF b/java/com.sap.sse.gwt.test/META-INF/MANIFEST.MF index 0061decf682..57d04e441ad 100644 --- a/java/com.sap.sse.gwt.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.gwt.test/META-INF/MANIFEST.MF @@ -8,6 +8,6 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Fragment-Host: com.sap.sse.gwt Require-Bundle: com.sap.sse.common;bundle-version="1.0.0", org.junit;bundle-version="4.8.2", - com.google.gwt.user;bundle-version="2.8.2";resolution:=optional, - com.google.gwt.servlet;bundle-version="2.8.2" + com.google.gwt.user;bundle-version="2.9.0";resolution:=optional, + com.google.gwt.servlet;bundle-version="2.9.0" Automatic-Module-Name: com.sap.sse.gwt.test diff --git a/java/com.sap.sse.gwt/META-INF/MANIFEST.MF b/java/com.sap.sse.gwt/META-INF/MANIFEST.MF index 2d1738c5868..559ab44bf80 100644 --- a/java/com.sap.sse.gwt/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.gwt/META-INF/MANIFEST.MF @@ -6,9 +6,9 @@ Automatic-Module-Name: com.sap.sse.gwt Bundle-Version: 1.0.0.qualifier Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.8 -Require-Bundle: com.google.gwt.user;bundle-version="2.8.2";resolution:=optional, - com.google.gwt.dev;bundle-version="2.8.2";resolution:=optional, - com.google.gwt.servlet;bundle-version="2.8.2", +Require-Bundle: com.google.gwt.user;bundle-version="2.9.0";resolution:=optional, + com.google.gwt.dev;bundle-version="2.9.0";resolution:=optional, + com.google.gwt.servlet;bundle-version="2.9.0", com.sap.sse.common, com.sap.sse.filestorage, com.sap.sse.security.common diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/filestorage/FileStoragePanel.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/filestorage/FileStoragePanel.java index 7535306d4e4..40fdbca7e24 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/filestorage/FileStoragePanel.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/controls/filestorage/FileStoragePanel.java @@ -165,8 +165,6 @@ public class FileStoragePanel extends FlowPanel { /** * Test the properties using {@link FileStorageService#testProperties()}, and display global errors and per-property * errors in the according label and table cells. - * - * @param callback */ private void testProperties(final Callback callback) { sailingService.testFileStorageServiceProperties(getSelectedServiceName(), getLocaleInfo(), diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/components/CompositeSettings.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/components/CompositeSettings.java index 94d8249fda4..02a3f9c3375 100755 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/components/CompositeSettings.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/shared/components/CompositeSettings.java @@ -12,7 +12,10 @@ import com.sap.sse.gwt.client.shared.perspective.PerspectiveCompositeSettings; /** * Groups settings for multiple {@link Component}s. This can be of particular interest when working with - * {@link Perspective}s and the perspective's {@link PerspectiveCompositeSettings composite settings}. + * {@link Perspective}s and the perspective's {@link PerspectiveCompositeSettings composite settings}.

    + * + * No synchronization is required here because when the constructor returns, the map used internally + * will no longer be modified. */ public class CompositeSettings extends AbstractSettings implements SettingsMap { private final Map settingsPerComponentId; diff --git a/java/com.sap.sse.replication/src/com/sap/sse/replication/impl/Activator.java b/java/com.sap.sse.replication/src/com/sap/sse/replication/impl/Activator.java index 9782f82699e..d06321bd8dc 100755 --- a/java/com.sap.sse.replication/src/com/sap/sse/replication/impl/Activator.java +++ b/java/com.sap.sse.replication/src/com/sap/sse/replication/impl/Activator.java @@ -11,6 +11,7 @@ import java.util.logging.Logger; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; +import com.sap.sse.common.Util; import com.sap.sse.replication.ReplicaDescriptor; import com.sap.sse.replication.Replicable; import com.sap.sse.replication.ReplicablesProvider; @@ -189,7 +190,7 @@ public class Activator implements BundleActivator { final String servletHost = System.getProperty(PROPERTY_NAME_REPLICATE_MASTER_SERVLET_HOST); final int servletPort = Integer.valueOf(System.getProperty(PROPERTY_NAME_REPLICATE_MASTER_SERVLET_PORT).trim()); final String bearerToken; - if (System.getProperty(PROPERTY_NAME_REPLICATE_MASTER_BEARER_TOKEN) != null) { + if (Util.hasLength(System.getProperty(PROPERTY_NAME_REPLICATE_MASTER_BEARER_TOKEN))) { bearerToken = System.getProperty(PROPERTY_NAME_REPLICATE_MASTER_BEARER_TOKEN).trim(); } else { bearerToken = RemoteServerUtil.resolveBearerTokenForRemoteServer(servletHost, servletPort, diff --git a/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/BasicUserStore.java b/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/BasicUserStore.java index 55b2d3d681c..b7b2aa878d4 100755 --- a/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/BasicUserStore.java +++ b/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/BasicUserStore.java @@ -65,8 +65,6 @@ public interface BasicUserStore extends UserGroupProvider, Named { void removeRoleFromUser(String username, Role role) throws UserManagementException; - Iterable getPermissionsFromUser(String username) throws UserManagementException; - void removePermissionFromUser(String username, WildcardPermission permission) throws UserManagementException; void addPermissionForUser(String username, WildcardPermission permission) throws UserManagementException; diff --git a/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/dto/OwnershipAnnotationDTO.java b/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/dto/OwnershipAnnotationDTO.java deleted file mode 100644 index 40493a4c112..00000000000 --- a/java/com.sap.sse.security.common/src/com/sap/sse/security/shared/dto/OwnershipAnnotationDTO.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.sap.sse.security.shared.dto; - -import com.sap.sse.security.shared.QualifiedObjectIdentifier; -import com.sap.sse.security.shared.impl.ObjectAnnotationImpl; - -public class OwnershipAnnotationDTO extends ObjectAnnotationImpl { - private static final long serialVersionUID = 7242600656125139931L; - - @Deprecated // gwt only - OwnershipAnnotationDTO() { - super(null, null, null); - } - - public OwnershipAnnotationDTO(OwnershipDTO annotation, QualifiedObjectIdentifier idOfAnnotatedObject, - String displayNameOfAnnotatedObject) { - super(annotation, idOfAnnotatedObject, displayNameOfAnnotatedObject); - } -} diff --git a/java/com.sap.sse.security.ui/META-INF/MANIFEST.MF b/java/com.sap.sse.security.ui/META-INF/MANIFEST.MF index 53159d5c61d..2d3bf1f1ab2 100644 --- a/java/com.sap.sse.security.ui/META-INF/MANIFEST.MF +++ b/java/com.sap.sse.security.ui/META-INF/MANIFEST.MF @@ -13,8 +13,8 @@ Bundle-ActivationPolicy: lazy Bundle-ClassPath: WEB-INF/classes/ Require-Bundle: javax.servlet;bundle-version="3.1.0", com.sap.sse.gwt, - com.google.gwt.user;bundle-version="2.8.2";resolution:=optional, - com.google.gwt.servlet;bundle-version="2.8.2", + com.google.gwt.user;bundle-version="2.9.0";resolution:=optional, + com.google.gwt.servlet;bundle-version="2.9.0", com.sap.sse.security, org.json.simple, com.sap.sse.common, diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementService.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementService.java index 09f88b28a3e..ae956c523a0 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementService.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementService.java @@ -19,7 +19,6 @@ import com.sap.sse.security.shared.UserManagementException; import com.sap.sse.security.shared.WildcardPermission; import com.sap.sse.security.shared.dto.AccessControlListAnnotationDTO; import com.sap.sse.security.shared.dto.AccessControlListDTO; -import com.sap.sse.security.shared.dto.OwnershipAnnotationDTO; import com.sap.sse.security.shared.dto.OwnershipDTO; import com.sap.sse.security.shared.dto.RoleDefinitionDTO; import com.sap.sse.security.shared.dto.RolesAndPermissionsForUserDTO; @@ -39,17 +38,6 @@ public interface UserManagementService extends RemoteService { Collection getAccessControlLists() throws UnauthorizedException, org.apache.shiro.authz.UnauthorizedException; - AccessControlListAnnotationDTO getAccessControlList(QualifiedObjectIdentifier idOfAccessControlledObject) - throws org.apache.shiro.authz.UnauthorizedException; - - AccessControlListDTO addToAccessControlList(QualifiedObjectIdentifier idOfAccessControlledObject, - String groupOrTenantIdAsString, String action) - throws UnauthorizedException, org.apache.shiro.authz.UnauthorizedException; - - AccessControlListDTO removeFromAccessControlList(QualifiedObjectIdentifier idOfAccessControlledObject, - String groupOrTenantIdAsString, String action) - throws UnauthorizedException, org.apache.shiro.authz.UnauthorizedException; - Collection getUserGroups() throws org.apache.shiro.authz.UnauthorizedException; UserGroupDTO getUserGroupByName(String userGroupName) @@ -78,8 +66,6 @@ public interface UserManagementService extends RemoteService { Collection getUserList() throws UnauthorizedException, org.apache.shiro.authz.UnauthorizedException; - UserDTO getUserByName(String username) throws UnauthorizedException, org.apache.shiro.authz.UnauthorizedException; - RoleDefinitionDTO createRoleDefinition(String roleDefinitionIdAsString, String name) throws org.apache.shiro.authz.UnauthorizedException; @@ -171,8 +157,6 @@ public interface UserManagementService extends RemoteService { Map getAllPreferences(String username) throws UserManagementException, UnauthorizedException, org.apache.shiro.authz.UnauthorizedException; - String getAccessToken(String username) throws UnauthorizedException, org.apache.shiro.authz.UnauthorizedException; - String getOrCreateAccessToken(String username) throws UnauthorizedException, org.apache.shiro.authz.UnauthorizedException; @@ -185,9 +169,6 @@ public interface UserManagementService extends RemoteService { public Triple verifySocialUser(CredentialDTO credential) throws OAuthException, org.apache.shiro.authz.UnauthorizedException; - OwnershipAnnotationDTO getOwnership(QualifiedObjectIdentifier idOfOwnedObject) - throws org.apache.shiro.authz.UnauthorizedException; - AccessControlListDTO overrideAccessControlList(QualifiedObjectIdentifier idOfAccessControlledObject, AccessControlListDTO acl) throws UnauthorizedException, org.apache.shiro.authz.UnauthorizedException; diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementServiceAsync.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementServiceAsync.java index 7db57c926e8..e6ee729aa9c 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementServiceAsync.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/client/UserManagementServiceAsync.java @@ -15,7 +15,6 @@ import com.sap.sse.security.shared.TypeRelativeObjectIdentifier; import com.sap.sse.security.shared.WildcardPermission; import com.sap.sse.security.shared.dto.AccessControlListAnnotationDTO; import com.sap.sse.security.shared.dto.AccessControlListDTO; -import com.sap.sse.security.shared.dto.OwnershipAnnotationDTO; import com.sap.sse.security.shared.dto.OwnershipDTO; import com.sap.sse.security.shared.dto.RoleDefinitionDTO; import com.sap.sse.security.shared.dto.RolesAndPermissionsForUserDTO; @@ -32,24 +31,14 @@ public interface UserManagementServiceAsync { QualifiedObjectIdentifier idOfOwnedObject, String displayNameOfOwnedObject, AsyncCallback callback); - void getOwnership(QualifiedObjectIdentifier idOfOwnedObject, AsyncCallback callback); - void getAccessControlLists(AsyncCallback> callback); - void getAccessControlList(QualifiedObjectIdentifier idOfAccessControlledObject, AsyncCallback callback); - void getAccessControlListWithoutPruning(QualifiedObjectIdentifier idOfAccessControlledObject, AsyncCallback updateAclAsyncCallback); void overrideAccessControlList(QualifiedObjectIdentifier idOfAccessControlledObject, AccessControlListDTO acl, AsyncCallback updateAclAsyncCallback); - void addToAccessControlList(QualifiedObjectIdentifier idOfAccessControlledObject, String permission, String name, - AsyncCallback callback); - - void removeFromAccessControlList(QualifiedObjectIdentifier idOfAccessControlledObject, String permission, - String name, AsyncCallback callback); - /** * Returns those user groups the requesting user can read */ @@ -78,8 +67,6 @@ public interface UserManagementServiceAsync { */ void getUserList(AsyncCallback> callback); - void getUserByName(String username, AsyncCallback callback); - /** * Returns true if a user associated to the given username even if the current user cannot see the existing user. */ @@ -139,15 +126,9 @@ public interface UserManagementServiceAsync { void getAllPreferences(String username, final AsyncCallback> callback); /** - * Obtains an access token for the user specified by {@code username}. The caller needs to - * have role {@link DefaultRoles#ADMIN} or be authorized as the user identified by {@code username} - * in order to be permitted to retrieve the access token. - */ - void getAccessToken(String username, AsyncCallback markedAsyncCallback); - - /** - * Like {@link #getAccessToken(String, AsyncCallback)}, only that instead of returning {@code null} a - * new access token will be created and returned. + * * Obtains an access token for the user specified by {@code username}. The caller needs to have role + * {@link DefaultRoles#ADMIN} or be authorized as the user identified by {@code username} in order to be permitted + * to retrieve the access token, a new access token will be created and returned. */ void getOrCreateAccessToken(String username, AsyncCallback callback); diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/SecurityDTOFactory.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/SecurityDTOFactory.java index 72a99351cab..063b9f8356e 100755 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/SecurityDTOFactory.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/SecurityDTOFactory.java @@ -18,7 +18,6 @@ import com.sap.sse.security.interfaces.Social; import com.sap.sse.security.shared.AccessControlListAnnotation; import com.sap.sse.security.shared.Account; import com.sap.sse.security.shared.Account.AccountType; -import com.sap.sse.security.shared.OwnershipAnnotation; import com.sap.sse.security.shared.QualifiedObjectIdentifier; import com.sap.sse.security.shared.RoleDefinition; import com.sap.sse.security.shared.SecurityUser; @@ -28,7 +27,6 @@ import com.sap.sse.security.shared.WildcardPermission; import com.sap.sse.security.shared.dto.AccessControlListAnnotationDTO; import com.sap.sse.security.shared.dto.AccessControlListDTO; import com.sap.sse.security.shared.dto.AccountDTO; -import com.sap.sse.security.shared.dto.OwnershipAnnotationDTO; import com.sap.sse.security.shared.dto.OwnershipDTO; import com.sap.sse.security.shared.dto.RoleDefinitionDTO; import com.sap.sse.security.shared.dto.RoleWithSecurityDTO; @@ -375,12 +373,6 @@ public class SecurityDTOFactory { return new Ownership(ownerUser, ownerGroup); } - public OwnershipAnnotationDTO createOwnerShipAnnotationDTO(OwnershipAnnotation annotation) { - OwnershipDTO ownerShipDTO = createOwnershipDTO(annotation.getAnnotation(), new HashMap<>(), new HashMap<>()); - return new OwnershipAnnotationDTO(ownerShipDTO, annotation.getIdOfAnnotatedObject(), - annotation.getDisplayNameOfAnnotatedObject()); - } - public Set createStrippedUsersFromUsers(Iterable users, SecurityService securityService, Map fromOriginalToStrippedDownUser, Map fromOriginalToStrippedDownUserGroup) { diff --git a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementServiceImpl.java b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementServiceImpl.java index 5ca00c7830d..93d88b06156 100644 --- a/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementServiceImpl.java +++ b/java/com.sap.sse.security.ui/src/main/java/com/sap/sse/security/ui/server/UserManagementServiceImpl.java @@ -38,7 +38,6 @@ import com.sap.sse.security.interfaces.Credential; import com.sap.sse.security.shared.AccessControlListAnnotation; import com.sap.sse.security.shared.HasPermissions; import com.sap.sse.security.shared.HasPermissions.DefaultActions; -import com.sap.sse.security.shared.OwnershipAnnotation; import com.sap.sse.security.shared.QualifiedObjectIdentifier; import com.sap.sse.security.shared.RoleDefinition; import com.sap.sse.security.shared.TypeRelativeObjectIdentifier; @@ -48,7 +47,6 @@ import com.sap.sse.security.shared.UserManagementException; import com.sap.sse.security.shared.WildcardPermission; import com.sap.sse.security.shared.dto.AccessControlListAnnotationDTO; import com.sap.sse.security.shared.dto.AccessControlListDTO; -import com.sap.sse.security.shared.dto.OwnershipAnnotationDTO; import com.sap.sse.security.shared.dto.OwnershipDTO; import com.sap.sse.security.shared.dto.RoleDefinitionDTO; import com.sap.sse.security.shared.dto.RolesAndPermissionsForUserDTO; @@ -214,12 +212,6 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U return securityDTOFactory.createOwnershipDTO(result, new HashMap<>(), new HashMap<>()); } - @Override - public OwnershipAnnotationDTO getOwnership(QualifiedObjectIdentifier idOfOwnedObject) { - OwnershipAnnotation annotation = getSecurityService().getOwnership(idOfOwnedObject); - return securityDTOFactory.createOwnerShipAnnotationDTO(annotation); - } - @Override public Collection getAccessControlLists() throws UnauthorizedException { // TODO decide whether a global getAccessControlList functionality is needed @@ -233,45 +225,6 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U return acls; } - @Override - public AccessControlListAnnotationDTO getAccessControlList(QualifiedObjectIdentifier idOfAccessControlledObject) { - // skip permission check for ACL linked to null object since it is public anyway - if (idOfAccessControlledObject != null) { - SecurityUtils.getSubject() - .checkPermission(idOfAccessControlledObject.getStringPermission(DefaultActions.CHANGE_ACL)); - } - return securityDTOFactory.createAccessControlListAnnotationDTO(getSecurityService().getAccessControlList(idOfAccessControlledObject)); - } - - @Override - public AccessControlListDTO addToAccessControlList(QualifiedObjectIdentifier idOfAccessControlledObject, - String groupIdAsString, String action) throws UnauthorizedException { - if (SecurityUtils.getSubject() - .isPermitted(idOfAccessControlledObject.getStringPermission(DefaultActions.CHANGE_ACL))) { - UserGroup userGroup = getUserGroup(groupIdAsString); - return securityDTOFactory.createAccessControlListDTO(getSecurityService().addToAccessControlList(idOfAccessControlledObject, userGroup, action)); - } else { - throw new UnauthorizedException("Not permitted to grant permission for user"); - } - } - - private UserGroup getUserGroup(String groupIdAsString) { - UUID groupId = UUID.fromString(groupIdAsString); - return getSecurityService().getUserGroup(groupId); - } - - @Override - public AccessControlListDTO removeFromAccessControlList(QualifiedObjectIdentifier idOfAccessControlledObject, - String groupOrTenantIdAsString, String permission) throws UnauthorizedException { - // FIXME replace permission check with a valid one - if (SecurityUtils.getSubject().isPermitted("tenant:revoke_permission:" + groupOrTenantIdAsString)) { - UserGroup userGroup = getUserGroup(groupOrTenantIdAsString); - return securityDTOFactory.createAccessControlListDTO(getSecurityService().removeFromAccessControlList(idOfAccessControlledObject, userGroup, permission)); - } else { - throw new UnauthorizedException("Not permitted to revoke permission for user"); - } - } - @Override public Collection getUserGroups() { Map fromOriginalToStrippedDownUser = new HashMap<>(); @@ -308,8 +261,7 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U } } - @Override - public UserDTO getUserByName(String username) throws UnauthorizedException { + private UserDTO getUserByName(String username) throws UnauthorizedException { final User user = getSecurityService().getUserByName(username); if (user == null || SecurityUtils.getSubject() @@ -782,12 +734,6 @@ public class UserManagementServiceImpl extends RemoteServiceServlet implements U return result; } - @Override - public String getAccessToken(String username) throws UnauthorizedException { - getSecurityService().checkCurrentUserReadPermission(getUserByName(username)); - return getSecurityService().getAccessToken(username); - } - @Override public String getOrCreateAccessToken(String username) throws UnauthorizedException { getSecurityService().checkCurrentUserUpdatePermission(getUserByName(username)); diff --git a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/AccessControlStoreImpl.java b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/AccessControlStoreImpl.java index f29b683a630..c47309dc1e9 100644 --- a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/AccessControlStoreImpl.java +++ b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/AccessControlStoreImpl.java @@ -362,15 +362,21 @@ public class AccessControlStoreImpl implements AccessControlStore { LockUtil.executeWithWriteLock(lockForManagementMappings, new Runnable() { @Override public void run() { - accessControlLists.clear(); - ownerships.clear(); - userGroupToAccessControlListAnnotation.clear(); - userGroupToOwnership.clear(); - userToOwnership.clear(); + mongoObjectFactory.deleteAllOwnerships(); + mongoObjectFactory.deleteAllAccessControlLists(); + removeAll(); } }); } + private void removeAll() { + accessControlLists.clear(); + ownerships.clear(); + userGroupToAccessControlListAnnotation.clear(); + userGroupToOwnership.clear(); + userToOwnership.clear(); + } + @Override public void replaceContentsFrom(final AccessControlStore newAccessControlStore) { LockUtil.executeWithWriteLock(lockForManagementMappings, new Runnable() { diff --git a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/MongoObjectFactory.java b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/MongoObjectFactory.java index ac1161fd849..72ea6485aa7 100644 --- a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/MongoObjectFactory.java +++ b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/MongoObjectFactory.java @@ -17,27 +17,35 @@ public interface MongoObjectFactory { public void deleteAccessControlList(QualifiedObjectIdentifier idOfAccessControlledObject, AccessControlList acl); + public void deleteAllAccessControlLists(); + public void storeOwnership(OwnershipAnnotation owner); - + public void deleteOwnership(QualifiedObjectIdentifier ownedObjectId, Ownership owner); + public void deleteAllOwnerships(); + public void storeRoleDefinition(RoleDefinition role); - + public void deleteRoleDefinition(RoleDefinition role); - + public void storeUserGroup(UserGroup group); - + public void deleteUserGroup(UserGroup userGroup); public void storeUser(User user); - + public void deleteUser(User user); - + public void storeSettings(Map settings); - + public void storeSettingTypes(Map> settingTypes); + public void deleteAllSettings(); + public void storePreferences(String username, Map userMap); + public void deleteAllPreferences(); + public MongoDatabase getDatabase(); } diff --git a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/UserStoreImpl.java b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/UserStoreImpl.java index a64472623fc..7c77a093732 100644 --- a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/UserStoreImpl.java +++ b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/UserStoreImpl.java @@ -370,6 +370,17 @@ public class UserStoreImpl implements UserStore { @Override public void clear() { + if (mongoObjectFactory != null) { + users.values().forEach(mongoObjectFactory::deleteUser); + userGroups.values().forEach(mongoObjectFactory::deleteUserGroup); + roleDefinitions.values().forEach(mongoObjectFactory::deleteRoleDefinition); + mongoObjectFactory.deleteAllPreferences(); + mongoObjectFactory.deleteAllSettings(); + } + removeAll(); + } + + private void removeAll() { userGroups.clear(); userGroupsByName.clear(); LockUtil.lockForWrite(userGroupsUserCacheLock); @@ -387,6 +398,7 @@ public class UserStoreImpl implements UserStore { roleDefinitions.clear(); usersByEmail.clear(); usersByAccessToken.clear(); + } /** @@ -859,14 +871,6 @@ public class UserStoreImpl implements UserStore { } } - @Override - public Iterable getPermissionsFromUser(String username) throws UserManagementException { - if (users.get(username) == null) { - throw new UserManagementException(UserManagementException.USER_DOES_NOT_EXIST); - } - return users.get(username).getPermissions(); - } - @Override public void addPermissionForUser(String username, WildcardPermission permission) throws UserManagementException { final User user = users.get(username); @@ -1039,7 +1043,6 @@ public class UserStoreImpl implements UserStore { @Override public void registerPreferenceConverter(String preferenceKey, PreferenceConverter converter) { PreferenceConverter alreadyAssociatedConverter = preferenceConverters.putIfAbsent(preferenceKey, converter); - if (alreadyAssociatedConverter == null) { final Set usersToProcess = new HashSet<>(preferences.keySet()); for (String user : usersToProcess) { diff --git a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/MongoObjectFactoryImpl.java b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/MongoObjectFactoryImpl.java index 70d8039093b..170ee37c6ea 100644 --- a/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/MongoObjectFactoryImpl.java +++ b/java/com.sap.sse.security.userstore.mongodb/src/com/sap/sse/security/userstore/mongodb/impl/MongoObjectFactoryImpl.java @@ -94,7 +94,14 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { dbACL.put(FieldNames.AccessControlList.OBJECT_ID.name(), idOfAccessControlledObject.toString()); aclCollection.deleteOne(dbACL); } - + + @Override + public void deleteAllAccessControlLists() { + final MongoCollection aclCollection = db + .getCollection(CollectionNames.ACCESS_CONTROL_LISTS.name()); + aclCollection.deleteMany(new Document()); + } + @Override public void storeOwnership(OwnershipAnnotation owner) { MongoCollection ownershipCollection = db.getCollection(CollectionNames.OWNERSHIPS.name()); @@ -116,6 +123,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { ownershipCollection.deleteOne(dbOwnership); } + @Override + public void deleteAllOwnerships() { + final MongoCollection ownershipCollection = db + .getCollection(CollectionNames.OWNERSHIPS.name()); + ownershipCollection.deleteMany(new Document()); + } + @Override public void storeRoleDefinition(RoleDefinition role) { MongoCollection roleCollection = db.getCollection(CollectionNames.ROLES.name()); @@ -262,6 +276,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { settingCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).replaceOne(query, dbSettings, new UpdateOptions().upsert(true)); } + @Override + public void deleteAllSettings() { + final MongoCollection settingsCollection = db + .getCollection(CollectionNames.SETTINGS.name()); + settingsCollection.deleteMany(new Document()); + } + @Override public void storePreferences(String username, Map userMap) { BasicDBList dbSettings = new BasicDBList(); @@ -277,6 +298,13 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { settingCollection.withWriteConcern(WriteConcern.ACKNOWLEDGED).replaceOne(query, update, new UpdateOptions().upsert(true)); } + @Override + public void deleteAllPreferences() { + final MongoCollection preferencesCollection = db + .getCollection(CollectionNames.PREFERENCES.name()); + preferencesCollection.deleteMany(new Document()); + } + @Override public void storeSettingTypes(Map> settingTypes) { MongoCollection settingCollection = db.getCollection(CollectionNames.SETTINGS.name()); @@ -303,4 +331,5 @@ public class MongoObjectFactoryImpl implements MongoObjectFactory { } return dbSettingTypes; } + } diff --git a/java/com.sap.sse.security/resources/shiro.ini b/java/com.sap.sse.security/resources/shiro.ini index 3f3b57c21ad..6514a930e58 100755 --- a/java/com.sap.sse.security/resources/shiro.ini +++ b/java/com.sap.sse.security/resources/shiro.ini @@ -78,4 +78,5 @@ bearerTokenOrAnonymous = com.sap.sse.security.BearerTokenOrBasicOrFormOrAnonymou /api/restsecurity/role = bearerToken /api/restsecurity/role/** = bearerToken /api/restsecurity/ownership/** = bearerTokenOrAnonymous -/api/restsecurity/has_permission = bearerTokenOrAnonymous \ No newline at end of file +/api/restsecurity/has_permission = bearerTokenOrAnonymous +/api/restsecurity/preferences/** = bearerToken \ No newline at end of file diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/SecurityService.java b/java/com.sap.sse.security/src/com/sap/sse/security/SecurityService.java index d37cf25182d..3b9721eaeb8 100644 --- a/java/com.sap.sse.security/src/com/sap/sse/security/SecurityService.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/SecurityService.java @@ -33,7 +33,6 @@ import com.sap.sse.security.shared.PermissionChecker; import com.sap.sse.security.shared.QualifiedObjectIdentifier; import com.sap.sse.security.shared.RoleDefinition; import com.sap.sse.security.shared.RolePrototype; -import com.sap.sse.security.shared.SocialUserAccount; import com.sap.sse.security.shared.TypeRelativeObjectIdentifier; import com.sap.sse.security.shared.UserGroupManagementException; import com.sap.sse.security.shared.UserManagementException; @@ -73,8 +72,6 @@ public interface SecurityService extends ReplicableWithObjectInputStream getAccessControlLists(); AccessControlListAnnotation getAccessControlList(QualifiedObjectIdentifier idOfAccessControlledObject); @@ -179,9 +176,6 @@ public interface SecurityService extends ReplicableWithObjectInputStream getPermissionsFromUser(String username) throws UserManagementException; - void removePermissionFromUser(String username, WildcardPermission permissionToRemove); void addPermissionForUser(String username, WildcardPermission permissionToAdd); @@ -246,8 +238,6 @@ public interface SecurityService extends ReplicableWithObjectInputStream T getSetting(String key, Class clazz); - Map getAllSettings(); Map> getAllSettingTypes(); @@ -340,8 +330,6 @@ public interface SecurityService extends ReplicableWithObjectInputStream objectsToFilter, Consumer filteredObjectsConsumer); - void filterObjectsWithPermissionForCurrentUser( - com.sap.sse.security.shared.HasPermissions.Action[] actions, Iterable objectsToFilter, - Consumer filteredObjectsConsumer); - /** * Filters objects with any of the given permissions for the current user. */ @@ -413,10 +397,6 @@ public interface SecurityService extends ReplicableWithObjectInputStream List mapAndFilterByReadPermissionForCurrentUser( Iterable objectsToFilter, Function filteredObjectsMapper); - List mapAndFilterByExplicitPermissionForCurrentUser( - HasPermissions.Action[] actions, Iterable objectsToFilter, - Function filteredObjectsMapper); - /** * Maps and filters by any of the given permissions for the current user. */ @@ -521,9 +501,6 @@ public interface SecurityService extends ReplicableWithObjectInputStream allInstances); - boolean hasCurrentUserRoleForOwnedObject(HasPermissions type, T object, - RoleDefinition roleToCheck); - boolean hasCurrentUserMetaPermission(WildcardPermission permissionToCheck, Ownership ownership); boolean hasCurrentUserMetaPermissionWithOwnershipLookup(WildcardPermission permissionToCheck); diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java b/java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java index 3a671ef1ebc..7d4fe428c54 100755 --- a/java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java @@ -91,7 +91,6 @@ import com.sap.sse.replication.OperationsToMasterSendingQueue; import com.sap.sse.replication.ReplicationMasterDescriptor; import com.sap.sse.replication.ReplicationService; import com.sap.sse.security.Action; -import com.sap.sse.security.BearerAuthenticationToken; import com.sap.sse.security.ClientUtils; import com.sap.sse.security.GithubApi; import com.sap.sse.security.InstagramApi; @@ -103,7 +102,6 @@ import com.sap.sse.security.SessionUtils; import com.sap.sse.security.interfaces.AccessControlStore; import com.sap.sse.security.interfaces.Credential; import com.sap.sse.security.interfaces.OAuthToken; -import com.sap.sse.security.interfaces.Social; import com.sap.sse.security.interfaces.SocialSettingsKeys; import com.sap.sse.security.interfaces.UserImpl; import com.sap.sse.security.interfaces.UserStore; @@ -156,7 +154,6 @@ import com.sap.sse.security.shared.QualifiedObjectIdentifier; import com.sap.sse.security.shared.RoleDefinition; import com.sap.sse.security.shared.RolePrototype; import com.sap.sse.security.shared.SecurityAccessControlList; -import com.sap.sse.security.shared.SocialUserAccount; import com.sap.sse.security.shared.TypeRelativeObjectIdentifier; import com.sap.sse.security.shared.UserGroupManagementException; import com.sap.sse.security.shared.UserManagementException; @@ -500,12 +497,6 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat public OwnershipAnnotation getOwnership(QualifiedObjectIdentifier idOfOwnedObjectAsString) { return accessControlStore.getOwnership(idOfOwnedObjectAsString); } - - @Override - public OwnershipAnnotation createDefaultOwnershipForNewObject(QualifiedObjectIdentifier idOfNewObject) { - return new OwnershipAnnotation(new Ownership(getCurrentUser(), getDefaultTenantForCurrentUser()), - idOfNewObject, /* display name */ idOfNewObject.toString()); - } public UserGroup getDefaultTenantForUser(User user) { UserGroup specificTenant = temporaryDefaultTenant.get(); @@ -687,7 +678,6 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat } final UUID tenantId = tenantOwner == null ? null : tenantOwner.getId(); final String userOwnerName = userOwner == null ? null : userOwner.getName(); - return apply(new SetOwnershipOperation(idOfOwnedObjectAsString, userOwnerName, tenantId, displayNameOfOwnedObject)); } @@ -860,21 +850,6 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat return redirectUrl; } - @Override - public User loginByAccessToken(String accessToken) { - BearerAuthenticationToken token = new BearerAuthenticationToken(accessToken); - logger.info("Trying to login with access token"); - Subject subject = SecurityUtils.getSubject(); - try { - subject.login(token); - final String username = (String) token.getPrincipal(); - return store.getUserByName(username); - } catch (AuthenticationException e) { - logger.log(Level.INFO, "Authentication failed with access token "+accessToken); - throw e; - } - } - @Override public void logout() { Subject subject = SecurityUtils.getSubject(); @@ -1232,11 +1207,6 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat return null; } - @Override - public Iterable getPermissionsFromUser(String username) throws UserManagementException { - return store.getPermissionsFromUser(username); - } - @Override public void removePermissionFromUser(String username, WildcardPermission permissionToRemove) { apply(new RemovePermissionForUserOperation(username, permissionToRemove)); @@ -1312,11 +1282,6 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat return store.setSetting(key, setting); } - @Override - public T getSetting(String key, Class clazz) { - return store.getSetting(key, clazz); - } - @Override public Map getAllSettings() { return store.getAllSettings(); @@ -1327,20 +1292,6 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat return store.getAllSettingTypes(); } - @Override - public User createSocialUser(String name, SocialUserAccount socialUserAccount) - throws UserManagementException, UserGroupManagementException { - if (store.getUserByName(name) != null) { - throw new UserManagementException(UserManagementException.USER_ALREADY_EXISTS); - } - User result = store.createUser(name, socialUserAccount.getProperty(Social.EMAIL.name()), - socialUserAccount); - UserGroup tenant = getOrCreateTenantForUser(result); - accessControlStore.setOwnership(tenant.getIdentifier(), result, tenant, tenant.getName()); - addUserToUserGroup(tenant, result); - return result; - } - @Override public User verifySocialUser(Credential credential) throws UserManagementException { OAuthToken otoken = new OAuthToken(credential, credential.getVerifier()); @@ -1945,22 +1896,6 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat }); } - @Override - public void filterObjectsWithPermissionForCurrentUser( - HasPermissions.Action[] actions, Iterable objectsToFilter, - Consumer filteredObjectsConsumer) { - objectsToFilter.forEach(objectToCheck -> { - boolean isPermitted = actions.length > 0; - for (int i = 0; i < actions.length; i++) { - isPermitted &= SecurityUtils.getSubject().isPermitted( - objectToCheck.getIdentifier().getStringPermission(actions[i])); - } - if (isPermitted) { - filteredObjectsConsumer.accept(objectToCheck); - } - }); - } - /** Filters the objects with any of the given permissions for the current user */ @Override public void filterObjectsWithAnyPermissionForCurrentUser( @@ -1990,16 +1925,6 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat return result; } - @Override - public List mapAndFilterByExplicitPermissionForCurrentUser( - HasPermissions.Action[] actions, Iterable objectsToFilter, - Function filteredObjectsMapper) { - final List result = new ArrayList<>(); - filterObjectsWithPermissionForCurrentUser(actions, objectsToFilter, - filteredObject -> result.add(filteredObjectsMapper.apply(filteredObject))); - return result; - } - @Override public List mapAndFilterByAnyExplicitPermissionForCurrentUser( HasPermissions permittedObject, HasPermissions.Action[] actions, Iterable objectsToFilter, @@ -2015,17 +1940,6 @@ public class SecurityServiceImpl implements ReplicableSecurityService, ClearStat return store.getUserByName(SecurityService.ALL_USERNAME); } - @Override - public boolean hasCurrentUserRoleForOwnedObject(HasPermissions type, T object, - RoleDefinition roleToCheck) { - assert type != null; - assert object != null; - assert roleToCheck != null; - OwnershipAnnotation ownershipToCheck = getOwnership(object.getIdentifier()); - return PermissionChecker.ownsUserASpecificRole(getCurrentUser(), getAllUser(), - ownershipToCheck == null ? null : ownershipToCheck.getAnnotation(), roleToCheck.getName()); - } - @Override public boolean hasCurrentUserMetaPermission(WildcardPermission permissionToCheck, Ownership ownership) { if (hasPermissionsProvider == null) { diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/OwnershipResource.java b/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/OwnershipResource.java index 9af20f5efb0..6f60f238040 100644 --- a/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/OwnershipResource.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/OwnershipResource.java @@ -1,8 +1,5 @@ package com.sap.sse.security.jaxrs.api; -import java.io.BufferedWriter; -import java.io.OutputStream; -import java.io.OutputStreamWriter; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -20,7 +17,6 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import javax.ws.rs.core.StreamingOutput; import javax.ws.rs.core.Response.Status; import org.apache.shiro.SecurityUtils; @@ -128,7 +124,7 @@ public class OwnershipResource extends AbstractSecurityResource { result.put(KEY_GROUP_ID, existingOwnership == null || existingOwnership.getAnnotation().getTenantOwner() == null ? null : existingOwnership.getAnnotation().getTenantOwner().getId().toString()); result.put(KEY_USERNAME, existingOwnership == null || existingOwnership.getAnnotation().getUserOwner() == null ? null : existingOwnership.getAnnotation().getUserOwner().getName()); result.put(KEY_DISPLAY_NAME, existingOwnership == null || existingOwnership.getDisplayNameOfAnnotatedObject() == null ? null : existingOwnership.getDisplayNameOfAnnotatedObject()); - return Response.ok((StreamingOutput) (OutputStream output)->result.writeJSONString(new BufferedWriter(new OutputStreamWriter(output)))).build(); + return Response.ok(streamingOutput(result)).build(); } @Path("{objectType}/{typeRelativeObjectId}/acl") @@ -155,7 +151,7 @@ public class OwnershipResource extends AbstractSecurityResource { actionsForGroup.put(KEY_ACTIONS, actions); } } - return Response.ok((StreamingOutput) (OutputStream output)->result.writeJSONString(new BufferedWriter(new OutputStreamWriter(output)))).build(); + return Response.ok(streamingOutput(result)).build(); } @Path("{objectType}/{typeRelativeObjectId}/acl") diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/PreferencesResource.java b/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/PreferencesResource.java similarity index 64% rename from java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/PreferencesResource.java rename to java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/PreferencesResource.java index de1adc2a2f7..67cf9efd7a5 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/PreferencesResource.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/PreferencesResource.java @@ -1,4 +1,4 @@ -package com.sap.sailing.server.gateway.jaxrs.api; +package com.sap.sse.security.jaxrs.api; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -13,22 +13,18 @@ import javax.ws.rs.core.Response; import org.apache.shiro.SecurityUtils; import org.json.simple.parser.ParseException; -import com.sap.sailing.server.gateway.deserialization.JsonDeserializationException; -import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; -import com.sap.sse.security.SecurityService; +import com.sap.sse.security.jaxrs.AbstractSecurityResource; -@Path("/v1/preferences") -public class PreferencesResource extends AbstractSailingServerResource { +@Path("/restsecurity/preferences") +public class PreferencesResource extends AbstractSecurityResource { @GET @Produces("application/json;charset=UTF-8") @Path("{settingsKey}") - public Response getPreference(@PathParam("settingsKey") String settingsKey) - throws ParseException, JsonDeserializationException { + public Response getPreference(@PathParam("settingsKey") String settingsKey) throws ParseException { Response response = null; if (SecurityUtils.getSubject().isAuthenticated()) { String username = SecurityUtils.getSubject().getPrincipal().toString(); - SecurityService securityService = getService(SecurityService.class); - String settings = securityService.getPreference(username, settingsKey); + String settings = getService().getPreference(username, settingsKey); if (settings == null) { response = Response.noContent().build(); } else { @@ -43,13 +39,11 @@ public class PreferencesResource extends AbstractSailingServerResource { @PUT @Consumes(MediaType.APPLICATION_JSON) @Path("{settingsKey}") - public Response putPreference(@PathParam("settingsKey") String settingsKey, String json) - throws ParseException, JsonDeserializationException { + public Response putPreference(@PathParam("settingsKey") String settingsKey, String json) throws ParseException { Response response = null; if (SecurityUtils.getSubject().isAuthenticated()) { String username = SecurityUtils.getSubject().getPrincipal().toString(); - SecurityService securityService = getService(SecurityService.class); - securityService.setPreference(username, settingsKey, json); + getService().setPreference(username, settingsKey, json); response = Response.ok().build(); } else { response = Response.status(401).build(); @@ -60,13 +54,11 @@ public class PreferencesResource extends AbstractSailingServerResource { @DELETE @Produces("application/json;charset=UTF-8") @Path("{settingsKey}") - public Response deletePreference(@PathParam("settingsKey") String settingsKey) - throws ParseException, JsonDeserializationException { + public Response deletePreference(@PathParam("settingsKey") String settingsKey) throws ParseException { Response response = null; if (SecurityUtils.getSubject().isAuthenticated()) { String username = SecurityUtils.getSubject().getPrincipal().toString(); - SecurityService securityService = getService(SecurityService.class); - securityService.unsetPreference(username, settingsKey); + getService().unsetPreference(username, settingsKey); response = Response.ok().build(); } else { response = Response.status(401).build(); diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/RestApiApplication.java b/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/RestApiApplication.java index 5caf9ec1301..afc4f74f450 100644 --- a/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/RestApiApplication.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/RestApiApplication.java @@ -15,6 +15,7 @@ public class RestApiApplication extends Application { classes.add(UserGroupResource.class); classes.add(RoleResource.class); classes.add(OwnershipResource.class); + classes.add(PreferencesResource.class); // exception mapper classes.add(ShiroAuthorizationExceptionTo401ResponseMapper.class); classes.add(OwnershipExceptionHandler.class); diff --git a/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/UserGroupResource.java b/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/UserGroupResource.java index acb6272b6d6..bfe35fc78bc 100644 --- a/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/UserGroupResource.java +++ b/java/com.sap.sse.security/src/com/sap/sse/security/jaxrs/api/UserGroupResource.java @@ -1,11 +1,14 @@ package com.sap.sse.security.jaxrs.api; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.UUID; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; +import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @@ -14,14 +17,17 @@ import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import org.apache.shiro.subject.SimplePrincipalCollection; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.JSONValue; +import org.json.simple.parser.ParseException; import com.sap.sse.common.Util; import com.sap.sse.security.jaxrs.AbstractSecurityResource; import com.sap.sse.security.shared.RoleDefinition; import com.sap.sse.security.shared.UserGroupManagementException; +import com.sap.sse.security.shared.HasPermissions.DefaultActions; import com.sap.sse.security.shared.impl.Ownership; import com.sap.sse.security.shared.impl.SecuredSecurityTypes; import com.sap.sse.security.shared.impl.User; @@ -70,13 +76,62 @@ public class UserGroupResource extends AbstractSecurityResource { return response; } + @GET + @Path("list/groupsUserIsPartOf") + @Produces("application/json;charset=UTF-8") + public Response getUserGroupsCurrentUserIsPartOf() throws ParseException { + Response response = null; + User user = getService().getCurrentUser(); + if (user != null) { + JSONObject root = new JSONObject(); + JSONArray groups = new JSONArray(); + root.put("groupsUserIsPartOf", groups); + for (UserGroup group : user.getUserGroups()) { + groups.add(convertUserGroupToJson(group, /* includingUSers */ false, /* includingRoles */ false)); + } + response = Response.ok(streamingOutput(root)).build(); + } else { + response = Response.status(401).build(); + } + return response; + } + + @GET + @Path("list/readable") + @Produces("application/json;charset=UTF-8") + public Response getReadableUserGroupsForCurrentUser(@QueryParam("userName") String userName) { + Response response = null; + final User user = userName != null ? getService().getUserByName(userName) : getService().getCurrentUser(); + if (user != null && getService().hasCurrentUserReadPermission(user)) { + final List userGroups = new ArrayList<>(); + getService().getUserGroupList().forEach(ug -> { + if (getService().getSecurityManager().isPermitted( + new SimplePrincipalCollection(user.getName(), user.getName()), + ug.getIdentifier().getPermission(DefaultActions.READ).toString())) { + userGroups.add(ug); + } + }); + final JSONObject root = new JSONObject(); + final JSONArray userGroupsJson = new JSONArray(); + userGroups.forEach(ug -> userGroupsJson + .add(convertUserGroupToJson(ug, /* includingUsers */ false, /* includingRoles */ true))); + response = Response.ok(root.toJSONString()).build(); + root.put("readableGroups", userGroupsJson); + response = Response.ok().entity(streamingOutput(root)).build(); + } else { + response = Response.status(Status.UNAUTHORIZED).build(); + } + return response; + } + private Response handleExistingUserGroup(final UserGroup usergroup) { Response response; if (usergroup == null) { response = Response.status(Status.BAD_REQUEST).entity("Usergroup with this id does not exist.").build(); } else { if (getService().hasCurrentUserReadPermission(usergroup)) { - final JSONObject jsonResult = convertUserGroupToJson(usergroup); + final JSONObject jsonResult = convertUserGroupToJson(usergroup, /* includingUsers */ true, + /* includingRoles */ true); response = Response.ok(streamingOutput(jsonResult)).build(); } else { response = Response.status(Status.UNAUTHORIZED).build(); @@ -86,32 +141,39 @@ public class UserGroupResource extends AbstractSecurityResource { } /** Returns a json object with id, groupname, roles and user names (filtered to thouse the current user can see). */ - private JSONObject convertUserGroupToJson(final UserGroup usergroup) { + private JSONObject convertUserGroupToJson(final UserGroup usergroup, boolean includingUsers, + boolean includingRoles) { final JSONObject jsonResult = new JSONObject(); jsonResult.put(KEY_GROUP_ID, usergroup.getId().toString()); jsonResult.put(KEY_GROUP_NAME, usergroup.getName()); - final JSONArray jsonUsersInGroup = new JSONArray(); - for (final User user : usergroup.getUsers()) { - // filter users - if (getService().hasCurrentUserReadPermission(user)) { - jsonUsersInGroup.add(user.getId()); + if (includingUsers) { + final JSONArray jsonUsersInGroup = new JSONArray(); + for (final User user : usergroup.getUsers()) { + // filter users + if (getService().hasCurrentUserReadPermission(user)) { + jsonUsersInGroup.add(user.getId()); + } } + jsonResult.put(KEY_USERS, jsonUsersInGroup); } - jsonResult.put(KEY_USERS, jsonUsersInGroup); - final JSONArray jsonRolesOfGroup = new JSONArray(); - for (final Map.Entry roleDefinition : usergroup.getRoleDefinitionMap().entrySet()) { - // filter users - if (getService().hasCurrentUserReadPermission(roleDefinition.getKey())) { - JSONObject roleJson = new JSONObject(); - roleJson.put(KEY_ROLE_ID, roleDefinition.getKey().getId().toString()); - roleJson.put(KEY_ROLE_NAME, roleDefinition.getKey().getName()); - roleJson.put(KEY_FOR_ALL, roleDefinition.getValue()); - jsonRolesOfGroup.add(roleJson); + if (includingRoles) { + final JSONArray jsonRolesOfGroup = new JSONArray(); + for (final Map.Entry roleDefinition : usergroup.getRoleDefinitionMap() + .entrySet()) { + // filter users + if (getService().hasCurrentUserReadPermission(roleDefinition.getKey())) { + JSONObject roleJson = new JSONObject(); + roleJson.put(KEY_ROLE_ID, roleDefinition.getKey().getId().toString()); + roleJson.put(KEY_ROLE_NAME, roleDefinition.getKey().getName()); + roleJson.put(KEY_FOR_ALL, roleDefinition.getValue()); + jsonRolesOfGroup.add(roleJson); + } } + jsonResult.put(KEY_ROLES, jsonRolesOfGroup); } - jsonResult.put(KEY_ROLES, jsonRolesOfGroup); + return jsonResult; } @@ -141,7 +203,7 @@ public class UserGroupResource extends AbstractSecurityResource { if (group == null) { response = Response.status(Status.INTERNAL_SERVER_ERROR).entity("Could not create user group.").build(); } else { - response = Response.status(Status.CREATED).entity(streamingOutput(convertUserGroupToJson(group))).build(); + response = Response.status(Status.CREATED).entity(streamingOutput(convertUserGroupToJson(group, /* includingUsers */ true, /* includingRoles */ true))).build(); } } @@ -317,7 +379,6 @@ public class UserGroupResource extends AbstractSecurityResource { public Response deleteRoleFromUserGroup(@PathParam(KEY_GROUP_ID) String userGroupId, @PathParam(KEY_ROLE_ID) String roleIdString) { Response response; - try { final UUID groupId = UUID.fromString(userGroupId); final UserGroup usergroup = getService().getUserGroup(groupId); @@ -357,4 +418,54 @@ public class UserGroupResource extends AbstractSecurityResource { } return response; } + + @POST + @Produces("application/json;charset=UTF-8") + @Path("setDefaultTenantForCurrentServerAndUser") + public Response setDefaultTenantForCurrentServerAndUser(@QueryParam("tenantGroup") UUID tenantId) + throws ParseException { + Response response = null; + User user = getService().getCurrentUser(); + if (user != null) { + getService().setDefaultTenantForCurrentServerForUser(user.getName(), tenantId); + response = Response.ok().build(); + } else { + response = Response.status(401).build(); + } + return response; + } + + @POST + @Path("addAnyUserToGroup") + @Produces("application/json;charset=UTF-8") + public Response addGroupToUserWithoutPermissionOnUser(@QueryParam("userName") String userName, + @QueryParam("groupId") UUID userGroupId) { + Response response = null; + final User user = getService().getUserByName(userName); + if (user != null) { + final UserGroup userGroup = getService().getUserGroup(userGroupId); + if (userGroup != null) { + if (!Util.contains(userGroup.getUsers(), user)) { + if (getService().hasCurrentUserUpdatePermission(userGroup)) { + if (!getService().hasCurrentUserMetaPermissionsOfRoleDefinitionsWithQualification( + userGroup.getRoleDefinitionMap().keySet(), new Ownership(null, userGroup))) { + response = Response.status(Status.UNAUTHORIZED).build(); + } else { + getService().addUserToUserGroup(userGroup, user); + response = Response.ok().build(); + } + } else { + response = Response.status(Status.UNAUTHORIZED).build(); + } + } else { + response = Response.status(Status.BAD_REQUEST).entity("User is already in this group.").build(); + } + } else { + response = Response.status(Status.BAD_REQUEST).entity("User Group does not exist.").build(); + } + } else { + response = Response.status(Status.BAD_REQUEST).entity("User does not exist.").build(); + } + return response; + } } diff --git a/java/com.sap.sse.security/webservices/api/index.html b/java/com.sap.sse.security/webservices/api/index.html index c09d0d5c594..4951479ec39 100755 --- a/java/com.sap.sse.security/webservices/api/index.html +++ b/java/com.sap.sse.security/webservices/api/index.html @@ -70,6 +70,30 @@ be http://sapsailing.com/security/api/restsecurity/login. /api/restsecurity/ownership Change Object ownership + + /api/restsecurity/usergroups/setDefaultTenantForCurrentServerAndUser + Allows to set a default tenant for the current user + + + /api/restsecurity/usergroups/addAnyUserToGroup + Allows to add a user to a group without permissions on the user. + + + /api/restsecurity/usergroups/readable + Lists all usergroups the current user or any user has readable permission for + + + /api/restsecurity/preferences/{SETTINGS_KEY} + Stores a document into the preferences of a user + + + /api/restsecurity/preferences/{SETTINGS_KEY} + Retrives a document that was stored into the preferences of a user + + + /api/restsecurity/preferences/{SETTINGS_KEY} + Removes a document from the preferences of a user + diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/preferencesDelete.html b/java/com.sap.sse.security/webservices/api/preferencesDelete.html similarity index 88% rename from java/com.sap.sailing.server.gateway/webservices/api/v1/preferencesDelete.html rename to java/com.sap.sse.security/webservices/api/preferencesDelete.html index 772301ddb3c..42f153ecb99 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/preferencesDelete.html +++ b/java/com.sap.sse.security/webservices/api/preferencesDelete.html @@ -9,7 +9,7 @@

    SAP Sailing Analytics Webservices API Version 1.0

    -

    URL: /api/v1/preferences/{SETTINGS_KEY}/

    +

    URL: /api/restsecurity/preferences/{SETTINGS_KEY}/

    Description:

    Deletes whatever is stored under SETTINGS_KEY in currently logged in users preferences

    @@ -30,7 +30,7 @@ Examples: - Delete @ http://sapsailing.com/sailingserver/api/v1/preferences/testSetting/ + Delete @ http://sapsailing.com/security/api/restsecurity/preferences/testSetting/
    Answer: Ok diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/preferencesGet.html b/java/com.sap.sse.security/webservices/api/preferencesGet.html similarity index 93% rename from java/com.sap.sailing.server.gateway/webservices/api/v1/preferencesGet.html rename to java/com.sap.sse.security/webservices/api/preferencesGet.html index a6a023a935c..8d8d7fde5b7 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/preferencesGet.html +++ b/java/com.sap.sse.security/webservices/api/preferencesGet.html @@ -30,7 +30,7 @@ Examples: - Get @ http://sapsailing.com/sailingserver/api/v1/preferences/testSetting/ + Get @ http://sapsailing.com/security/api/restsecurity/preferences/testSetting/
    Answer: No Content Status code, or Ok and the stored document diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/preferencesPut.html b/java/com.sap.sse.security/webservices/api/preferencesPut.html similarity index 93% rename from java/com.sap.sailing.server.gateway/webservices/api/v1/preferencesPut.html rename to java/com.sap.sse.security/webservices/api/preferencesPut.html index 5acf8a45e6d..c1ff2fe8d27 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/preferencesPut.html +++ b/java/com.sap.sse.security/webservices/api/preferencesPut.html @@ -30,7 +30,7 @@ Examples: - Put @ http://sapsailing.com/sailingserver/api/v1/preferences/testSetting/ + Put @ http://sapsailing.com/security/api/restsecurity/preferences/testSetting/
    Answer: Ok diff --git a/java/com.sap.sailing.server.gateway/webservices/api/v1/usergroupsGet.html b/java/com.sap.sse.security/webservices/api/usergroupsAddAnyUserToGroup.html similarity index 58% rename from java/com.sap.sailing.server.gateway/webservices/api/v1/usergroupsGet.html rename to java/com.sap.sse.security/webservices/api/usergroupsAddAnyUserToGroup.html index 44020be718b..8d3829d2c74 100644 --- a/java/com.sap.sailing.server.gateway/webservices/api/v1/usergroupsGet.html +++ b/java/com.sap.sse.security/webservices/api/usergroupsAddAnyUserToGroup.html @@ -9,10 +9,10 @@

    SAP Sailing Analytics Webservices API Version 1.0

    -

    URL: /api/v1/usergroups/

    +

    URL: /api/restsecurity/usergroups/addAnyUserToGroup

    Description: -

    Gets the usergroup names and id's the currently logged in user is part of

    +

    Adds an existing user to an existing group without having permission on the user.


    @@ -21,19 +21,26 @@ - - - - - - + + + + + + + + + + + + +
    Output format:Json
    Mandatory parameters: none
    Examples: - Get @ http://sapsailing.com/sailingserver/api/v1/usergroups/ -
    +
    Mandatory parameters:userName - name of user to add to the group
    + groupId - Id of the group
    Optional parameters:None
    Request method:POST
    Example:http://sapsailing.com/security/api/restsecurity/usergroup/addAnyUserToGroup?groupId=e406d1c5-d613-48d7-9d56-f0573ad61194&userName=user1
    Back to Web Service Overview diff --git a/java/com.sap.sse.security/webservices/api/usergroupsGetReadable.html b/java/com.sap.sse.security/webservices/api/usergroupsGetReadable.html new file mode 100644 index 00000000000..e056ca54303 --- /dev/null +++ b/java/com.sap.sse.security/webservices/api/usergroupsGetReadable.html @@ -0,0 +1,66 @@ + + + + + + + + SAP Sailing Analytics Webservices API Version 1.0 + + +

    SAP Sailing Analytics Webservices API Version 1.0

    +

    URL: /api/restsecurity/usergroups/readable

    + +Description: +

    Gets the usergroups a user or the current logged in user can read.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Webservice Type:REST
    Output format:Json
    Request method:GET
    Mandatory parameters:none
    Optional parameters:userName: username of he user to obtain readable groups from. If this is not set, the readable groups of the currently logged in user are returned.
    Examples: + Get @ http://sapsailing.com/security/api/restsecurity/usergroup/readable +
    + Example payload:
    +
    +{
    +    "readableGroups": [
    +        {
    +            "uuid": "96759067-7090-413d-94c5-8367c2e34b9f",
    +            "name": "group2ToAdd",
    +            "roles": []
    +        },
    +        {
    +            "uuid": "a8f98697-6d74-42da-b516-430279d9dadd",
    +            "name": "user1-tenant",
    +            "roles": []
    +        }
    +    ]
    +}
    +
    +
    +
    +Back to Web Service Overview + + diff --git a/java/com.sap.sse.security/webservices/api/usergroupsSetDefaultTenantForCurrentServerAndUser.html b/java/com.sap.sse.security/webservices/api/usergroupsSetDefaultTenantForCurrentServerAndUser.html new file mode 100644 index 00000000000..91f9c57c2ae --- /dev/null +++ b/java/com.sap.sse.security/webservices/api/usergroupsSetDefaultTenantForCurrentServerAndUser.html @@ -0,0 +1,48 @@ + + + + + + + + SAP Sailing Analytics Webservices API Version 1.0 + + +

    SAP Sailing Analytics Webservices API Version 1.0

    +

    URL: /api/restsecurity/usergroups/setDefaultTenantForCurrentServerAndUser

    + +Description: +

    Sets the users default tenant to the given usergroup or clears any prior assignment. +This default tenant or "group" is the group used for the group ownership of new objects +created on the user's behalf.

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    Webservice Type:REST
    Output format:none
    Mandatory parameters:None
    Optional parameters:tenantGroup UUID of the new tenant group, can be null
    Request method:POST
    Example:http://sapsailing.com/security/api/restsecurity/usergroup/setDefaultTenantForCurrentServerAndUser?tenantGroup=e406d1c5-d613-48d7-9d56-f0573ad61194
    +
    +Back to Web Service Overview + + diff --git a/java/com.sap.sse.shared.android/src/com/sap/sse/util/WeakReferenceWithCleanerCallback.java b/java/com.sap.sse.shared.android/src/com/sap/sse/util/WeakReferenceWithCleanerCallback.java new file mode 100755 index 00000000000..a0f9dc1716e --- /dev/null +++ b/java/com.sap.sse.shared.android/src/com/sap/sse/util/WeakReferenceWithCleanerCallback.java @@ -0,0 +1,61 @@ +package com.sap.sse.util; + +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * A generic weak reference that maintains a {@link Runnable callback} which is invoked when the reference + * is enqueued after it has been cleared by the garbage collector.

    + * + * Make sure to not create a strong reference from the callback to the referent because this will keep the + * weak reference from ever being enqueued as its referent will remain strongly referenced. + * + * @author Axel Uhl (D043530) + * + * @param + */ +public class WeakReferenceWithCleanerCallback extends WeakReference { + private static final Logger logger = Logger.getLogger(WeakReferenceWithCleanerCallback.class.getName()); + private static ReferenceQueue> queue = new ReferenceQueue<>(); + + private final Runnable cleanerCallback; + + static { + Thread t = new Thread(WeakReferenceWithCleanerCallback.class.getSimpleName() + " weak reference cleaner") { + @Override + public void run() { + while (true) { + try { + final Reference> ref = queue.remove(); + final Runnable callback = ((WeakReferenceWithCleanerCallback) ref).cleanerCallback; + if (callback != null) { + callback.run(); + } + } catch (InterruptedException e) { + logger.log(Level.SEVERE, "Error trying to clean weak reference", e); + } catch (Exception e2) { + logger.severe("Shouldn't have gotten here. Continuing..."); + } + } + } + }; + t.setDaemon(true); + t.start(); + } + + /** + * @param cleanerCallback + * ensure that no strong reference exists from this parameter object to the {@code referent} or else this + * weak reference will never be cleared and hence will never be enqueued. May be {@code null} in which case + * simply no callback will be triggered when this reference is enqueued; use a regular {@link WeakReference} + * instead in this case! + */ + public WeakReferenceWithCleanerCallback(T referent, Runnable cleanerCallback) { + super(referent); + this.cleanerCallback = cleanerCallback; + } +} + diff --git a/java/com.sap.sse/src/com/sap/sse/util/AbstractMXBeanImpl.java b/java/com.sap.sse/src/com/sap/sse/util/AbstractMXBeanImpl.java deleted file mode 100644 index 2c92a57de3b..00000000000 --- a/java/com.sap.sse/src/com/sap/sse/util/AbstractMXBeanImpl.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.sap.sse.util; - -public abstract class AbstractMXBeanImpl { - protected String escapeIllegalObjectNameCharacters(String name) { - return name.replaceAll("[:/,]", "_"); - } -} diff --git a/java/com.sap.sse/src/com/sap/sse/util/apachelog/LogEntry.java b/java/com.sap.sse/src/com/sap/sse/util/apachelog/LogEntry.java index a053288d34b..82387ac122a 100644 --- a/java/com.sap.sse/src/com/sap/sse/util/apachelog/LogEntry.java +++ b/java/com.sap.sse/src/com/sap/sse/util/apachelog/LogEntry.java @@ -93,7 +93,9 @@ public class LogEntry { } public TimePoint getTimepoint() throws ParseException { - return new MillisecondsTimePoint(dateFormat.parse(getTimestampString())); + synchronized (dateFormat) { + return new MillisecondsTimePoint(dateFormat.parse(getTimestampString())); + } } public String getRequest() { diff --git a/java/com.sap.sse/src/com/sap/sse/util/apachelog/PerHostnameEntry.java b/java/com.sap.sse/src/com/sap/sse/util/apachelog/PerHostnameEntry.java index 7fd96788267..2ce0aea2702 100644 --- a/java/com.sap.sse/src/com/sap/sse/util/apachelog/PerHostnameEntry.java +++ b/java/com.sap.sse/src/com/sap/sse/util/apachelog/PerHostnameEntry.java @@ -37,7 +37,9 @@ public class PerHostnameEntry { int tmpYear; int tmpZeroBasedMonth; try { - cal.setTime(dateFormat.parse(dateString)); + synchronized (dateFormat) { + cal.setTime(dateFormat.parse(dateString)); + } tmpYear = cal.get(Calendar.YEAR); tmpZeroBasedMonth = cal.get(Calendar.MONTH); } catch (ParseException e) { diff --git a/java/com.sap.sse/src/com/sap/sse/util/impl/ThreadPoolMXBeanImpl.java b/java/com.sap.sse/src/com/sap/sse/util/impl/ThreadPoolMXBeanImpl.java index d3484be8dc5..78238724fd1 100644 --- a/java/com.sap.sse/src/com/sap/sse/util/impl/ThreadPoolMXBeanImpl.java +++ b/java/com.sap.sse/src/com/sap/sse/util/impl/ThreadPoolMXBeanImpl.java @@ -3,10 +3,9 @@ package com.sap.sse.util.impl; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; -import com.sap.sse.util.AbstractMXBeanImpl; import com.sap.sse.util.ThreadPoolMXBean; -public class ThreadPoolMXBeanImpl extends AbstractMXBeanImpl implements ThreadPoolMXBean { +public class ThreadPoolMXBeanImpl implements ThreadPoolMXBean { private static final long serialVersionUID = -7057754487764427044L; private final NamedTracingScheduledThreadPoolExecutor threadPool; @@ -22,7 +21,7 @@ public class ThreadPoolMXBeanImpl extends AbstractMXBeanImpl implements ThreadPo @Override public ObjectName getObjectName() throws MalformedObjectNameException { - return new ObjectName("com.sap.sse:type=ThreadPool,name="+escapeIllegalObjectNameCharacters(getName())); + return new ObjectName("com.sap.sse:type=ThreadPool,name="+ObjectName.quote(getName())); } @Override diff --git a/java/org.moxieapps.gwt.highcharts/META-INF/MANIFEST.MF b/java/org.moxieapps.gwt.highcharts/META-INF/MANIFEST.MF index ff39419a254..2b2dcca8215 100644 --- a/java/org.moxieapps.gwt.highcharts/META-INF/MANIFEST.MF +++ b/java/org.moxieapps.gwt.highcharts/META-INF/MANIFEST.MF @@ -19,7 +19,7 @@ Export-Package: org.moxieapps.gwt.highcharts.client.plotOptions;uses:="o ieapps.gwt.highcharts.client,com.google.gwt.json.client";version="1.5.0 " Bundle-ActivationPolicy: lazy -Require-Bundle: com.google.gwt.user;bundle-version="2.8.2";resolution:=optional, - com.google.gwt.dev;bundle-version="2.8.2";resolution:=optional, - com.google.gwt.servlet;bundle-version="2.8.2" +Require-Bundle: com.google.gwt.user;bundle-version="2.9.0";resolution:=optional, + com.google.gwt.dev;bundle-version="2.9.0";resolution:=optional, + com.google.gwt.servlet;bundle-version="2.9.0" Automatic-Module-Name: org.moxieapps.gwt.highcharts diff --git a/java/pom.xml b/java/pom.xml index 134e4ef4887..dda0c71ac73 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -32,10 +32,10 @@ (see Bugzilla: https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=3859). --> 1.6.0 - 2.8.2 + 2.9.0 - 2.8.2 - 2.8.0 + 2.9.0 + 2.9.0 2 race-analysis-p2-remote