Merge branch 'master' into bug4811-with-bug5288

This commit is contained in:
Axel Uhl committed 2021-01-09 00:04:54 +01:00
commit 5ecece468b
6 files changed
+408 -43

No files matched your search

@@ -1,11 +1,12 @@
package com.sap.sailing.domain.orc;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.StreamSupport;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
@@ -13,9 +14,8 @@ import org.junit.runners.model.Statement;
import com.sap.sailing.domain.common.orc.ORCCertificate;
import com.sap.sailing.domain.orc.ORCPublicCertificateDatabase.CertificateHandle;
import com.sap.sailing.domain.orc.ORCPublicCertificateDatabase.CountryOverview;
import com.sap.sailing.domain.orc.impl.ORCPublicCertificateDatabaseImpl;
import com.sap.sse.common.CountryCode;
import com.sap.sse.common.CountryCodeFactory;
/***
* A IgnoreInvalidOrcCerticatesRule is an implementation of TestRule. This class execution depends on
@@ -57,7 +57,7 @@ public class FailIfNoValidOrcCertificateRule implements TestRule {
this.description = description;
availableCerts = new ArrayList<>();
}
/***
* This method executes for every test case having {@link TestRule} annotation of
* {@link FailIfNoValidOrcCertificateRule} class. Assume statement at the end of this method evaluates whether
@@ -68,22 +68,21 @@ public class FailIfNoValidOrcCertificateRule implements TestRule {
boolean certificateExists = true;
FailIfNoValidOrcCertificates annotation = description.getAnnotation(FailIfNoValidOrcCertificates.class);
if (annotation != null) {
int currentYear = LocalDate.now().getYear();
final CountryOverview countryWithMostValidCertificates = StreamSupport
.stream(db.getCountriesWithValidCertificates().spliterator(), /* parallel */ false)
.max((c1, c2) -> c1.getCertCount() - c2.getCertCount()).get();
certificateExists = false;
for (int year=currentYear; year>=currentYear-1; year--) {
for (CountryCode countryCode : CountryCodeFactory.INSTANCE.getAll()) {
try {
Iterable<CertificateHandle> certificateHandles = db.search(countryCode, year, null, null, null, null, /* includeInvalid */ false);
Iterable<ORCCertificate> orcCertificates = db.getCertificates(certificateHandles);
orcCertificates.forEach(availableCerts::add);
if (orcCertificates.iterator().hasNext()) {
certificateExists = true;
break; // Note: this stops after the first valid certificates for a country have been read!
}
} catch (Exception ex) {
// Exceptions are ignored because we are searching for any country's ORC certificate availability.
}
try {
Iterable<CertificateHandle> certificateHandles = db.search(countryWithMostValidCertificates.getIssuingCountry(),
countryWithMostValidCertificates.getVPPYear(), null, null, null, null, /* includeInvalid */ false);
Iterable<ORCCertificate> orcCertificates = db.getCertificates(certificateHandles);
orcCertificates.forEach(availableCerts::add);
if (orcCertificates.iterator().hasNext()) {
certificateExists = true;
}
} catch (Exception ex) {
logger.log(Level.WARNING, "Problem trying to fetch certificates for country "+countryWithMostValidCertificates.getIssuingCountry()+
" and year "+countryWithMostValidCertificates.getVPPYear());
}
}
if (certificateExists) {
@@ -10,6 +10,9 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.StreamSupport;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.math.ArgumentOutsideDomainException;
import org.apache.commons.math.FunctionEvaluationException;
@@ -20,6 +23,8 @@ import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
import org.w3c.dom.DOMException;
import org.xml.sax.SAXException;
import com.sap.sailing.domain.common.impl.KnotSpeedImpl;
import com.sap.sailing.domain.common.impl.NauticalMileDistance;
@@ -31,7 +36,9 @@ import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveCourseImpl;
import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveLegImpl;
import com.sap.sailing.domain.orc.impl.ORCCertificatesJsonImporter;
import com.sap.sailing.domain.orc.impl.ORCPerformanceCurveImpl;
import com.sap.sailing.domain.orc.impl.ORCPublicCertificateDatabaseImpl;
import com.sap.sse.common.Bearing;
import com.sap.sse.common.CountryCode;
import com.sap.sse.common.Distance;
import com.sap.sse.common.Duration;
import com.sap.sse.common.Speed;
@@ -81,7 +88,8 @@ public class TestORCPerformanceCurve {
}
@BeforeClass
public static void initialize() throws IOException, ParseException {
public static void initialize() throws IOException, ParseException, DOMException, SAXException,
ParserConfigurationException, java.text.ParseException {
List<ORCPerformanceCurveLeg> legs = new ArrayList<>();
legs.add(new ORCPerformanceCurveLegImpl(new NauticalMileDistance(2.23), new DegreeBearingImpl(10)));
legs.add(new ORCPerformanceCurveLegImpl(new NauticalMileDistance(2.00), new DegreeBearingImpl(170)));
@@ -97,7 +105,12 @@ public class TestORCPerformanceCurve {
File fileWithSpecificBins = new File(RESOURCES + "newFormatCertificate.json");
importerWithSpecificBins = new ORCCertificatesJsonImporter().read(new FileInputStream(fileWithSpecificBins));
// Online File:
importerOnline = new ORCCertificatesJsonImporter().read(new URL("https://data.orc.org/public/WPub.dll?action=DownBoatRMS&CountryId=GER&ext=json").openStream());
final CountryCode countryWithMostValidCertificates = StreamSupport
.stream(ORCPublicCertificateDatabaseImpl.INSTANCE.getCountriesWithValidCertificates().spliterator(),
/* parallel */ false)
.max((c1, c2) -> c1.getCertCount() - c2.getCertCount()).get().getIssuingCountry();
importerOnline = new ORCCertificatesJsonImporter().read(new URL("https://data.orc.org/public/WPub.dll?action=DownBoatRMS&CountryId="+
countryWithMostValidCertificates.getThreeLetterIOCCode()+"&ext=json").openStream());
}
@Test
@@ -160,6 +160,14 @@ public class TestORCPublicCertificateDatabase {
* boat class name; could be set to cert.getBoatClassName() but there are
* deviations in ORC DBs and query API, so leaving null:
*/ null, /* includeInvalid */ false);
if (Util.isEmpty(certHandles)) {
// there were certs; get one from the previous year
certHandles = db.search(null, LocalDate.now().getYear()-1, null, cert.getBoatName(),
cert.getSailNumber(), /*
* boat class name; could be set to cert.getBoatClassName() but there are
* deviations in ORC DBs and query API, so leaving null:
*/ null, /* includeInvalid */ false);
}
Optional<CertificateHandle> certificateHandle = Optional.ofNullable(certHandles.iterator().hasNext() ? certHandles.iterator().next() : null);
assertTrue("No certificate found for handle "+certificateHandle+
" extracted from certificates "+certificates, certificateHandle.isPresent());
@@ -188,7 +196,7 @@ public class TestORCPublicCertificateDatabase {
new BoatClassImpl(orcCertificate.getBoatClassName(), true)));
}
for (Future<Set<ORCCertificate>> futureResult : futures) {
isYearFound = isYearFound || assertFoundYear(futureResult.get(), year);
isYearFound = isYearFound || assertFoundYear(futureResult.get(), year) || assertFoundYear(futureResult.get(), year-1);
}
assertTrue(isYearFound);
}
@@ -1,5 +1,7 @@
package com.sap.sailing.domain.orc;
import java.io.IOException;
import java.text.ParseException;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.Date;
@@ -9,6 +11,11 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Future;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.DOMException;
import org.xml.sax.SAXException;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.common.orc.ORCCertificate;
import com.sap.sailing.domain.orc.impl.ORCPublicCertificateDatabaseImpl;
@@ -128,6 +135,36 @@ public interface ORCPublicCertificateDatabase {
return familyById.get(familyId);
}
}
/**
* Data about valid certificates in a country, as obtained, e.g., from http://data.orc.org/public/WPub.dll/RMS. Such a
* record, in its original XML representation, looks like this:
*
* <pre>
&lt;CountryId&gt;AUS&lt;/CountryId&gt;
&lt;Family&gt;&lt;/Family&gt;
&lt;CertType&gt;3&lt;/CertType&gt;
&lt;VPPYear&gt;2020&lt;/VPPYear&gt;
&lt;CertCount&gt;161&lt;/CertCount&gt;
&lt;CountryName&gt;Australia&lt;/CountryName&gt;
&lt;LastUpdate&gt;2021-01-08T08:12:57.000Z&lt;/LastUpdate&gt;
&lt;CertName&gt;Club&lt;/CertName&gt;
&lt;RMSCode&gt;CLUB&lt;/RMSCode&gt;
* </pre>
*
* @author Axel Uhl (D043530)
*/
public interface CountryOverview {
CountryCode getIssuingCountry();
CertificateFamily getFamily();
Integer getCertType();
Integer getVPPYear();
int getCertCount();
TimePoint getLastUpdate();
String getCertName();
String getRMSCode();
}
/**
* Equality and hash code of such handles is based on the {@link #getReferenceNumber() reference number} only.
*
@@ -229,4 +266,7 @@ public interface ORCPublicCertificateDatabase {
Future<Set<ORCCertificate>> search(String yachtName, String sailNumber, BoatClass boatClass);
Date parseDate(final String dateString) throws DateTimeParseException;
Iterable<CountryOverview> getCountriesWithValidCertificates()
throws SAXException, IOException, ParserConfigurationException, DOMException, ParseException;
}
@@ -2,7 +2,9 @@ package com.sap.sailing.domain.orc.impl;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
@@ -11,9 +13,7 @@ import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
@@ -25,12 +25,14 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.http.HttpMessage;
import org.apache.http.HttpResponse;
@@ -46,6 +48,7 @@ import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import com.sap.sailing.domain.base.BoatClass;
import com.sap.sailing.domain.common.BoatClassMasterdata;
@@ -76,6 +79,7 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
private static final NameValuePair ACTION_PARAM = new BasicNameValuePair(ACTION_PARAM_NAME, ACTION_PARAM_VALUE_LIST_CERT);
private static final NameValuePair XSLP_PARAM = new BasicNameValuePair(XSLP_PARAM_NAME, XSLP_PARAM_VALUE_LIST_CERT);
private static final String SEARCH_URL = "http://data.orc.org/public/WPub.dll";
private static final String COUNTRY_OVERVIEW_URL = SEARCH_URL+"/RMS";
private static final String SINGLE_CERTIFICATE_DOWNLOAD_URL = "http://data.orc.org/public/WPub.dll?action=DownBoatRMS";
private static final String ROOT_ELEMENT = "ROOT";
private static final String DATA_ELEMENT = "DATA";
@@ -96,6 +100,62 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX")
};
private static class CountryOverviewImpl implements CountryOverview {
private final CountryCode issuingCountry;
private final CertificateFamily family;
private final Integer certType;
private final Integer vppYear;
private final int certCount;
private final TimePoint lastUpdate;
private final String certName;
private final String rmsCode;
protected CountryOverviewImpl(CountryCode issuingCountry, CertificateFamily family, Integer certType,
Integer vppYear, int certCount, TimePoint lastUpdate, String certName, String rmsCode) {
super();
this.issuingCountry = issuingCountry;
this.family = family;
this.certType = certType;
this.vppYear = vppYear;
this.certCount = certCount;
this.lastUpdate = lastUpdate;
this.certName = certName;
this.rmsCode = rmsCode;
}
@Override
public CountryCode getIssuingCountry() {
return issuingCountry;
}
@Override
public CertificateFamily getFamily() {
return family;
}
@Override
public Integer getCertType() {
return certType;
}
@Override
public Integer getVPPYear() {
return vppYear;
}
@Override
public int getCertCount() {
return certCount;
}
@Override
public TimePoint getLastUpdate() {
return lastUpdate;
}
@Override
public String getCertName() {
return certName;
}
@Override
public String getRMSCode() {
return rmsCode;
}
}
/**
* Hash code and equality as based on {@link #getReferenceNumber() the reference number field} only.
*
@@ -325,6 +385,81 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
return result;
}
@Override
public Iterable<CountryOverview> getCountriesWithValidCertificates()
throws SAXException, IOException, ParserConfigurationException, DOMException, ParseException {
final Set<ORCPublicCertificateDatabase.CountryOverview> result = new HashSet<>();
final HttpClient client = HttpClientBuilder.create().build();
final List<NameValuePair> params = new ArrayList<>();
final HttpPost postRequest = new HttpPost(COUNTRY_OVERVIEW_URL);
addAuthorizationHeader(postRequest);
logger.fine(()->"Searching for "+params+"...");
final HttpResponse processorResponse = client.execute(postRequest);
final InputStream content = processorResponse.getEntity().getContent();
final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final Document document = builder.parse(content);
final NodeList dataNodes = document.getElementsByTagName(ROOT_ELEMENT).item(0).getChildNodes();
for (int dataNodeIndex=0; dataNodeIndex<dataNodes.getLength(); dataNodeIndex++) {
final Node dataNode = dataNodes.item(dataNodeIndex);
if (dataNode.getNodeName().equals(DATA_ELEMENT)) {
final NodeList rowNodes = dataNode.getChildNodes();
for (int rowNodeIndex=0; rowNodeIndex<rowNodes.getLength(); rowNodeIndex++) {
final Node rowNode = rowNodes.item(rowNodeIndex);
if (rowNode.getNodeName().equals(ROW_ELEMENT)) {
final CountryOverview countryOverview = parseCountryOverview(rowNode);
if (countryOverview.getVPPYear() != null) {
result.add(countryOverview);
}
}
}
}
}
logger.fine(()->"Search for "+params+" returned "+result.size()+" results");
return result;
}
private CountryOverview parseCountryOverview(Node rowNode) throws DOMException, ParseException {
final DateFormat isoDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.mmmX");
CountryCode issuingCountry = null;
CertificateFamily family = null;
Integer certType = null;
Integer vppYear = null;
int certCount = 0;
TimePoint lastUpdate = null;
String certName = null;
String rmsCode = null;
for (int i=0; i<rowNode.getChildNodes().getLength(); i++) {
final Node child = rowNode.getChildNodes().item(i);
switch (child.getNodeName()) {
case "CountryId":
issuingCountry = CountryCodeFactory.INSTANCE.getFromThreeLetterIOCName(child.getTextContent().trim());
break;
case "Family":
family = Util.hasLength(child.getTextContent().trim()) ? CertificateFamily.fromId(new Integer(child.getTextContent().trim())) : null;
break;
case "CertType":
certType = child.getTextContent().trim().isEmpty() ? null : Integer.valueOf(child.getTextContent().trim());
break;
case "VPPYear":
vppYear = child.getTextContent().trim().isEmpty() ? null : Integer.valueOf(child.getTextContent().trim());
break;
case "CertCount":
certCount = Integer.valueOf(child.getTextContent().trim()).intValue();
break;
case "LastUpdate":
lastUpdate = TimePoint.of(isoDateFormat.parse(child.getTextContent().trim()));
break;
case "CertName":
certName = child.getTextContent().trim();
break;
case "RMSCode":
rmsCode = child.getTextContent().trim();
break;
}
}
return new CountryOverviewImpl(issuingCountry, family, certType, vppYear, certCount, lastUpdate, certName, rmsCode);
}
private void addAuthorizationHeader(final HttpMessage httpMessage) {
httpMessage.addHeader("Authorization", "Basic "+new String(Base64.getEncoder().encode((USER_NAME+":"+getDecodedCredentials()).getBytes())));
}
@@ -486,7 +621,13 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
public ORCCertificate getCertificate(String referenceNumber, CertificateFamily family) throws Exception {
final String queryParameters = "ext=json&RefNo="+referenceNumber+"&family="+family.getFamilyQueryParamValue();
logger.fine("Obtaining certificate for reference number "+referenceNumber);
final ORCCertificate result = getSingleCertificate(queryParameters);
ORCCertificate result;
try {
result = getSingleCertificate(queryParameters);
} catch (Exception e) {
logger.log(Level.WARNING, "Error trying to find ORC certificate with reference number "+referenceNumber, e);
result = null;
}
if (result == null) {
logger.info("Couldn't find ORC certificate with reference number "+referenceNumber);
}
@@ -541,7 +682,7 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
final FutureTask<Set<ORCCertificate>> result = new FutureTask<Set<ORCCertificate>>(()->{
final Set<ORCCertificate> certificates = new HashSet<>();
Iterable<CertificateHandle> certificateHandles = fuzzySearchVaryingSailNumberPadding(yachtName, sailNumber, boatClass);
if (!containsHandleForCurrentYear(certificateHandles)) {
if (!containsValidHandle(certificateHandles)) {
// try swapping yacht name and sail number and go again:
logger.fine(()->"Nothing found for "+yachtName+"/"+sailNumber+"/"+boatClass+
"; trying by swapping sail number and yacht name");
@@ -569,7 +710,7 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
for (final String sailNumberVariant : getSailNumberVariants(sailNumber)) {
logger.fine(()->"Trying sail number variation "+sailNumberVariant);
final Iterable<CertificateHandle> certificateHandles = fuzzySearchVaryingBoatClassName(yachtName, sailNumberVariant, boatClass);
Util.addAll(filterHandlesForCurrentYear(certificateHandles), result);
Util.addAll(filterValidHandles(certificateHandles), result);
}
if (sailNumber != null && result.isEmpty() && (yachtName != null || boatClass != null)) {
logger.fine(()->"Nothing found; trying without restricting sail number to "+sailNumber);
@@ -579,21 +720,12 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
return result;
}
private boolean containsHandleForCurrentYear(Iterable<CertificateHandle> certificateHandles) {
return filterHandlesForCurrentYear(certificateHandles).iterator().hasNext();
private boolean containsValidHandle(Iterable<CertificateHandle> certificateHandles) {
return filterValidHandles(certificateHandles).iterator().hasNext();
}
private Iterable<CertificateHandle> filterHandlesForCurrentYear(Iterable<CertificateHandle> certificateHandles) {
final List<CertificateHandle> result = new LinkedList<>();
final Calendar cal = new GregorianCalendar();
final int currentYear = cal.get(Calendar.YEAR);
for (final CertificateHandle handle : certificateHandles) {
cal.setTime(handle.getIssueDate().asDate());
if (cal.get(Calendar.YEAR) == currentYear) {
result.add(handle);
}
}
return result;
private Iterable<CertificateHandle> filterValidHandles(Iterable<CertificateHandle> certificateHandles) {
return Util.filter(certificateHandles, handle->handle.isValid());
}
/**
@@ -613,7 +745,7 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
private Iterable<CertificateHandle> fuzzySearchVaryingBoatClassName(final String yachtName, final String sailNumber, final BoatClass boatClass) throws Exception {
String successfulBoatClassName = boatClass==null?null:boatClass.getName();
Iterable<CertificateHandle> certificateHandles = search(/* issuingCountry */ null, /* yearOfIssuance */ null, /* referenceNumber */ null, yachtName, sailNumber, successfulBoatClassName, /* includeInvalid */ false);
if (!containsHandleForCurrentYear(certificateHandles) && successfulBoatClassName != null) {
if (!containsValidHandle(certificateHandles) && successfulBoatClassName != null) {
if (yachtName != null || sailNumber != null) {
logger.fine(()->"Nothing found; removing boat class name restriction "+boatClass.getName());
// try without boat class restriction
@@ -627,7 +759,7 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
// if a valid boatClass was specified, try to filter; if none match the filter, return unfiltered
if (boatClass != null) {
final Set<CertificateHandle> restrictedResults = new HashSet<>();
for (final CertificateHandle handle : filterHandlesForCurrentYear(certificateHandles)) {
for (final CertificateHandle handle : filterValidHandles(certificateHandles)) {
final BoatClassMasterdata boatClassMasterData = BoatClassMasterdata.resolveBoatClass(handle.getBoatClassName());
if (boatClassMasterData != null && boatClassMasterData.getDisplayName().equals(boatClass.getName())) {
restrictedResults.add(handle);
@@ -28,10 +28,183 @@
<stringAttribute key="profilingTraceType-NETWORK_TRACE" value="KEY_SESSION_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_USER_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_REQUEST_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_RESOLVE_ALL_HOSTS%CTX_KEY%true%CTX_ENTRY%KEY_APPLICATION_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_ENABLEMENT%CTX_KEY%false%CTX_ENTRY%"/>
<stringAttribute key="profilingTraceType-PERFORMANCE_HOTSPOT_TRACE" value="KEY_SESSION_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_USER_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_REQUEST_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_IGNORE_SLEEPING_THREADS%CTX_KEY%true%CTX_ENTRY%KEY_APPLICATION_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_ENABLEMENT%CTX_KEY%false%CTX_ENTRY%"/>
<stringAttribute key="profilingTraceType-SYNCHRONIZATION_TRACE" value="KEY_SESSION_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_USER_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_REQUEST_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_APPLICATION_FILTER%CTX_KEY%*%CTX_ENTRY%KEY_ENABLEMENT%CTX_KEY%false%CTX_ENTRY%"/>
<setAttribute key="selected_target_bundles">
<setEntry value="com.fasterxml.jackson.core.jackson-annotations@default:default"/>
<setEntry value="com.fasterxml.jackson.core.jackson-core@default:default"/>
<setEntry value="com.fasterxml.jackson.core.jackson-databind@default:default"/>
<setEntry value="com.rabbitmq.client@default:default"/>
<setEntry value="com.sun.activation.javax.activation@default:default"/>
<setEntry value="com.sun.istack.commons-runtime@default:default"/>
<setEntry value="com.sun.jersey.contribs.jersey-multipart@default:default"/>
<setEntry value="com.sun.jersey@default:default"/>
<setEntry value="com.sun.mail.javax.mail@default:default"/>
<setEntry value="com.sun.xml.bind.jaxb-impl@default:default"/>
<setEntry value="jackson-core-asl@default:default"/>
<setEntry value="jackson-jaxrs@default:default"/>
<setEntry value="jackson-mapper-asl@default:default"/>
<setEntry value="javax.servlet@default:default"/>
<setEntry value="javax.validation@default:default"/>
<setEntry value="javax.ws.rs@default:default"/>
<setEntry value="javax.xml.stream@default:default"/>
<setEntry value="javax.xml.ws@default:default"/>
<setEntry value="javax.xml@default:default"/>
<setEntry value="jaxb-api@default:default"/>
<setEntry value="jcl.over.slf4j@default:default"/>
<setEntry value="lz4-java@default:default"/>
<setEntry value="org.apache.commons.beanutils@default:default"/>
<setEntry value="org.apache.commons.codec@default:default"/>
<setEntry value="org.apache.commons.collections@default:default"/>
<setEntry value="org.apache.commons.fileupload@default:default"/>
<setEntry value="org.apache.commons.io@default:default"/>
<setEntry value="org.apache.commons.lang@default:default"/>
<setEntry value="org.apache.commons.math3@default:default"/>
<setEntry value="org.apache.commons.math@default:default"/>
<setEntry value="org.apache.felix.gogo.command@default:default"/>
<setEntry value="org.apache.felix.gogo.runtime@default:default"/>
<setEntry value="org.apache.felix.gogo.shell@default:default"/>
<setEntry value="org.apache.felix.shell.remote@default:default"/>
<setEntry value="org.apache.felix.shell@default:default"/>
<setEntry value="org.apache.httpcomponents.httpclient@default:default"/>
<setEntry value="org.apache.httpcomponents.httpcore@default:default"/>
<setEntry value="org.apache.poi.ooxml.schemas@default:default"/>
<setEntry value="org.apache.poi.ooxml@default:default"/>
<setEntry value="org.apache.poi@default:default"/>
<setEntry value="org.apache.servicemix.bundles.aws-java-sdk@default:default"/>
<setEntry value="org.apache.servicemix.bundles.ehcache@default:default"/>
<setEntry value="org.apache.servicemix.bundles.scribe@default:default"/>
<setEntry value="org.apache.servicemix.bundles.zxing@default:default"/>
<setEntry value="org.apache.shiro.core@default:default"/>
<setEntry value="org.apache.shiro.ehcache@default:default"/>
<setEntry value="org.apache.shiro.web@default:default"/>
<setEntry value="org.apache.xmlbeans@default:default"/>
<setEntry value="org.dom4j@default:default"/>
<setEntry value="org.eclipse.equinox.cm@default:default"/>
<setEntry value="org.eclipse.equinox.common@2:true"/>
<setEntry value="org.eclipse.equinox.console@default:default"/>
<setEntry value="org.eclipse.equinox.launcher@default:default"/>
<setEntry value="org.eclipse.equinox.simpleconfigurator@1:true"/>
<setEntry value="org.eclipse.jetty.client@default:default"/>
<setEntry value="org.eclipse.jetty.deploy@default:default"/>
<setEntry value="org.eclipse.jetty.http@default:default"/>
<setEntry value="org.eclipse.jetty.io@default:default"/>
<setEntry value="org.eclipse.jetty.jmx@default:default"/>
<setEntry value="org.eclipse.jetty.osgi.boot@default:default"/>
<setEntry value="org.eclipse.jetty.security@default:default"/>
<setEntry value="org.eclipse.jetty.server@default:default"/>
<setEntry value="org.eclipse.jetty.servlet@default:default"/>
<setEntry value="org.eclipse.jetty.util@default:default"/>
<setEntry value="org.eclipse.jetty.webapp@default:default"/>
<setEntry value="org.eclipse.jetty.websocket.api@default:default"/>
<setEntry value="org.eclipse.jetty.websocket.client@default:default"/>
<setEntry value="org.eclipse.jetty.websocket.common@default:default"/>
<setEntry value="org.eclipse.jetty.xml@default:default"/>
<setEntry value="org.eclipse.osgi.services@default:default"/>
<setEntry value="org.eclipse.osgi.util@default:default"/>
<setEntry value="org.eclipse.osgi@-1:true"/>
<setEntry value="org.hyperic.sigar@default:default"/>
<setEntry value="org.jdom@default:default"/>
<setEntry value="org.jvnet.mimepull@default:default"/>
<setEntry value="org.mongodb.mongo-java-driver@default:default"/>
<setEntry value="org.objectweb.asm@default:default"/>
<setEntry value="routeconverter@default:default"/>
<setEntry value="slf4j.api@default:default"/>
<setEntry value="slf4j.jdk14@default:false"/>
</setAttribute>
<setAttribute key="selected_workspace_bundles">
<setEntry value="com.google.gwt.servlet@default:default"/>
<setEntry value="com.googlecode.java-diff-utils@default:default"/>
<setEntry value="com.sap.sailing.barbados.resultimport@default:default"/>
<setEntry value="com.sap.sailing.competitorimport@default:default"/>
<setEntry value="com.sap.sailing.dashboards.gwt@default:default"/>
<setEntry value="com.sap.sailing.datamining.provider@default:default"/>
<setEntry value="com.sap.sailing.datamining.shared@default:default"/>
<setEntry value="com.sap.sailing.datamining@default:default"/>
<setEntry value="com.sap.sailing.declination@default:default"/>
<setEntry value="com.sap.sailing.domain.bravoadapter@default:default"/>
<setEntry value="com.sap.sailing.domain.common@default:default"/>
<setEntry value="com.sap.sailing.domain.deckmanadapter@default:default"/>
<setEntry value="com.sap.sailing.domain.expeditionadapter@default:default"/>
<setEntry value="com.sap.sailing.domain.igtimiadapter.gateway@default:default"/>
<setEntry value="com.sap.sailing.domain.igtimiadapter.persistence@default:default"/>
<setEntry value="com.sap.sailing.domain.igtimiadapter@default:default"/>
<setEntry value="com.sap.sailing.domain.persistence@default:default"/>
<setEntry value="com.sap.sailing.domain.racelogtrackingadapter@default:default"/>
<setEntry value="com.sap.sailing.domain.shared.android@default:default"/>
<setEntry value="com.sap.sailing.domain.swisstimingadapter.persistence@default:default"/>
<setEntry value="com.sap.sailing.domain.swisstimingadapter@default:default"/>
<setEntry value="com.sap.sailing.domain.swisstimingreplayadapter@default:default"/>
<setEntry value="com.sap.sailing.domain.tractracadapter.persistence@default:default"/>
<setEntry value="com.sap.sailing.domain.tractracadapter@default:default"/>
<setEntry value="com.sap.sailing.domain.windfinderadapter@default:default"/>
<setEntry value="com.sap.sailing.domain@default:default"/>
<setEntry value="com.sap.sailing.ess40.resultimport@default:default"/>
<setEntry value="com.sap.sailing.expeditionconnector.common@default:default"/>
<setEntry value="com.sap.sailing.expeditionconnector.persistence@default:default"/>
<setEntry value="com.sap.sailing.expeditionconnector@default:default"/>
<setEntry value="com.sap.sailing.freg.resultimport@default:default"/>
<setEntry value="com.sap.sailing.geocoding@default:default"/>
<setEntry value="com.sap.sailing.grib@default:default"/>
<setEntry value="com.sap.sailing.gwt.ui@default:default"/>
<setEntry value="com.sap.sailing.kiworesultimport@default:default"/>
<setEntry value="com.sap.sailing.manage2sail.resultimport@default:default"/>
<setEntry value="com.sap.sailing.manage2sail@default:default"/>
<setEntry value="com.sap.sailing.monitoring@default:default"/>
<setEntry value="com.sap.sailing.news@default:default"/>
<setEntry value="com.sap.sailing.nmeaconnector@default:default"/>
<setEntry value="com.sap.sailing.polars.datamining.shared@default:default"/>
<setEntry value="com.sap.sailing.polars.datamining@default:default"/>
<setEntry value="com.sap.sailing.polars@default:default"/>
<setEntry value="com.sap.sailing.resultimport@default:default"/>
<setEntry value="com.sap.sailing.routeconverterjava11extension@default:false"/>
<setEntry value="com.sap.sailing.sailwave.resultimport@default:default"/>
<setEntry value="com.sap.sailing.server.gateway.serialization.shared.android@default:default"/>
<setEntry value="com.sap.sailing.server.gateway.serialization@default:default"/>
<setEntry value="com.sap.sailing.server.gateway.test.support@4:true"/>
<setEntry value="com.sap.sailing.server.gateway@default:default"/>
<setEntry value="com.sap.sailing.server.interface@default:default"/>
<setEntry value="com.sap.sailing.server.trackfiles@default:default"/>
<setEntry value="com.sap.sailing.server@default:default"/>
<setEntry value="com.sap.sailing.simulator@default:default"/>
<setEntry value="com.sap.sailing.udpconnector@default:default"/>
<setEntry value="com.sap.sailing.velum.resultimport@default:default"/>
<setEntry value="com.sap.sailing.www@default:default"/>
<setEntry value="com.sap.sailing.xmlexport@default:default"/>
<setEntry value="com.sap.sailing.xrr.resultimport@default:default"/>
<setEntry value="com.sap.sailing.xrr.schema@default:default"/>
<setEntry value="com.sap.sailing.xrr.structureimport@default:default"/>
<setEntry value="com.sap.sailing.yachtscoring.resultimport@default:default"/>
<setEntry value="com.sap.sse.common@default:default"/>
<setEntry value="com.sap.sse.datamining.annotations@default:default"/>
<setEntry value="com.sap.sse.datamining.shared@default:default"/>
<setEntry value="com.sap.sse.datamining.ui@default:default"/>
<setEntry value="com.sap.sse.datamining@default:default"/>
<setEntry value="com.sap.sse.filestorage@default:default"/>
<setEntry value="com.sap.sse.gwt.adminconsole@default:default"/>
<setEntry value="com.sap.sse.gwt@default:default"/>
<setEntry value="com.sap.sse.jersey.jaxbdependencyfragment@default:false"/>
<setEntry value="com.sap.sse.jettyextensions@default:false"/>
<setEntry value="com.sap.sse.mail@default:default"/>
<setEntry value="com.sap.sse.mongodb@default:default"/>
<setEntry value="com.sap.sse.operationaltransformation@default:default"/>
<setEntry value="com.sap.sse.replication.interfaces@default:default"/>
<setEntry value="com.sap.sse.replication@default:default"/>
<setEntry value="com.sap.sse.security.common@default:default"/>
<setEntry value="com.sap.sse.security.interface@default:default"/>
<setEntry value="com.sap.sse.security.persistence@default:default"/>
<setEntry value="com.sap.sse.security.ui@default:default"/>
<setEntry value="com.sap.sse.security.userstore.mongodb@default:default"/>
<setEntry value="com.sap.sse.security@default:default"/>
<setEntry value="com.sap.sse.shared.android@default:default"/>
<setEntry value="com.sap.sse.threadmanager@default:default"/>
<setEntry value="com.sap.sse@default:default"/>
<setEntry value="com.tractrac.clientmodule@default:default"/>
<setEntry value="net.sf.marineapi@default:default"/>
<setEntry value="org.json.simple@default:default"/>
<setEntry value="org.moxieapps.gwt.highcharts@default:default"/>
<setEntry value="org.mp4parser.isoparser@default:default"/>
</setAttribute>
<booleanAttribute key="show_selected_only" value="false"/>
<stringAttribute key="target_bundles" value="com.fasterxml.jackson.core.jackson-annotations@default:default,com.fasterxml.jackson.core.jackson-core@default:default,com.fasterxml.jackson.core.jackson-databind@default:default,com.rabbitmq.client@default:default,com.sun.activation.javax.activation@default:default,com.sun.istack.commons-runtime@default:default,com.sun.jersey.contribs.jersey-multipart@default:default,com.sun.jersey@default:default,com.sun.mail.javax.mail@default:default,com.sun.xml.bind.jaxb-impl@default:default,jackson-core-asl@default:default,jackson-jaxrs@default:default,jackson-mapper-asl@default:default,javax.servlet@default:default,javax.validation@default:default,javax.ws.rs@default:default,javax.xml.stream@default:default,javax.xml.ws@default:default,javax.xml@default:default,jaxb-api@default:default,jcl.over.slf4j@default:default,lz4-java@default:default,org.apache.commons.beanutils@default:default,org.apache.commons.codec@default:default,org.apache.commons.collections@default:default,org.apache.commons.fileupload@default:default,org.apache.commons.io@default:default,org.apache.commons.lang@default:default,org.apache.commons.math3@default:default,org.apache.commons.math@default:default,org.apache.felix.gogo.command@default:default,org.apache.felix.gogo.runtime@default:default,org.apache.felix.gogo.shell@default:default,org.apache.felix.shell.remote@default:default,org.apache.felix.shell@default:default,org.apache.httpcomponents.httpclient@default:default,org.apache.httpcomponents.httpcore@default:default,org.apache.poi.ooxml.schemas@default:default,org.apache.poi.ooxml@default:default,org.apache.poi@default:default,org.apache.servicemix.bundles.aws-java-sdk@default:default,org.apache.servicemix.bundles.ehcache@default:default,org.apache.servicemix.bundles.scribe@default:default,org.apache.servicemix.bundles.zxing@default:default,org.apache.shiro.core@default:default,org.apache.shiro.ehcache@default:default,org.apache.shiro.web@default:default,org.apache.xmlbeans@default:default,org.dom4j@default:default,org.eclipse.equinox.cm@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.console@default:default,org.eclipse.equinox.launcher@default:default,org.eclipse.equinox.simpleconfigurator@1:true,org.eclipse.jetty.client@default:default,org.eclipse.jetty.deploy@default:default,org.eclipse.jetty.http@default:default,org.eclipse.jetty.io@default:default,org.eclipse.jetty.jmx@default:default,org.eclipse.jetty.osgi.boot@default:default,org.eclipse.jetty.security@default:default,org.eclipse.jetty.server@default:default,org.eclipse.jetty.servlet@default:default,org.eclipse.jetty.util@default:default,org.eclipse.jetty.webapp@default:default,org.eclipse.jetty.websocket.api@default:default,org.eclipse.jetty.websocket.client@default:default,org.eclipse.jetty.websocket.common@default:default,org.eclipse.jetty.xml@default:default,org.eclipse.osgi.services@default:default,org.eclipse.osgi.util@default:default,org.eclipse.osgi@-1:true,org.hyperic.sigar@default:default,org.jdom@default:default,org.jvnet.mimepull@default:default,org.mongodb.mongo-java-driver@default:default,org.objectweb.asm@default:default,routeconverter@default:default,slf4j.api@default:default,slf4j.jdk14@default:false"/>
<booleanAttribute key="tracing" value="false"/>
<booleanAttribute key="useCustomFeatures" value="false"/>
<booleanAttribute key="useDefaultConfigArea" value="false"/>
<stringAttribute key="workspace_bundles" value="com.google.gwt.servlet@default:default,com.googlecode.java-diff-utils@default:default,com.sap.sailing.barbados.resultimport@default:default,com.sap.sailing.competitorimport@default:default,com.sap.sailing.dashboards.gwt@default:default,com.sap.sailing.datamining.provider@default:default,com.sap.sailing.datamining.shared@default:default,com.sap.sailing.datamining@default:default,com.sap.sailing.declination@default:default,com.sap.sailing.domain.bravoadapter@default:default,com.sap.sailing.domain.common@default:default,com.sap.sailing.domain.deckmanadapter@default:default,com.sap.sailing.domain.expeditionadapter@default:default,com.sap.sailing.domain.igtimiadapter.gateway@default:default,com.sap.sailing.domain.igtimiadapter.persistence@default:default,com.sap.sailing.domain.igtimiadapter@default:default,com.sap.sailing.domain.persistence@default:default,com.sap.sailing.domain.racelogtrackingadapter@default:default,com.sap.sailing.domain.shared.android@default:default,com.sap.sailing.domain.swisstimingadapter.persistence@default:default,com.sap.sailing.domain.swisstimingadapter@default:default,com.sap.sailing.domain.swisstimingreplayadapter@default:default,com.sap.sailing.domain.tractracadapter.persistence@default:default,com.sap.sailing.domain.tractracadapter@default:default,com.sap.sailing.domain.windfinderadapter@default:default,com.sap.sailing.domain@default:default,com.sap.sailing.ess40.resultimport@default:default,com.sap.sailing.expeditionconnector.common@default:default,com.sap.sailing.expeditionconnector.persistence@default:default,com.sap.sailing.expeditionconnector@default:default,com.sap.sailing.freg.resultimport@default:default,com.sap.sailing.geocoding@default:default,com.sap.sailing.grib@default:default,com.sap.sailing.gwt.ui@default:default,com.sap.sailing.kiworesultimport@default:default,com.sap.sailing.manage2sail.resultimport@default:default,com.sap.sailing.manage2sail@default:default,com.sap.sailing.monitoring@default:default,com.sap.sailing.news@default:default,com.sap.sailing.nmeaconnector@default:default,com.sap.sailing.polars.datamining.shared@default:default,com.sap.sailing.polars.datamining@default:default,com.sap.sailing.polars@default:default,com.sap.sailing.resultimport@default:default,com.sap.sailing.routeconverterjava11extension@default:false,com.sap.sailing.sailwave.resultimport@default:default,com.sap.sailing.server.gateway.serialization.shared.android@default:default,com.sap.sailing.server.gateway.serialization@default:default,com.sap.sailing.server.gateway.test.support@4:true,com.sap.sailing.server.gateway@default:default,com.sap.sailing.server.interface@default:default,com.sap.sailing.server.trackfiles@default:default,com.sap.sailing.server@default:default,com.sap.sailing.simulator@default:default,com.sap.sailing.udpconnector@default:default,com.sap.sailing.velum.resultimport@default:default,com.sap.sailing.www@default:default,com.sap.sailing.xmlexport@default:default,com.sap.sailing.xrr.resultimport@default:default,com.sap.sailing.xrr.schema@default:default,com.sap.sailing.xrr.structureimport@default:default,com.sap.sailing.yachtscoring.resultimport@default:default,com.sap.sse.common@default:default,com.sap.sse.datamining.annotations@default:default,com.sap.sse.datamining.shared@default:default,com.sap.sse.datamining.ui@default:default,com.sap.sse.datamining@default:default,com.sap.sse.filestorage@default:default,com.sap.sse.gwt.adminconsole@default:default,com.sap.sse.gwt@default:default,com.sap.sse.jersey.jaxbdependencyfragment@default:false,com.sap.sse.jettyextensions@default:false,com.sap.sse.mail@default:default,com.sap.sse.mongodb@default:default,com.sap.sse.operationaltransformation@default:default,com.sap.sse.replication.interfaces@default:default,com.sap.sse.replication@default:default,com.sap.sse.security.common@default:default,com.sap.sse.security.interface@default:default,com.sap.sse.security.persistence@default:default,com.sap.sse.security.ui@default:default,com.sap.sse.security.userstore.mongodb@default:default,com.sap.sse.security@default:default,com.sap.sse.shared.android@default:default,com.sap.sse.threadmanager@default:default,com.sap.sse@default:default,com.tractrac.clientmodule@default:default,net.sf.marineapi@default:default,org.json.simple@default:default,org.moxieapps.gwt.highcharts@default:default,org.mp4parser.isoparser@default:default"/>
</launchConfiguration>