java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/ui/EditCAM.java
... ...
@@ -99,6 +99,7 @@ public class EditCAM extends javax.swing.JDialog {
99 99
}
100 100
});
101 101
jMarkList.setModel(new javax.swing.AbstractListModel<ClockAtMarkElement>() {
102
+ private static final long serialVersionUID = 1L;
102 103
ClockAtMarkElement[] clockAtMarkElements = { new ClockAtMarkElement(1, new Date(), "Item 1"),
103 104
new ClockAtMarkElement(1, new Date(), "Item 2"), new ClockAtMarkElement(1, new Date(), "Item 3"),
104 105
new ClockAtMarkElement(1, new Date(), "Item 4"), new ClockAtMarkElement(1, new Date(), "Item 5") };
java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/ui/EditCCG.java
... ...
@@ -128,6 +128,7 @@ public class EditCCG extends javax.swing.JDialog {
128 128
});
129 129
130 130
jMarkList.setModel(new javax.swing.AbstractListModel<CCGMessage>() {
131
+ private static final long serialVersionUID = 1L;
131 132
CCGMessage[] ccgMessages = { new CCGMessage("Item 1", new ArrayList<Mark>()),
132 133
new CCGMessage("Item 2", new ArrayList<Mark>()),
133 134
new CCGMessage("Item 3", new ArrayList<Mark>()),
java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/ui/EditSTL.java
... ...
@@ -93,6 +93,7 @@ public class EditSTL extends javax.swing.JDialog {
93 93
}
94 94
});
95 95
jCompetitorList.setModel(new javax.swing.AbstractListModel<Competitor>() {
96
+ private static final long serialVersionUID = 1L;
96 97
Competitor[] competitors = { new CompetitorWithoutID("Item 1", "DEU", "Item 1"),
97 98
new CompetitorWithoutID("Item 2", "DEU", "Item 2"),
98 99
new CompetitorWithoutID("Item 3", "DEU", "Item 3"),
java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/ui/EditTMD.java
... ...
@@ -101,6 +101,7 @@ public class EditTMD extends javax.swing.JDialog {
101 101
}
102 102
});
103 103
jTmdData.setModel(new javax.swing.AbstractListModel<TimingDataElement>() {
104
+ private static final long serialVersionUID = 1L;
104 105
TimingDataElement[] strings = { new TimingDataElement(1, 1, new Date()),
105 106
new TimingDataElement(2, 2, new Date()),
106 107
new TimingDataElement(3, 3, new Date()),
java/com.sap.sailing.domain.swisstimingadapter.test/src/com/sap/sailing/domain/swisstimingadapter/test/ui/SwissTimingRaceEditor.java
... ...
@@ -87,6 +87,7 @@ public class SwissTimingRaceEditor extends javax.swing.JFrame {
87 87
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
88 88
setTitle("SwissTiming-Sample-Race Editor");
89 89
jCommandList.setModel(new javax.swing.AbstractListModel<Object>() {
90
+ private static final long serialVersionUID = 1L;
90 91
String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
91 92
public int getSize() { return strings.length; }
92 93
public Object getElementAt(int i) { return strings[i]; }
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/AbstractTracTracLiveTest.java
... ...
@@ -167,7 +167,7 @@ public abstract class AbstractTracTracLiveTest extends StoredTrackBasedTest {
167 167
}
168 168
169 169
public static String getTracTracApiToken() {
170
- return "tracTest";
170
+ return "e1c8618d5da19eb97a08aafe93ccf11374d83c92"; // token for test user sap-test; permitted to publish; see https://bugzilla.sapsailing.com/bugzilla/show_bug.cgi?id=6170#c8
171 171
}
172 172
173 173
protected void addReceiverToStopDuringTearDown(Receiver receiver) {
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/ParseTracTracJSONServiceOutputTest.java
... ...
@@ -74,7 +74,7 @@ public class ParseTracTracJSONServiceOutputTest {
74 74
@Test
75 75
public void testWeymouthOnline() throws MalformedURLException, IOException, java.text.ParseException, ParseException, URISyntaxException {
76 76
JSONService jsonService = DomainFactory.INSTANCE.parseJSONURLWithRaceRecords(new URL(
77
- "http://" + TracTracConnectionConstants.HOST_NAME + "/events/event_20110505_SailingTea/jsonservice.php?trickOurProxy=true"), true);
77
+ "http://" + TracTracConnectionConstants.HOST_NAME + "/events/event_20110505_SailingTea/jsonservice.php?trickOurProxy=true"), true, AbstractTracTracLiveTest.getTracTracApiToken());
78 78
assertEquals("Academy Tracking 2011", jsonService.getEventName());
79 79
List<RaceRecord> races = jsonService.getRaceRecords();
80 80
assertTrue(races.size()>=28);
... ...
@@ -91,7 +91,7 @@ public class ParseTracTracJSONServiceOutputTest {
91 91
@Test
92 92
public void testWeymouthURIsOnline() throws MalformedURLException, IOException, java.text.ParseException, ParseException, URISyntaxException {
93 93
JSONService jsonService = DomainFactory.INSTANCE.parseJSONURLWithRaceRecords(new URL(
94
- "http://" + TracTracConnectionConstants.HOST_NAME + "/events/event_20110505_SailingTea/jsonservice.php"), true);
94
+ "http://" + TracTracConnectionConstants.HOST_NAME + "/events/event_20110505_SailingTea/jsonservice.php"), true, AbstractTracTracLiveTest.getTracTracApiToken());
95 95
List<RaceRecord> races = jsonService.getRaceRecords();
96 96
assertFalse(races.isEmpty());
97 97
for (RaceRecord race : races) {
... ...
@@ -115,7 +115,7 @@ public class ParseTracTracJSONServiceOutputTest {
115 115
@Test
116 116
public void testHamiltonOnline() throws MalformedURLException, IOException, java.text.ParseException, ParseException, URISyntaxException {
117 117
JSONService jsonService = DomainFactory.INSTANCE.parseJSONURLWithRaceRecords(new URL(
118
- "http://" + TracTracConnectionConstants.HOST_NAME + "/events/event_20110308_SAPWorldCh/jsonservice.php?humba=trala"), true);
118
+ "http://" + TracTracConnectionConstants.HOST_NAME + "/events/event_20110308_SAPWorldCh/jsonservice.php?humba=trala"), true, AbstractTracTracLiveTest.getTracTracApiToken());
119 119
assertEquals("SAP 2011 505 World Championship", jsonService.getEventName());
120 120
List<RaceRecord> races = jsonService.getRaceRecords();
121 121
assertEquals(14, races.size());
java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/test/TrackTest.java
... ...
@@ -163,7 +163,10 @@ public class TrackTest {
163 163
List<Timed> timeds = new ArrayList<>();
164 164
for (TimePoint t = start; !t.after(end); t = t.plus((gpsFix5.getTimePoint().asMillis()-gpsFix1.getTimePoint().asMillis())/10)) {
165 165
final TimePoint finalT = t;
166
- timeds.add(new Timed() {public TimePoint getTimePoint() { return finalT; }});
166
+ timeds.add(new Timed() {
167
+ private static final long serialVersionUID = 7038806820707652754L;
168
+ public TimePoint getTimePoint() { return finalT; }
169
+ });
167 170
}
168 171
assertEqualEstimatedPositionsSingleVsIterated(timeds, /* extrapolate */ true);
169 172
assertEqualEstimatedPositionsSingleVsIterated(timeds, /* extrapolate */ false);
... ...
@@ -176,7 +179,10 @@ public class TrackTest {
176 179
List<Timed> timeds = new ArrayList<>();
177 180
for (TimePoint t = start; !t.after(end); t = t.plus(gpsFix5.getTimePoint().asMillis()-gpsFix1.getTimePoint().asMillis())) {
178 181
final TimePoint finalT = t;
179
- timeds.add(new Timed() {public TimePoint getTimePoint() { return finalT; }});
182
+ timeds.add(new Timed() {
183
+ private static final long serialVersionUID = -6329517520161330872L;
184
+ public TimePoint getTimePoint() { return finalT; }
185
+ });
180 186
}
181 187
assertEqualEstimatedPositionsSingleVsIterated(timeds, /* extrapolate */ true);
182 188
assertEqualEstimatedPositionsSingleVsIterated(timeds, /* extrapolate */ false);
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/DomainFactory.java
... ...
@@ -244,7 +244,7 @@ public interface DomainFactory {
244 244
URI courseDesignUpdateURI, String tracTracApiToken, IEventSubscriber eventSubscriber, IRaceSubscriber raceSubscriber, boolean ignoreTracTracMarkPassings,
245 245
long timeoutInMilliseconds, RaceTrackingHandler raceTrackingHandler, RaceAndCompetitorStatusWithRaceLogReconciler raceAndCompetitorStatusWithRaceLogReconciler, ReceiverType... types);
246 246
247
- JSONService parseJSONURLWithRaceRecords(URL jsonURL, boolean loadClientParams) throws IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException;
247
+ JSONService parseJSONURLWithRaceRecords(URL jsonURL, boolean loadClientParams, String tracTracApiToken) throws IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException;
248 248
249 249
/**
250 250
* Returns a {@link RaceDefinition} for the race if it already exists, <code>null</code> otherwise.
... ...
@@ -306,7 +306,7 @@ public interface DomainFactory {
306 306
*/
307 307
Serializable getRaceID(IRace tractracRace);
308 308
309
- JSONService parseJSONURLForOneRaceRecord(URL jsonURL, String raceId, boolean loadClientParams)
309
+ JSONService parseJSONURLForOneRaceRecord(URL jsonURL, String raceId, boolean loadClientParams, String tracTracApiToken)
310 310
throws IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException;
311 311
312 312
MetadataParser getMetadataParser();
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/RaceRecord.java
... ...
@@ -18,7 +18,9 @@ import java.util.regex.Matcher;
18 18
import java.util.regex.Pattern;
19 19
20 20
import com.sap.sse.InvalidDateException;
21
+import com.sap.sse.common.Duration;
21 22
import com.sap.sse.common.TimePoint;
23
+import com.sap.sse.common.Util;
22 24
import com.sap.sse.common.impl.MillisecondsTimePoint;
23 25
import com.sap.sse.util.DateParser;
24 26
import com.sap.sse.util.HttpUrlConnectionHelper;
... ...
@@ -49,7 +51,7 @@ public class RaceRecord {
49 51
public RaceRecord(URL jsonURL, String regattaName, String name, String replayURL, String paramURLAsString,
50 52
String ID, String trackingstarttime, String trackingendtime, String racestarttime,
51 53
String commaSeparatedBoatClassNames, String status, String visibility, boolean hasReplay, boolean loadLiveAndStoredURI,
52
- String defaultUpdateURI)
54
+ String defaultUpdateURI, String tracTracApiToken)
53 55
throws URISyntaxException, IOException {
54 56
super();
55 57
this.regattaName = regattaName;
... ...
@@ -109,7 +111,7 @@ public class RaceRecord {
109 111
throw e;
110 112
}
111 113
if (loadLiveAndStoredURI) {
112
- Map<String, String> paramURLContents = parseParams(paramURL);
114
+ Map<String, String> paramURLContents = parseParams(paramURL, tracTracApiToken);
113 115
String liveURIAsString = paramURLContents.get(LIVE_URI_PROPERTY);
114 116
liveURI = liveURIAsString == null ? null : new URI(liveURIAsString);
115 117
String storedURIAsString = paramURLContents.get(STORED_URI_PROPERTY);
... ...
@@ -142,10 +144,17 @@ public class RaceRecord {
142 144
return technicalEventName;
143 145
}
144 146
145
- private Map<String, String> parseParams(URL paramURL) throws IOException {
147
+ private Map<String, String> parseParams(URL paramURL, String tracTracApiToken) throws IOException {
146 148
Map<String, String> result = new HashMap<String, String>();
147 149
Pattern pattern = Pattern.compile("^([^:]*):(.*)$");
148
- final URLConnection connection = HttpUrlConnectionHelper.redirectConnection(paramURL);
150
+ final URLConnection connection = HttpUrlConnectionHelper.redirectConnection(paramURL,
151
+ /* timeout */ Duration.ONE_MINUTE,
152
+ /* pre-connection modifier adds authorization header: */
153
+ c -> {
154
+ if (Util.hasLength(tracTracApiToken)) {
155
+ c.setRequestProperty("Authorization", "Bearer "+tracTracApiToken);
156
+ }
157
+ });
149 158
final Charset charset = HttpUrlConnectionHelper.getCharsetFromConnectionOrDefault(connection, "UTF-8");
150 159
BufferedReader r = new BufferedReader(new InputStreamReader(connection.getInputStream(), charset));
151 160
String line;
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/TracTracAdapter.java
... ...
@@ -93,18 +93,18 @@ public interface TracTracAdapter {
93 93
* {@link #addTracTracRace(URL, URI, URI, WindStore, long)} calls to individually start tracking races of this
94 94
* event, rather than tracking <em>all</em> races in the event which is hardly ever useful. The returned pair's
95 95
* first component is the event name.
96
- *
97 96
* @param loadClientParams
98 97
* shall the properties from the clientparams.php file such as liveURI and storedURI already be loaded?
99 98
* Generally, this is not necessary as the
100 99
* {@link #addTracTracRace(TrackerManager, RegattaIdentifier, URL, URI, URI, URI, TimePoint, TimePoint, RaceLogStore, WindStore, long, boolean, String, String)}
101 100
* and {@link #addTracTracRace(TrackerManager, URL, URI, URI, URI, RaceLogStore, WindStore, long, String, String)} will
102 101
* fetch the JSON and clientparams.php documents to work with up-to-date data.
102
+ * @param tracTracApiToken TODO
103 103
*/
104
- Util.Pair<String, List<RaceRecord>> getTracTracRaceRecords(URL jsonURL, boolean loadClientParams) throws IOException,
104
+ Util.Pair<String, List<RaceRecord>> getTracTracRaceRecords(URL jsonURL, boolean loadClientParams, String tracTracApiToken) throws IOException,
105 105
ParseException, org.json.simple.parser.ParseException, URISyntaxException;
106 106
107
- RaceRecord getSingleTracTracRaceRecord(URL jsonURL, String raceId, boolean loadClientParams) throws Exception;
107
+ RaceRecord getSingleTracTracRaceRecord(URL jsonURL, String raceId, boolean loadClientParams, String tracTracApiToken) throws Exception;
108 108
109 109
TracTracConfiguration createTracTracConfiguration(String creatorName, String name, String jsonURL,
110 110
String liveDataURI, String storedDataURI, String courseDesignUpdateURI, String tracTracApiToken);
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/DomainFactoryImpl.java
... ...
@@ -1048,8 +1048,9 @@ public class DomainFactoryImpl implements DomainFactory {
1048 1048
}
1049 1049
1050 1050
@Override
1051
- public JSONService parseJSONURLWithRaceRecords(URL jsonURL, boolean loadClientParams) throws IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException {
1052
- return new JSONServiceImpl(jsonURL, loadClientParams);
1051
+ public JSONService parseJSONURLWithRaceRecords(URL jsonURL, boolean loadClientParams, String tracTracApiToken)
1052
+ throws IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException {
1053
+ return new JSONServiceImpl(jsonURL, loadClientParams, tracTracApiToken);
1053 1054
}
1054 1055
1055 1056
@Override
... ...
@@ -1073,9 +1074,9 @@ public class DomainFactoryImpl implements DomainFactory {
1073 1074
}
1074 1075
1075 1076
@Override
1076
- public JSONService parseJSONURLForOneRaceRecord(URL jsonURL, String raceId, boolean loadClientParams)
1077
+ public JSONService parseJSONURLForOneRaceRecord(URL jsonURL, String raceId, boolean loadClientParams, String tracTracApiToken)
1077 1078
throws IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException {
1078
- return new JSONServiceImpl(jsonURL, raceId, loadClientParams);
1079
+ return new JSONServiceImpl(jsonURL, raceId, loadClientParams, tracTracApiToken);
1079 1080
}
1080 1081
1081 1082
@Override
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/JSONServiceImpl.java
... ...
@@ -18,17 +18,18 @@ import org.json.simple.parser.JSONParser;
18 18
19 19
import com.sap.sailing.domain.tractracadapter.JSONService;
20 20
import com.sap.sailing.domain.tractracadapter.RaceRecord;
21
+import com.sap.sse.common.Util;
21 22
import com.sap.sse.util.HttpUrlConnectionHelper;
22 23
23 24
public class JSONServiceImpl implements JSONService {
24 25
private final String regattaName;
25 26
private final List<RaceRecord> raceRecords;
26 27
27
- public JSONServiceImpl(URL jsonURL, boolean loadLiveAndStoredURI) throws IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException {
28
- this(jsonURL, /* race ID == null means load all race records */ null, loadLiveAndStoredURI);
28
+ public JSONServiceImpl(URL jsonURL, boolean loadLiveAndStoredURI, String tracTracApiToken) throws IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException {
29
+ this(jsonURL, /* race ID == null means load all race records */ null, loadLiveAndStoredURI, tracTracApiToken);
29 30
}
30 31
31
- private RaceRecord createRaceRecord(URL jsonURL, boolean loadLiveAndStoredURI, JSONObject jsonRaceEntry, String defaultUpdateURI)
32
+ private RaceRecord createRaceRecord(URL jsonURL, boolean loadLiveAndStoredURI, JSONObject jsonRaceEntry, String defaultUpdateURI, String tracTracApiToken)
32 33
throws URISyntaxException, IOException {
33 34
RaceRecord raceRecord = new RaceRecord(jsonURL, regattaName,
34 35
(String) jsonRaceEntry.get("name"), (String) jsonRaceEntry.get("url_html"),
... ...
@@ -41,7 +42,7 @@ public class JSONServiceImpl implements JSONService {
41 42
(String) jsonRaceEntry.get("status"),
42 43
(String) jsonRaceEntry.get("visibility"),
43 44
Boolean.valueOf((Boolean) jsonRaceEntry.get("has_replay")),
44
- /*loadLiveAndStoreURI*/ loadLiveAndStoredURI, defaultUpdateURI);
45
+ /*loadLiveAndStoreURI*/ loadLiveAndStoredURI, defaultUpdateURI, tracTracApiToken);
45 46
return raceRecord;
46 47
}
47 48
... ...
@@ -50,8 +51,11 @@ public class JSONServiceImpl implements JSONService {
50 51
* if {@code null}, add all races found to the {@link #raceRecords}; otherwise, add only the race whose
51 52
* ID matches
52 53
*/
53
- public JSONServiceImpl(URL jsonURL, String raceEntryId, boolean loadLiveAndStoredURI) throws IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException {
54
+ public JSONServiceImpl(URL jsonURL, String raceEntryId, boolean loadLiveAndStoredURI, String tracTracApiToken) throws IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException {
54 55
final URLConnection connection = jsonURL.openConnection();
56
+ if (Util.hasLength(tracTracApiToken)) {
57
+ connection.setRequestProperty("Authorization", "Bearer "+tracTracApiToken);
58
+ }
55 59
final Charset charset = HttpUrlConnectionHelper.getCharsetFromConnectionOrDefault(connection, "UTF-8");
56 60
JSONObject jsonObject = parseJSONObject(connection.getInputStream(), charset);
57 61
raceRecords = new ArrayList<RaceRecord>();
... ...
@@ -60,7 +64,7 @@ public class JSONServiceImpl implements JSONService {
60 64
for (Object raceEntry : (JSONArray) jsonObject.get("races")) {
61 65
JSONObject jsonRaceEntry = (JSONObject) raceEntry;
62 66
if (raceEntryId == null || jsonRaceEntry.get("id").equals(raceEntryId)) {
63
- RaceRecord raceRecord = createRaceRecord(jsonURL, loadLiveAndStoredURI, jsonRaceEntry, defaultUpdateURI);
67
+ RaceRecord raceRecord = createRaceRecord(jsonURL, loadLiveAndStoredURI, jsonRaceEntry, defaultUpdateURI, tracTracApiToken);
64 68
raceRecords.add(raceRecord);
65 69
}
66 70
}
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/RaceTrackingConnectivityParametersImpl.java
... ...
@@ -80,6 +80,7 @@ public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTracking
80 80
this.useOfficialEventsToUpdateRaceLog = useOfficialEventsToUpdateRaceLog;
81 81
this.paramURL = paramURL;
82 82
this.timeoutInMillis = timeoutInMillis;
83
+ this.tracTracApiToken = tracTracApiToken; // required before trying getTractracRace()
83 84
final IRace tractracRace = getTractracRace();
84 85
if (preferReplayIfAvailable && isReplayRace(tractracRace) &&
85 86
(!Util.equalsWithNull(liveURI, tractracRace.getLiveURI()) || !Util.equalsWithNull(storedURI, tractracRace.getStoredURI()))) {
... ...
@@ -100,7 +101,6 @@ public class RaceTrackingConnectivityParametersImpl extends AbstractRaceTracking
100 101
this.offsetToStartTimeOfSimulatedRace = offsetToStartTimeOfSimulatedRace;
101 102
this.raceLogStore = raceLogStore;
102 103
this.regattaLogStore = regattaLogStore;
103
- this.tracTracApiToken = tracTracApiToken;
104 104
this.raceStatus = raceStatus;
105 105
this.raceVisibility = raceVisibility;
106 106
this.useInternalMarkPassingAlgorithm = useInternalMarkPassingAlgorithm;
java/com.sap.sailing.domain.tractracadapter/src/com/sap/sailing/domain/tractracadapter/impl/TracTracAdapterImpl.java
... ...
@@ -81,18 +81,18 @@ public class TracTracAdapterImpl implements TracTracAdapter {
81 81
}
82 82
83 83
@Override
84
- public Util.Pair<String, List<RaceRecord>> getTracTracRaceRecords(URL jsonURL, boolean loadClientParams)
84
+ public Util.Pair<String, List<RaceRecord>> getTracTracRaceRecords(URL jsonURL, boolean loadClientParams, String tracTracApiToken)
85 85
throws IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException {
86 86
logger.info("Retrieving TracTrac race records from " + jsonURL);
87
- JSONService jsonService = getTracTracDomainFactory().parseJSONURLWithRaceRecords(jsonURL, loadClientParams);
87
+ JSONService jsonService = getTracTracDomainFactory().parseJSONURLWithRaceRecords(jsonURL, loadClientParams, tracTracApiToken);
88 88
logger.info("OK retrieving TracTrac race records from " + jsonURL);
89 89
return new Util.Pair<String, List<RaceRecord>>(jsonService.getEventName(), jsonService.getRaceRecords());
90 90
}
91 91
92 92
@Override
93
- public RaceRecord getSingleTracTracRaceRecord(URL jsonURL, String raceId, boolean loadClientParams)
93
+ public RaceRecord getSingleTracTracRaceRecord(URL jsonURL, String raceId, boolean loadClientParams, String tracTracApiToken)
94 94
throws Exception {
95
- JSONService service = getTracTracDomainFactory().parseJSONURLForOneRaceRecord(jsonURL, raceId, loadClientParams);
95
+ JSONService service = getTracTracDomainFactory().parseJSONURLForOneRaceRecord(jsonURL, raceId, loadClientParams, tracTracApiToken);
96 96
if (!service.getRaceRecords().isEmpty()) {
97 97
return service.getRaceRecords().get(0);
98 98
}
java/com.sap.sailing.domain/src/com/sap/sailing/domain/markpassingcalculation/MarkPassingCalculator.java
... ...
@@ -589,7 +589,7 @@ public class MarkPassingCalculator {
589 589
// creation matches that of this mark passing calculator's race; load instead of compute
590 590
updateMarkPassingsFromRegistry();
591 591
queue.clear();
592
- stop(); // ensures an end marker is written to queue to the queue.take() call in Listen.run() will always get unblocked after the queue.clear() above
592
+ stop(); // ensures an end marker is written to queue so the queue.take() call in Listen.run() will always get unblocked after the queue.clear() above
593 593
suspended = false;
594 594
} else {
595 595
suspended = false;
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/TracTracEventManagementPanel.java
... ...
@@ -449,6 +449,7 @@ public class TracTracEventManagementPanel extends AbstractEventManagementPanel i
449 449
if (selectedConnections.size() == 1) {
450 450
TracTracConfigurationWithSecurityDTO selectedConnection = selectedConnections.iterator().next();
451 451
sailingService.listTracTracRacesInEvent(selectedConnection.getJsonUrl(), listHiddenRaces,
452
+ selectedConnection.getTracTracApiToken(),
452 453
new MarkedAsyncCallback<com.sap.sse.common.Util.Pair<String, List<TracTracRaceRecordDTO>>>(
453 454
new AsyncCallback<com.sap.sse.common.Util.Pair<String, List<TracTracRaceRecordDTO>>>() {
454 455
@Override
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingService.java
... ...
@@ -129,7 +129,7 @@ public interface SailingService extends RemoteService, RemoteReplicationService
129 129
List<EventDTO> getEvents() throws Exception;
130 130
131 131
Util.Pair<String, List<TracTracRaceRecordDTO>> listTracTracRacesInEvent(String eventJsonURL,
132
- boolean listHiddenRaces) throws UnauthorizedException, Exception;
132
+ boolean listHiddenRaces, String tracTracApiToken) throws UnauthorizedException, Exception;
133 133
134 134
void replaySwissTimingRace(RegattaIdentifier regattaIdentifier, Iterable<SwissTimingReplayRaceDTO> replayRaces,
135 135
boolean trackWind, boolean correctWindByDeclination, boolean useInternalMarkPassingAlgorithm)
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceAsync.java
... ...
@@ -123,11 +123,10 @@ public interface SailingServiceAsync extends RemoteReplicationServiceAsync {
123 123
124 124
/**
125 125
* The string returned in the callback's pair is the common event name
126
- *
127 126
* @param listHiddenRaces
128 127
*/
129 128
void listTracTracRacesInEvent(String eventJsonURL, boolean listHiddenRaces,
130
- AsyncCallback<Util.Pair<String, List<TracTracRaceRecordDTO>>> callback);
129
+ String tracTracApiToken, AsyncCallback<Util.Pair<String, List<TracTracRaceRecordDTO>>> callback);
131 130
132 131
void replaySwissTimingRace(RegattaIdentifier regattaIdentifier, Iterable<SwissTimingReplayRaceDTO> replayRaces,
133 132
boolean trackWind, boolean correctWindByDeclination, boolean useInternalMarkPassingAlgorithm,
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/SailingServiceWrite.java
... ...
@@ -115,7 +115,6 @@ import com.sap.sse.security.interfaces.UserStore;
115 115
import com.sap.sse.security.ui.shared.SuccessInfo;
116 116
117 117
public interface SailingServiceWrite extends FileStorageManagementGwtService, SailingService {
118
-
119 118
void setORCPerformanceCurveScratchBoat(String leaderboardName, String raceColumnName, String fleetName,
120 119
CompetitorDTO newScratchBoatDTO) throws NotFoundException;
121 120
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceImpl.java
... ...
@@ -1287,9 +1287,9 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
1287 1287
}
1288 1288
1289 1289
@Override
1290
- public com.sap.sse.common.Util.Pair<String, List<TracTracRaceRecordDTO>> listTracTracRacesInEvent(String eventJsonURL, boolean listHiddenRaces) throws MalformedURLException, IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException {
1290
+ public com.sap.sse.common.Util.Pair<String, List<TracTracRaceRecordDTO>> listTracTracRacesInEvent(String eventJsonURL, boolean listHiddenRaces, String tracTracApiToken) throws MalformedURLException, IOException, ParseException, org.json.simple.parser.ParseException, URISyntaxException {
1291 1291
com.sap.sse.common.Util.Pair<String,List<RaceRecord>> raceRecords;
1292
- raceRecords = getTracTracAdapter().getTracTracRaceRecords(new URL(eventJsonURL), /*loadClientParam*/ false);
1292
+ raceRecords = getTracTracAdapter().getTracTracRaceRecords(new URL(eventJsonURL), /*loadClientParam*/ false, tracTracApiToken);
1293 1293
List<TracTracRaceRecordDTO> result = new ArrayList<TracTracRaceRecordDTO>();
1294 1294
for (RaceRecord raceRecord : raceRecords.getB()) {
1295 1295
if (listHiddenRaces == false && raceRecord.getRaceVisibility().equals(TracTracConnectionConstants.HIDDEN_VISIBILITY)) {
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/SailingServiceWriteImpl.java
... ...
@@ -571,10 +571,11 @@ public class SailingServiceWriteImpl extends SailingServiceImpl implements Saili
571 571
+ " and storedURI " + storedURIFromConfiguration);
572 572
getSecurityService().checkCurrentUserServerPermission(ServerActions.CREATE_OBJECT);
573 573
final TracTracConfiguration config = tractracDomainObjectFactory.getTracTracConfiguration(jsonUrlAsKey);
574
+ final String tracTracApiToken = config == null ? null : config.getTracTracApiToken();
574 575
for (TracTracRaceRecordDTO rr : rrs) {
575 576
try {
576 577
// reload JSON and load clientparams.php
577
- final RaceRecord record = getTracTracAdapter().getSingleTracTracRaceRecord(new URL(rr.jsonURL), rr.id, /*loadClientParams*/true);
578
+ final RaceRecord record = getTracTracAdapter().getSingleTracTracRaceRecord(new URL(rr.jsonURL), rr.id, /*loadClientParams*/true, tracTracApiToken);
578 579
logger.info("Loaded race " + record.getName() + " in " + record.getEventName() + " start:" + record.getRaceStartTime() +
579 580
" trackingStart:" + record.getTrackingStartTime() + " trackingEnd:" + record.getTrackingEndTime());
580 581
// note that the live URI may be null for races that were put into replay mode
... ...
@@ -605,7 +606,7 @@ public class SailingServiceWriteImpl extends SailingServiceImpl implements Saili
605 606
new MillisecondsTimePoint(record.getTrackingStartTime().asMillis()),
606 607
new MillisecondsTimePoint(record.getTrackingEndTime().asMillis()), getRaceLogStore(),
607 608
getRegattaLogStore(), RaceTracker.TIMEOUT_FOR_RECEIVING_RACE_DEFINITION_IN_MILLISECONDS,
608
- offsetToStartTimeOfSimulatedRace, useInternalMarkPassingAlgorithm, config == null ? null : config.getTracTracApiToken(),
609
+ offsetToStartTimeOfSimulatedRace, useInternalMarkPassingAlgorithm, tracTracApiToken,
609 610
record.getRaceStatus(), record.getRaceVisibility(), trackWind,
610 611
correctWindByDeclination, useOfficialEventsToUpdateRaceLog,
611 612
liveURIFromConfiguration==null || liveURIFromConfiguration.trim().length() == 0 ? null : new URI(liveURIFromConfiguration),
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/WindowManager.java
... ...
@@ -5,6 +5,7 @@ import java.util.Set;
5 5
import java.util.function.BiConsumer;
6 6
import java.util.function.Consumer;
7 7
import java.util.function.Supplier;
8
+import java.util.logging.Logger;
8 9
9 10
import org.openqa.selenium.Dimension;
10 11
import org.openqa.selenium.JavascriptExecutor;
... ...
@@ -21,6 +22,8 @@ import org.openqa.selenium.support.ui.WebDriverWait;
21 22
* Riccardo Nimser (D049941)
22 23
*/
23 24
public class WindowManager {
25
+ private static final Logger logger = Logger.getLogger(WindowManager.class.getName());
26
+
24 27
private WebDriverWindow defaultWindow;
25 28
private final Set<WebDriverWindow> allWindows = new HashSet<>();
26 29
private WebDriver driver;
... ...
@@ -108,12 +111,18 @@ public class WindowManager {
108 111
}
109 112
110 113
private boolean isDriverAlive(WebDriver driver) {
111
- try {
112
- driver.getWindowHandles();
113
- return true;
114
- } catch (NoSuchSessionException | SessionNotCreatedException e) {
115
- return false;
114
+ boolean result;
115
+ if (driver == null) {
116
+ result = false;
117
+ } else {
118
+ try {
119
+ driver.getWindowHandles();
120
+ result = true;
121
+ } catch (NoSuchSessionException | SessionNotCreatedException e) {
122
+ result = false;
123
+ }
116 124
}
125
+ return result;
117 126
}
118 127
119 128
private void setWindowMaximized(WebDriver driver) {
... ...
@@ -137,6 +146,16 @@ public class WindowManager {
137 146
138 147
public void closeAllWindows() {
139 148
forEachOpenedWindow(WebDriverWindow::close);
149
+ if (driver != null) {
150
+ try {
151
+ driver.close();
152
+ driver.quit();
153
+ } catch (org.openqa.selenium.NoSuchSessionException e) {
154
+ logger.warning("The Selenium driver seems to have already been closed");
155
+ // Already closed — ignore
156
+ }
157
+ driver = null;
158
+ }
140 159
}
141 160
142 161
private class ManagedWebDriverWindow extends WebDriverWindow {
java/com.sap.sailing.server.trackfiles.test/src/com/sap/sailing/server/trackfiles/test/DynamicTrackedRaceWithMarkPassingCalculator.java
... ...
@@ -0,0 +1,28 @@
1
+package com.sap.sailing.server.trackfiles.test;
2
+
3
+import com.sap.sailing.domain.base.RaceDefinition;
4
+import com.sap.sailing.domain.base.Sideline;
5
+import com.sap.sailing.domain.markpassingcalculation.MarkPassingCalculator;
6
+import com.sap.sailing.domain.markpassinghash.MarkPassingRaceFingerprintRegistry;
7
+import com.sap.sailing.domain.racelog.RaceLogAndTrackedRaceResolver;
8
+import com.sap.sailing.domain.ranking.RankingMetricConstructor;
9
+import com.sap.sailing.domain.shared.tracking.TrackingConnectorInfo;
10
+import com.sap.sailing.domain.tracking.TrackedRegatta;
11
+import com.sap.sailing.domain.tracking.WindStore;
12
+import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
13
+
14
+public class DynamicTrackedRaceWithMarkPassingCalculator extends DynamicTrackedRaceImpl {
15
+ private static final long serialVersionUID = -8076705893930566222L;
16
+
17
+ public DynamicTrackedRaceWithMarkPassingCalculator(TrackedRegatta trackedRegatta, RaceDefinition race, Iterable<Sideline> sidelines,
18
+ WindStore windStore, long delayToLiveInMillis, long millisecondsOverWhichToAverageWind,
19
+ long millisecondsOverWhichToAverageSpeed, boolean useInternalMarkPassingAlgorithm,
20
+ RankingMetricConstructor rankingMetricConstructor, RaceLogAndTrackedRaceResolver raceLogResolver, TrackingConnectorInfo trackingConnectorInfo,
21
+ MarkPassingRaceFingerprintRegistry markPassingRaceFingerprintRegistry) {
22
+ super(trackedRegatta, race, sidelines, windStore, delayToLiveInMillis, millisecondsOverWhichToAverageWind, millisecondsOverWhichToAverageSpeed, useInternalMarkPassingAlgorithm, rankingMetricConstructor, raceLogResolver, trackingConnectorInfo, markPassingRaceFingerprintRegistry);
23
+ }
24
+
25
+ public MarkPassingCalculator getMarkPassingCalculator() {
26
+ return markPassingCalculator;
27
+ }
28
+}
java/com.sap.sailing.server.trackfiles.test/src/com/sap/sailing/server/trackfiles/test/JumpyTrackSmootheningTest.java
... ...
@@ -68,7 +68,6 @@ import com.sap.sailing.domain.tracking.MarkPassing;
68 68
import com.sap.sailing.domain.tracking.TrackedRegatta;
69 69
import com.sap.sailing.domain.tracking.WindTrack;
70 70
import com.sap.sailing.domain.tracking.impl.DynamicGPSFixMovingTrackImpl;
71
-import com.sap.sailing.domain.tracking.impl.DynamicTrackedRaceImpl;
72 71
import com.sap.sailing.domain.tracking.impl.DynamicTrackedRegattaImpl;
73 72
import com.sap.sailing.domain.tracking.impl.EmptyWindStore;
74 73
import com.sap.sailing.domain.tracking.impl.OutlierFilter;
... ...
@@ -197,7 +196,7 @@ public class JumpyTrackSmootheningTest {
197 196
durationForOriginalTrack = startedAt.until(doneAt);
198 197
logger.info("Duration for computing mark passings with original track: "+durationForOriginalTrack);
199 198
assertNotNull(markPassings);
200
- assertEquals(13, markPassings.size());
199
+ assertEquals(5, markPassings.size()); // there are fewer mark passings with the spikes still included
201 200
}
202 201
assertTrue(durationForAdjustedTrack.times(2).compareTo(durationForOriginalTrack) < 0,
203 202
"Expected duration for mark passing analysis on adjusted track to be at least two times less than for original track: "+
... ...
@@ -238,9 +237,9 @@ public class JumpyTrackSmootheningTest {
238 237
* its calculation. As a result, a test may determine the impact filtering / adjusting the track may have on the
239 238
* mark passing analysis.
240 239
*/
241
- private DynamicTrackedRace createRace(DynamicGPSFixTrack<Competitor, GPSFixMoving> competitorTrack) throws PatchFailedException, ParseException {
240
+ private DynamicTrackedRace createRace(DynamicGPSFixTrack<Competitor, GPSFixMoving> competitorTrack) throws PatchFailedException, ParseException, InterruptedException {
242 241
final Competitor gallagherZelenka = competitorTrack.getTrackedItem();
243
- final DynamicTrackedRace trackedRace = createTrackedRace("Oak cliff DH Distance Race", "R1", BoatClassMasterdata.MELGES_24, gallagherZelenka);
242
+ final DynamicTrackedRaceWithMarkPassingCalculator trackedRace = createTrackedRace("Oak cliff DH Distance Race", "R1", BoatClassMasterdata.MELGES_24, gallagherZelenka);
244 243
final Series defaultSeries = trackedRace.getTrackedRegatta().getRegatta().getSeries().iterator().next();
245 244
final Fleet defaultFleet = defaultSeries.getFleets().iterator().next();
246 245
final RaceColumnInSeries r1RaceColumn = defaultSeries.getRaceColumns().iterator().next();
... ...
@@ -291,7 +290,6 @@ public class JumpyTrackSmootheningTest {
291 290
addFixedMarkPassingToRaceLog("2020-10-14T18:21:38Z", gallagherZelenka, 4, raceLog);
292 291
trackedRace.setStatus(new TrackedRaceStatusImpl(TrackedRaceStatusEnum.LOADING, 0.0)); // suspends mark passing calculator
293 292
final DynamicGPSFixTrack<Competitor, GPSFixMoving> competitorTrackInRace = trackedRace.getTrack(gallagherZelenka);
294
- // TODO switch race into suspended mode to avoid updates during mass fix insertion:
295 293
competitorTrack.lockForRead();
296 294
try {
297 295
for (final GPSFixMoving fix : competitorTrack.getRawFixes()) {
... ...
@@ -301,15 +299,11 @@ public class JumpyTrackSmootheningTest {
301 299
competitorTrack.unlockAfterRead();
302 300
}
303 301
trackedRace.setStatus(new TrackedRaceStatusImpl(TrackedRaceStatusEnum.TRACKING, 1.0)); // resumes mark passing calculator
304
- // FIXME is it possible that MarkPassingCalculator.Listen has applied only a subset of the changes from its queue when this method returns?
305
- // It scoops up a few events from the queue under the MPC write lock and collects the changes in various collections, but doesn't re-calculate while suspended;
306
- // When the lock is released prior to fetching the next set of events from the queue, the test case calling this method may call getMarkPassings(..., true)
307
- // and obtain the read lock, keeping the Listen thread from applying the next round of updates. Yes, the getMarkPassings(...) call may return something,
308
- // but that may be the result of only applying a subset of the changes, with other changes still in the queue...
302
+ trackedRace.getMarkPassingCalculator().waitUntilStopped(/* timeout in millis */ Duration.ONE_MINUTE.times(15).asMillis());
309 303
return trackedRace;
310 304
}
311 305
312
- private DynamicTrackedRace createTrackedRace(String regattaName, String name, BoatClassMasterdata boatClassMasterData, Competitor gallagherZelenka) {
306
+ private DynamicTrackedRaceWithMarkPassingCalculator createTrackedRace(String regattaName, String name, BoatClassMasterdata boatClassMasterData, Competitor gallagherZelenka) {
313 307
final BoatClassImpl boatClass = new BoatClassImpl(boatClassMasterData);
314 308
final TrackedRegatta trackedRegatta = new DynamicTrackedRegattaImpl(new RegattaImpl(regattaName, boatClass,
315 309
/* canBoatsOfCompetitorsChangePerRace */ false, /* competitorRegistrationType */ CompetitorRegistrationType.CLOSED,
... ...
@@ -321,7 +315,7 @@ public class JumpyTrackSmootheningTest {
321 315
final Map<Competitor, Boat> competitorsAndTheirBoats = Util.<Competitor, Boat>mapBuilder().put(gallagherZelenka, boat).build();
322 316
final Course course = new CourseImpl("R1 Course", Collections.emptySet());
323 317
final RaceDefinition race = new RaceDefinitionImpl(name, course, boatClass, competitorsAndTheirBoats, UUID.randomUUID());
324
- return new DynamicTrackedRaceImpl(trackedRegatta, race, /* sidelines */ Collections.emptySet(), new EmptyWindStore(), /* delayToLiveInMillis */ 1000,
318
+ return new DynamicTrackedRaceWithMarkPassingCalculator(trackedRegatta, race, /* sidelines */ Collections.emptySet(), new EmptyWindStore(), /* delayToLiveInMillis */ 1000,
325 319
WindTrack.DEFAULT_MILLISECONDS_OVER_WHICH_TO_AVERAGE_WIND, /* time over which to average speed: */ boatClass.getApproximateManeuverDurationInMilliseconds(),
326 320
/* useInternalMarkPassingAlgorithm */ true, OneDesignRankingMetric::new, mock(RaceLogAndTrackedRaceResolver.class), /* trackingConnectorInfo */ null, /* markPassingRaceFingerprintRegistry */ null);
327 321
}
java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/useragent/UserAgentCheckerImpl.java
... ...
@@ -10,6 +10,7 @@ public class UserAgentCheckerImpl implements UserAgentChecker {
10 10
* Version numbers indicate minimum required browser (20 = at least this version)
11 11
*/
12 12
private static final HashMap<AgentTypes, Integer> MINIMUM_SUPPORTED_AGENTS = new HashMap<AgentTypes, Integer>() {
13
+ private static final long serialVersionUID = -3972648919899828625L;
13 14
{
14 15
put(AgentTypes.MSIE, 9);
15 16
put(AgentTypes.SAFARI, 5);