Skip to content
Snippets Groups Projects
Commit 1bcf8906 authored by gmantele's avatar gmantele
Browse files

[TAP] Add a configuration file property: 'coordinate_systems'. It lets list...

[TAP] Add a configuration file property: 'coordinate_systems'. It lets list all allowed coordinate systems. By default, the list is empty, meaning that any is allowed.
parent df668abf
No related branches found
No related tags found
No related merge requests found
...@@ -6,6 +6,7 @@ import static tap.config.TAPConfiguration.DEFAULT_GROUP_USER_DIRECTORIES; ...@@ -6,6 +6,7 @@ import static tap.config.TAPConfiguration.DEFAULT_GROUP_USER_DIRECTORIES;
import static tap.config.TAPConfiguration.DEFAULT_MAX_ASYNC_JOBS; import static tap.config.TAPConfiguration.DEFAULT_MAX_ASYNC_JOBS;
import static tap.config.TAPConfiguration.DEFAULT_RETENTION_PERIOD; import static tap.config.TAPConfiguration.DEFAULT_RETENTION_PERIOD;
import static tap.config.TAPConfiguration.DEFAULT_UPLOAD_MAX_FILE_SIZE; import static tap.config.TAPConfiguration.DEFAULT_UPLOAD_MAX_FILE_SIZE;
import static tap.config.TAPConfiguration.KEY_COORD_SYS;
import static tap.config.TAPConfiguration.KEY_DEFAULT_EXECUTION_DURATION; import static tap.config.TAPConfiguration.KEY_DEFAULT_EXECUTION_DURATION;
import static tap.config.TAPConfiguration.KEY_DEFAULT_OUTPUT_LIMIT; import static tap.config.TAPConfiguration.KEY_DEFAULT_OUTPUT_LIMIT;
import static tap.config.TAPConfiguration.KEY_DEFAULT_RETENTION_PERIOD; import static tap.config.TAPConfiguration.KEY_DEFAULT_RETENTION_PERIOD;
...@@ -87,6 +88,7 @@ import uws.service.file.LocalUWSFileManager; ...@@ -87,6 +88,7 @@ import uws.service.file.LocalUWSFileManager;
import uws.service.file.UWSFileManager; import uws.service.file.UWSFileManager;
import uws.service.log.UWSLog.LogLevel; import uws.service.log.UWSLog.LogLevel;
import adql.db.FunctionDef; import adql.db.FunctionDef;
import adql.db.STCS;
import adql.parser.ParseException; import adql.parser.ParseException;
import adql.query.operand.function.UserDefinedFunction; import adql.query.operand.function.UserDefinedFunction;
...@@ -123,6 +125,8 @@ public final class ConfigurableServiceConnection implements ServiceConnection { ...@@ -123,6 +125,8 @@ public final class ConfigurableServiceConnection implements ServiceConnection {
private UserIdentifier userIdentifier = null; private UserIdentifier userIdentifier = null;
private ArrayList<String> lstCoordSys = null;
private ArrayList<String> geometries = null; private ArrayList<String> geometries = null;
private final String GEOMETRY_REGEXP = "(AREA|BOX|CENTROID|CIRCLE|CONTAINS|DISTANCE|COORD1|COORD2|COORDSYS|INTERSECTS|POINT|POLYGON|REGION)"; private final String GEOMETRY_REGEXP = "(AREA|BOX|CENTROID|CIRCLE|CONTAINS|DISTANCE|COORD1|COORD2|COORDSYS|INTERSECTS|POINT|POLYGON|REGION)";
...@@ -175,6 +179,7 @@ public final class ConfigurableServiceConnection implements ServiceConnection { ...@@ -175,6 +179,7 @@ public final class ConfigurableServiceConnection implements ServiceConnection {
initUserIdentifier(tapConfig); initUserIdentifier(tapConfig);
// 9. CONFIGURE ADQL: // 9. CONFIGURE ADQL:
initCoordSys(tapConfig);
initADQLGeometries(tapConfig); initADQLGeometries(tapConfig);
initUDFs(tapConfig); initUDFs(tapConfig);
} }
...@@ -669,6 +674,57 @@ public final class ConfigurableServiceConnection implements ServiceConnection { ...@@ -669,6 +674,57 @@ public final class ConfigurableServiceConnection implements ServiceConnection {
userIdentifier = newInstance(propValue, KEY_USER_IDENTIFIER, UserIdentifier.class); userIdentifier = newInstance(propValue, KEY_USER_IDENTIFIER, UserIdentifier.class);
} }
private void initCoordSys(final Properties tapConfig) throws TAPException{
// Get the property value:
String propValue = getProperty(tapConfig, KEY_COORD_SYS);
// NO VALUE => ALL COORD SYS ALLOWED!
if (propValue == null)
lstCoordSys = null;
// "NONE" => ALL COORD SYS FORBIDDEN (= no coordinate system expression is allowed)!
else if (propValue.equalsIgnoreCase(VALUE_NONE))
lstCoordSys = new ArrayList<String>(0);
// "ANY" => ALL COORD SYS ALLOWED (= any coordinate system is allowed)!
else if (propValue.equalsIgnoreCase(VALUE_ANY))
lstCoordSys = null;
// OTHERWISE, JUST THE ALLOWED ONE ARE LISTED:
else{
// split all the list items:
String[] items = propValue.split(",");
if (items.length > 0){
lstCoordSys = new ArrayList<String>(items.length);
for(String item : items){
item = item.trim();
// empty item => ignored
if (item.length() <= 0)
continue;
// "NONE" is not allowed inside a list => error!
else if (item.toUpperCase().equals(VALUE_NONE))
throw new TAPException("The special value \"" + VALUE_NONE + "\" can not be used inside a list! It MUST be used in replacement of a whole list to specify that no value is allowed.");
// "ANY" is not allowed inside a list => error!
else if (item.toUpperCase().equals(VALUE_ANY))
throw new TAPException("The special value \"" + VALUE_ANY + "\" can not be used inside a list! It MUST be used in replacement of a whole list to specify that any value is allowed.");
// parse the coordinate system regular expression in order to check it:
else{
try{
STCS.buildCoordSysRegExp(new String[]{item});
lstCoordSys.add(item);
}catch(ParseException pe){
throw new TAPException("Incorrect coordinate system regular expression (\"" + item + "\"): " + pe.getMessage(), pe);
}
}
}
// if finally no item has been specified, consider it as "any coordinate system allowed":
if (lstCoordSys.size() == 0)
lstCoordSys = null;
}else
lstCoordSys = null;
}
}
private void initADQLGeometries(final Properties tapConfig) throws TAPException{ private void initADQLGeometries(final Properties tapConfig) throws TAPException{
// Get the property value: // Get the property value:
String propValue = getProperty(tapConfig, KEY_GEOMETRIES); String propValue = getProperty(tapConfig, KEY_GEOMETRIES);
...@@ -996,7 +1052,7 @@ public final class ConfigurableServiceConnection implements ServiceConnection { ...@@ -996,7 +1052,7 @@ public final class ConfigurableServiceConnection implements ServiceConnection {
@Override @Override
public Collection<String> getCoordinateSystems(){ public Collection<String> getCoordinateSystems(){
return null; return lstCoordSys;
} }
@Override @Override
......
...@@ -107,6 +107,7 @@ public final class TAPConfiguration { ...@@ -107,6 +107,7 @@ public final class TAPConfiguration {
public final static String KEY_USER_IDENTIFIER = "user_identifier"; public final static String KEY_USER_IDENTIFIER = "user_identifier";
/* ADQL RESTRICTIONS */ /* ADQL RESTRICTIONS */
public final static String KEY_COORD_SYS = "coordinate_systems";
public final static String KEY_GEOMETRIES = "geometries"; public final static String KEY_GEOMETRIES = "geometries";
public final static String VALUE_NONE = "NONE"; public final static String VALUE_NONE = "NONE";
public final static String KEY_UDFS = "udfs"; public final static String KEY_UDFS = "udfs";
......
...@@ -568,6 +568,33 @@ ...@@ -568,6 +568,33 @@
</tr> </tr>
<tr><td colspan="5">ADQL restrictions</td></tr> <tr><td colspan="5">ADQL restrictions</td></tr>
<tr class="optional">
<td class="done">coordinate_systems</td>
<td></td>
<td>text</td>
<td>
<p>Comma-separated list of all allowed coordinate systems.</p>
<p>
Each item of the list be a kind of regular expression respecting the following syntax:
<code><i>Frame</i> <i>RefPos</i> <i>Flavor</i></code>. In other words, it must be a string of exactly
3 parts. Each of this part is a single value, a list of allowed values or a <code>*</code> meaning all
values. A list of values must be indicated between parenthesis and values must be separated by a pipe.
</p>
<p>Allowed values for <code>Frame</code> are: <code>ICRS</code>, <code>FK4</code>,
<code>FK5</code>, <code>ECLIPTIC</code>, <code>GALACTIC</code> and <code>UNKNOWNFRAME</code>.</p>
<p>Allowed values for <code>RefPos</code> are: <code>BARYCENTER</code>, <code>GEOCENTER</code>,
<code>HELIOCENTER</code>, <code>LSR</code>, <code>TOPOCENTER</code>, <code>RELOCATABLE</code>
and <code>UNKNOWNREFPOS</code>.</p>
<p>Allowed values for <code>Flavor</code> are: <code>CARTESIAN2</code>, <code>CARTESIAN3</code> and
<code>SPHERICAL2</code>.</p>
<p>
If the special value <em>NONE</em> is given instead of a list of allowed coordinate systems,
no coordinate system will be allowed. And if the list is empty, any coordinate system will be allowed.
</p>
<p><em>By default, any coordinate system is allowed.</em></p>
</td>
<td><ul><li>ø <em>(default)</em></li><li>NONE</li><li>ICRS * *</li><li>ICRS * *, ECLIPTIC * (CARTESIAN2 | SPHERICAL2)</li></ul></td>
</tr>
<tr class="optional"> <tr class="optional">
<td class="done">geometries</td> <td class="done">geometries</td>
<td></td> <td></td>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# FULL TAP CONFIGURATION FILE # # FULL TAP CONFIGURATION FILE #
# # # #
# TAP Version: 2.0 # # TAP Version: 2.0 #
# Date: 10 Mars 2015 # # Date: 11 Mars 2015 #
# Author: Gregory Mantelet (ARI) # # Author: Gregory Mantelet (ARI) #
# # # #
########################################################## ##########################################################
...@@ -416,6 +416,24 @@ upload_max_file_size = 2147483647B ...@@ -416,6 +416,24 @@ upload_max_file_size = 2147483647B
# Default: no identification is performed => all users are then anonymous and their jobs can be seen by everybody. # Default: no identification is performed => all users are then anonymous and their jobs can be seen by everybody.
user_identifier = user_identifier =
######################
# COORDINATE SYSTEMS #
######################
# [OPTIONAL]
# Comma-separated list of all allowed coordinate systems.
#
# Each item of the list be a kind of regular expression respecting the following syntax: Frame RefPos Flavor. In other words, it must be a string of exactly 3 parts. Each of this part is a single value, a list of allowed values or a * meaning all values. A list of values must be indicated between parenthesis and values must be separated by a pipe.
#
# Allowed values for Frame are: ICRS, FK4, FK5, ECLIPTIC, GALACTIC and UNKNOWNFRAME.
# Allowed values for RefPos are: BARYCENTER, GEOCENTER, HELIOCENTER, LSR, TOPOCENTER, RELOCATABLE and UNKNOWNREFPOS.
# Allowed values for Flavor are: CARTESIAN2, CARTESIAN3 and SPHERICAL2.
#
# If the special value NONE is given instead of a list of allowed coordinate systems, no coordinate system will be allowed. And if the list is empty, any coordinate system will be allowed.
#
# By default, any coordinate system is allowed.
coordinate_systems =
############## ##############
# GEOMETRIES # # GEOMETRIES #
############## ##############
......
...@@ -7,6 +7,7 @@ import static org.junit.Assert.assertNull; ...@@ -7,6 +7,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static tap.config.TAPConfiguration.DEFAULT_MAX_ASYNC_JOBS; import static tap.config.TAPConfiguration.DEFAULT_MAX_ASYNC_JOBS;
import static tap.config.TAPConfiguration.KEY_COORD_SYS;
import static tap.config.TAPConfiguration.KEY_DEFAULT_OUTPUT_LIMIT; import static tap.config.TAPConfiguration.KEY_DEFAULT_OUTPUT_LIMIT;
import static tap.config.TAPConfiguration.KEY_FILE_MANAGER; import static tap.config.TAPConfiguration.KEY_FILE_MANAGER;
import static tap.config.TAPConfiguration.KEY_GEOMETRIES; import static tap.config.TAPConfiguration.KEY_GEOMETRIES;
...@@ -65,6 +66,9 @@ import uws.service.file.LocalUWSFileManager; ...@@ -65,6 +66,9 @@ import uws.service.file.LocalUWSFileManager;
import uws.service.log.DefaultUWSLog; import uws.service.log.DefaultUWSLog;
import uws.service.log.UWSLog.LogLevel; import uws.service.log.UWSLog.LogLevel;
import adql.db.FunctionDef; import adql.db.FunctionDef;
import adql.db.STCS.Flavor;
import adql.db.STCS.Frame;
import adql.db.STCS.RefPos;
import adql.db.TestDBChecker.UDFToto; import adql.db.TestDBChecker.UDFToto;
import adql.translator.PostgreSQLTranslator; import adql.translator.PostgreSQLTranslator;
...@@ -83,14 +87,15 @@ public class TestConfigurableServiceConnection { ...@@ -83,14 +87,15 @@ public class TestConfigurableServiceConnection {
maxAsyncProp, negativeMaxAsyncProp, notIntMaxAsyncProp, maxAsyncProp, negativeMaxAsyncProp, notIntMaxAsyncProp,
defaultOutputLimitProp, maxOutputLimitProp, defaultOutputLimitProp, maxOutputLimitProp,
bothOutputLimitGoodProp, bothOutputLimitBadProp, userIdentProp, bothOutputLimitGoodProp, bothOutputLimitBadProp, userIdentProp,
notClassPathUserIdentProp, geometriesProp, noneGeomProp, notClassPathUserIdentProp, coordSysProp, noneCoordSysProp,
anyGeomProp, noneInsideGeomProp, unknownGeomProp, anyUdfsProp, anyCoordSysProp, noneInsideCoordSysProp, unknownCoordSysProp,
noneUdfsProp, udfsProp, udfsWithClassNameProp, geometriesProp, noneGeomProp, anyGeomProp, noneInsideGeomProp,
udfsListWithNONEorANYProp, udfsWithWrongParamLengthProp, unknownGeomProp, anyUdfsProp, noneUdfsProp, udfsProp,
udfsWithMissingBracketsProp, udfsWithMissingDefProp1, udfsWithClassNameProp, udfsListWithNONEorANYProp,
udfsWithMissingDefProp2, emptyUdfItemProp1, emptyUdfItemProp2, udfsWithWrongParamLengthProp, udfsWithMissingBracketsProp,
udfWithMissingEndBracketProp, customFactoryProp, udfsWithMissingDefProp1, udfsWithMissingDefProp2,
badCustomFactoryProp; emptyUdfItemProp1, emptyUdfItemProp2, udfWithMissingEndBracketProp,
customFactoryProp, badCustomFactoryProp;
@BeforeClass @BeforeClass
public static void setUp() throws Exception{ public static void setUp() throws Exception{
...@@ -199,6 +204,21 @@ public class TestConfigurableServiceConnection { ...@@ -199,6 +204,21 @@ public class TestConfigurableServiceConnection {
notClassPathUserIdentProp = (Properties)validProp.clone(); notClassPathUserIdentProp = (Properties)validProp.clone();
notClassPathUserIdentProp.setProperty(KEY_USER_IDENTIFIER, "foo"); notClassPathUserIdentProp.setProperty(KEY_USER_IDENTIFIER, "foo");
coordSysProp = (Properties)validProp.clone();
coordSysProp.setProperty(KEY_COORD_SYS, "icrs * *, ICrs * (Spherical2| CARTEsian2)");
noneCoordSysProp = (Properties)validProp.clone();
noneCoordSysProp.setProperty(KEY_COORD_SYS, VALUE_NONE);
anyCoordSysProp = (Properties)validProp.clone();
anyCoordSysProp.setProperty(KEY_COORD_SYS, VALUE_ANY);
noneInsideCoordSysProp = (Properties)validProp.clone();
noneInsideCoordSysProp.setProperty(KEY_COORD_SYS, " ICRS * *, none, FK4 (GEOCENTER|heliocenter) *");
unknownCoordSysProp = (Properties)validProp.clone();
unknownCoordSysProp.setProperty(KEY_COORD_SYS, "ICRS foo *");
geometriesProp = (Properties)validProp.clone(); geometriesProp = (Properties)validProp.clone();
geometriesProp.setProperty(KEY_GEOMETRIES, "point, CIRCle , cONTAins,intersECTS"); geometriesProp.setProperty(KEY_GEOMETRIES, "point, CIRCle , cONTAins,intersECTS");
...@@ -756,6 +776,52 @@ public class TestConfigurableServiceConnection { ...@@ -756,6 +776,52 @@ public class TestConfigurableServiceConnection {
assertEquals("Unknown ADQL geometrical function: \"foo\"!", e.getMessage()); assertEquals("Unknown ADQL geometrical function: \"foo\"!", e.getMessage());
} }
// Valid coordinate systems list:
try{
ServiceConnection connection = new ConfigurableServiceConnection(coordSysProp);
assertNotNull(connection.getCoordinateSystems());
assertEquals(2, connection.getCoordinateSystems().size());
assertEquals("icrs * *", ((ArrayList<String>)connection.getCoordinateSystems()).get(0));
assertEquals("ICrs * (Spherical2| CARTEsian2)", ((ArrayList<String>)connection.getCoordinateSystems()).get(1));
}catch(Exception e){
fail("This MUST have succeeded because the given list of coordinate systems is correct! \nCaught exception: " + getPertinentMessage(e));
}
// "NONE" as coordinate systems list:
try{
ServiceConnection connection = new ConfigurableServiceConnection(noneCoordSysProp);
assertNotNull(connection.getCoordinateSystems());
assertEquals(0, connection.getCoordinateSystems().size());
}catch(Exception e){
fail("This MUST have succeeded because the given list of coordinate systems is correct (reduced to only NONE)! \nCaught exception: " + getPertinentMessage(e));
}
// "ANY" as coordinate systems list:
try{
ServiceConnection connection = new ConfigurableServiceConnection(anyCoordSysProp);
assertNull(connection.getCoordinateSystems());
}catch(Exception e){
fail("This MUST have succeeded because the given list of coordinate systems is correct (reduced to only ANY)! \nCaught exception: " + getPertinentMessage(e));
}
// "NONE" inside a coordinate systems list:
try{
new ConfigurableServiceConnection(noneInsideCoordSysProp);
fail("This MUST have failed because the given coordinate systems list contains at least 3 items, whose one is NONE!");
}catch(Exception e){
assertEquals(TAPException.class, e.getClass());
assertEquals("The special value \"" + VALUE_NONE + "\" can not be used inside a list! It MUST be used in replacement of a whole list to specify that no value is allowed.", e.getMessage());
}
// Unknown coordinate system function:
try{
new ConfigurableServiceConnection(unknownCoordSysProp);
fail("This MUST have failed because the given coordinate systems list contains at least 1 unknown coordinate system!");
}catch(Exception e){
assertEquals(TAPException.class, e.getClass());
assertEquals("Incorrect coordinate system regular expression (\"ICRS foo *\"): Wrong allowed coordinate system syntax for the 1-th item: \"ICRS foo *\"! Expected: \"frameRegExp refposRegExp flavorRegExp\" ; where each xxxRegExp = (xxx | '*' | '('xxx ('|' xxx)*')'), frame=\"" + Frame.regexp + "\", refpos=\"" + RefPos.regexp + "\" and flavor=\"" + Flavor.regexp + "\" ; an empty string is also allowed and will be interpreted as '*' (so all possible values).", e.getMessage());
}
// "ANY" as UDFs list: // "ANY" as UDFs list:
try{ try{
ServiceConnection connection = new ConfigurableServiceConnection(anyUdfsProp); ServiceConnection connection = new ConfigurableServiceConnection(anyUdfsProp);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment