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
Loading
Loading
Loading
Loading
+57 −1
Original line number Diff line number Diff line
@@ -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_RETENTION_PERIOD;
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_OUTPUT_LIMIT;
import static tap.config.TAPConfiguration.KEY_DEFAULT_RETENTION_PERIOD;
@@ -87,6 +88,7 @@ import uws.service.file.LocalUWSFileManager;
import uws.service.file.UWSFileManager;
import uws.service.log.UWSLog.LogLevel;
import adql.db.FunctionDef;
import adql.db.STCS;
import adql.parser.ParseException;
import adql.query.operand.function.UserDefinedFunction;

@@ -123,6 +125,8 @@ public final class ConfigurableServiceConnection implements ServiceConnection {

	private UserIdentifier userIdentifier = null;

	private ArrayList<String> lstCoordSys = null;

	private ArrayList<String> geometries = null;
	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 {
		initUserIdentifier(tapConfig);

		// 9. CONFIGURE ADQL:
		initCoordSys(tapConfig);
		initADQLGeometries(tapConfig);
		initUDFs(tapConfig);
	}
@@ -669,6 +674,57 @@ public final class ConfigurableServiceConnection implements ServiceConnection {
			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{
		// Get the property value:
		String propValue = getProperty(tapConfig, KEY_GEOMETRIES);
@@ -996,7 +1052,7 @@ public final class ConfigurableServiceConnection implements ServiceConnection {

	@Override
	public Collection<String> getCoordinateSystems(){
		return null;
		return lstCoordSys;
	}

	@Override
+1 −0
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ public final class TAPConfiguration {
	public final static String KEY_USER_IDENTIFIER = "user_identifier";

	/* ADQL RESTRICTIONS */
	public final static String KEY_COORD_SYS = "coordinate_systems";
	public final static String KEY_GEOMETRIES = "geometries";
	public final static String VALUE_NONE = "NONE";
	public final static String KEY_UDFS = "udfs";
+27 −0
Original line number Diff line number Diff line
@@ -568,6 +568,33 @@
			</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">
				<td class="done">geometries</td>
				<td></td>
+19 −1
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
#             FULL TAP CONFIGURATION FILE                #
#                                                        #
# TAP Version: 2.0                                       #
# Date: 10 Mars 2015                                     #
# Date: 11 Mars 2015                                     #
# Author: Gregory Mantelet (ARI)                         #
#                                                        #
########################################################## 
@@ -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.
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 #
##############
+74 −8
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
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_FILE_MANAGER;
import static tap.config.TAPConfiguration.KEY_GEOMETRIES;
@@ -65,6 +66,9 @@ import uws.service.file.LocalUWSFileManager;
import uws.service.log.DefaultUWSLog;
import uws.service.log.UWSLog.LogLevel;
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.translator.PostgreSQLTranslator;

@@ -83,14 +87,15 @@ public class TestConfigurableServiceConnection {
			maxAsyncProp, negativeMaxAsyncProp, notIntMaxAsyncProp,
			defaultOutputLimitProp, maxOutputLimitProp,
			bothOutputLimitGoodProp, bothOutputLimitBadProp, userIdentProp,
			notClassPathUserIdentProp, geometriesProp, noneGeomProp,
			anyGeomProp, noneInsideGeomProp, unknownGeomProp, anyUdfsProp,
			noneUdfsProp, udfsProp, udfsWithClassNameProp,
			udfsListWithNONEorANYProp, udfsWithWrongParamLengthProp,
			udfsWithMissingBracketsProp, udfsWithMissingDefProp1,
			udfsWithMissingDefProp2, emptyUdfItemProp1, emptyUdfItemProp2,
			udfWithMissingEndBracketProp, customFactoryProp,
			badCustomFactoryProp;
			notClassPathUserIdentProp, coordSysProp, noneCoordSysProp,
			anyCoordSysProp, noneInsideCoordSysProp, unknownCoordSysProp,
			geometriesProp, noneGeomProp, anyGeomProp, noneInsideGeomProp,
			unknownGeomProp, anyUdfsProp, noneUdfsProp, udfsProp,
			udfsWithClassNameProp, udfsListWithNONEorANYProp,
			udfsWithWrongParamLengthProp, udfsWithMissingBracketsProp,
			udfsWithMissingDefProp1, udfsWithMissingDefProp2,
			emptyUdfItemProp1, emptyUdfItemProp2, udfWithMissingEndBracketProp,
			customFactoryProp, badCustomFactoryProp;

	@BeforeClass
	public static void setUp() throws Exception{
@@ -199,6 +204,21 @@ public class TestConfigurableServiceConnection {
		notClassPathUserIdentProp = (Properties)validProp.clone();
		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.setProperty(KEY_GEOMETRIES, "point, CIRCle  ,	cONTAins,intersECTS");

@@ -756,6 +776,52 @@ public class TestConfigurableServiceConnection {
			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:
		try{
			ServiceConnection connection = new ConfigurableServiceConnection(anyUdfsProp);