Skip to content
Snippets Groups Projects
Commit 62a44426 authored by gmantele's avatar gmantele
Browse files

[TAP] Add a property in the configuration file to set a custom TAPFactory (in...

[TAP] Add a property in the configuration file to set a custom TAPFactory (in replacement of ConfigurableTAPFactory.
parent c790223e
No related branches found
No related tags found
No related merge requests found
......@@ -27,6 +27,7 @@ import static tap.config.TAPConfiguration.KEY_MIN_LOG_LEVEL;
import static tap.config.TAPConfiguration.KEY_OUTPUT_FORMATS;
import static tap.config.TAPConfiguration.KEY_PROVIDER_NAME;
import static tap.config.TAPConfiguration.KEY_SERVICE_DESCRIPTION;
import static tap.config.TAPConfiguration.KEY_TAP_FACTORY;
import static tap.config.TAPConfiguration.KEY_UDFS;
import static tap.config.TAPConfiguration.KEY_UPLOAD_ENABLED;
import static tap.config.TAPConfiguration.KEY_UPLOAD_MAX_FILE_SIZE;
......@@ -93,7 +94,7 @@ public final class ConfigurableServiceConnection implements ServiceConnection {
private TAPLog logger;
private ConfigurableTAPFactory tapFactory;
private TAPFactory tapFactory;
private final TAPMetadata metadata;
......@@ -136,7 +137,7 @@ public final class ConfigurableServiceConnection implements ServiceConnection {
initLogger(tapConfig);
// 3. BUILD THE TAP FACTORY:
tapFactory = new ConfigurableTAPFactory(this, tapConfig);
initFactory(tapConfig);
// 4. GET THE METADATA:
metadata = initMetadata(tapConfig);
......@@ -236,6 +237,14 @@ public final class ConfigurableServiceConnection implements ServiceConnection {
logger.info(buf.toString());
}
private void initFactory(final Properties tapConfig) throws TAPException{
String propValue = getProperty(tapConfig, KEY_TAP_FACTORY);
if (propValue == null)
tapFactory = new ConfigurableTAPFactory(this, tapConfig);
else
tapFactory = newInstance(propValue, KEY_TAP_FACTORY, TAPFactory.class, new Class<?>[]{ServiceConnection.class}, new Object[]{this});
}
private TAPMetadata initMetadata(final Properties tapConfig) throws TAPException{
// Get the fetching method to use:
String metaFetchType = getProperty(tapConfig, KEY_METADATA);
......
......@@ -115,6 +115,9 @@ public final class TAPConfiguration {
/* ADDITIONAL TAP RESOURCES */
public final static String KEY_ADD_TAP_RESOURCES = "additional_resources";
/* CUSTOM FACTORY */
public final static String KEY_TAP_FACTORY = "tap_factory";
/**
* <p>Read the asked property from the given Properties object.</p>
* <ul>
......
......@@ -146,7 +146,7 @@
<td></td>
</tr>
<tr><td colspan="5">Database</td></tr>
<tr><td colspan="5">Database (only if tap_factory = ø)</td></tr>
<tr class="mandatory">
<td class="done">database_access</td>
<td></td>
......@@ -374,7 +374,7 @@
<td><ul><li>D 6 30</li><li>W 2 6 30</li><li>M 2 6 30</li><li>H 10</li><li>m</li></ul></td>
</tr>
<tr><td colspan="5">UWS Backup</td></tr>
<tr><td colspan="5">UWS Backup (only if tap_factory = ø)</td></tr>
<tr class="optional">
<td class="done">backup_frequency</td>
<td></td>
......@@ -622,6 +622,23 @@
<td>{aPackage.QuickADQLValidator}</td>
</tr>
<tr><td colspan="5">Custom TAP Factory</td></tr>
<tr class="optional">
<td class="done">tap_factory</td>
<td></td>
<td>text</td>
<td>
<p>Class to use in replacement of the default TAPFactory.</p>
<p>
This property must be a class name (given between {...}). It must reference an extension of the abstract TAPFactory.
This extension must have at least one constructor with exactly one parameter of type ServiceConnection.
</p>
<p><em>By default, the default TAPFactory (tap.config.ConfigurableTAPFactory) is used and may use all properties related to the backup management,
the database access and the ADQL translation.</em></p>
</td>
<td>{aPackage.MyTAPFactory}</td>
</tr>
</table>
<script type="text/javascript">
var nb = document.getElementsByClassName("mandatory").length;
......
......@@ -2,7 +2,7 @@
# FULL TAP CONFIGURATION FILE #
# #
# TAP Version: 2.0 #
# Date: 18 Feb. 2015 #
# Date: 19 Feb. 2015 #
# Author: Gregory Mantelet (ARI) #
# #
##########################################################
......@@ -463,4 +463,18 @@ udfs =
# name (e.g. if getName() returns "sync", the /sync resource won't be anymore the default Sync resource of this library but your new resource).
#
# By default, this list is empty ; only the standard TAP resources exist.
additional_resources =
\ No newline at end of file
additional_resources =
######################
# CUSTOM TAP_FACTORY #
######################
# [OPTIONAL]
# Class to use in replacement of the default TAPFactory.
#
# This property must be a class name (given between {...}). It must reference an extension of the abstract TAPFactory.
# This extension must have at least one constructor with exactly one parameter of type ServiceConnection.
#
# By default, the default TAPFactory (tap.config.ConfigurableTAPFactory) is used and may use all properties related to the backup management,
# the database access and the ADQL translation.
tap_factory =
......@@ -17,6 +17,7 @@ import static tap.config.TAPConfiguration.KEY_METADATA;
import static tap.config.TAPConfiguration.KEY_METADATA_FILE;
import static tap.config.TAPConfiguration.KEY_MIN_LOG_LEVEL;
import static tap.config.TAPConfiguration.KEY_OUTPUT_FORMATS;
import static tap.config.TAPConfiguration.KEY_TAP_FACTORY;
import static tap.config.TAPConfiguration.KEY_UDFS;
import static tap.config.TAPConfiguration.KEY_USER_IDENTIFIER;
import static tap.config.TAPConfiguration.VALUE_ANY;
......@@ -44,9 +45,13 @@ import javax.servlet.http.HttpServletRequest;
import org.junit.BeforeClass;
import org.junit.Test;
import tap.AbstractTAPFactory;
import tap.ServiceConnection;
import tap.ServiceConnection.LimitUnit;
import tap.TAPException;
import tap.db.DBConnection;
import tap.db.DBException;
import tap.db.JDBCConnection;
import tap.formatter.OutputFormat;
import tap.formatter.VOTableFormat;
import uk.ac.starlink.votable.DataFormat;
......@@ -61,6 +66,7 @@ import uws.service.log.DefaultUWSLog;
import uws.service.log.UWSLog.LogLevel;
import adql.db.FunctionDef;
import adql.db.TestDBChecker.UDFToto;
import adql.translator.PostgreSQLTranslator;
public class TestConfigurableServiceConnection {
......@@ -83,7 +89,8 @@ public class TestConfigurableServiceConnection {
udfsListWithNONEorANYProp, udfsWithWrongParamLengthProp,
udfsWithMissingBracketsProp, udfsWithMissingDefProp1,
udfsWithMissingDefProp2, emptyUdfItemProp1, emptyUdfItemProp2,
udfWithMissingEndBracketProp;
udfWithMissingEndBracketProp, customFactoryProp,
badCustomFactoryProp;
@BeforeClass
public static void setUp() throws Exception{
......@@ -242,6 +249,12 @@ public class TestConfigurableServiceConnection {
udfWithMissingEndBracketProp = (Properties)validProp.clone();
udfWithMissingEndBracketProp.setProperty(KEY_UDFS, "[toto(a string)->VARCHAR");
customFactoryProp = (Properties)validProp.clone();
customFactoryProp.setProperty(KEY_TAP_FACTORY, "{tap.config.TestConfigurableServiceConnection$CustomTAPFactory}");
badCustomFactoryProp = (Properties)validProp.clone();
badCustomFactoryProp.setProperty(KEY_TAP_FACTORY, "{tap.config.TestConfigurableServiceConnection$BadCustomTAPFactory}");
}
/**
......@@ -855,6 +868,24 @@ public class TestConfigurableServiceConnection {
assertEquals(TAPException.class, e.getClass());
assertEquals("Wrong UDF declaration syntax: missing closing bracket at position 24!", e.getMessage());
}
// Valid custom TAPFactory:
try{
ServiceConnection connection = new ConfigurableServiceConnection(customFactoryProp);
assertNotNull(connection.getFactory());
assertEquals(CustomTAPFactory.class, connection.getFactory().getClass());
}catch(Exception e){
fail("This MUST have succeeded because the given custom TAPFactory exists and have the required constructor! \nCaught exception: " + getPertinentMessage(e));
}
// Bad custom TAPFactory (required constructor missing):
try{
new ConfigurableServiceConnection(badCustomFactoryProp);
fail("This MUST have failed because the specified TAPFactory extension does not have a constructor with ServiceConnection!");
}catch(Exception e){
assertEquals(TAPException.class, e.getClass());
assertEquals("Missing constructor tap.config.TestConfigurableServiceConnection$BadCustomTAPFactory(tap.ServiceConnection)! See the value \"{tap.config.TestConfigurableServiceConnection$BadCustomTAPFactory}\" of the property \"" + KEY_TAP_FACTORY + "\".", e.getMessage());
}
}
public static final String getPertinentMessage(final Exception ex){
......@@ -898,4 +929,61 @@ public class TestConfigurableServiceConnection {
}
/**
* TAPFactory just to test whether the property tap_factory works well.
*
* @author Gr&eacute;gory Mantelet (ARI)
* @version 02/2015
*/
private static class CustomTAPFactory extends AbstractTAPFactory {
private final JDBCConnection dbConn;
public CustomTAPFactory(final ServiceConnection conn) throws DBException{
super(conn);
dbConn = new JDBCConnection("", "jdbc:postgresql:gmantele", "gmantele", null, new PostgreSQLTranslator(), "TheOnlyConnection", conn.getLogger());
}
@Override
public DBConnection getConnection(final String jobID) throws TAPException{
return dbConn;
}
@Override
public void freeConnection(final DBConnection conn){}
@Override
public void destroy(){
try{
dbConn.getInnerConnection().close();
}catch(Exception ex){}
}
}
/**
* TAPFactory just to test whether the property tap_factory is rejected when no constructor with a single parameter of type ServiceConnection exists.
*
* @author Gr&eacute;gory Mantelet (ARI)
* @version 02/2015
*/
private static class BadCustomTAPFactory extends AbstractTAPFactory {
public BadCustomTAPFactory() throws DBException{
super(null);
}
@Override
public DBConnection getConnection(final String jobID) throws TAPException{
return null;
}
@Override
public void freeConnection(final DBConnection conn){}
@Override
public void destroy(){}
}
}
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