From 62a44426fd07a50e96e5c5f1d19e2cf97a878913 Mon Sep 17 00:00:00 2001 From: gmantele <gmantele@ari.uni-heidelberg.de> Date: Thu, 19 Feb 2015 12:04:01 +0100 Subject: [PATCH] [TAP] Add a property in the configuration file to set a custom TAPFactory (in replacement of ConfigurableTAPFactory. --- .../config/ConfigurableServiceConnection.java | 13 ++- src/tap/config/TAPConfiguration.java | 3 + src/tap/config/tap_configuration_file.html | 21 ++++- src/tap/config/tap_full.properties | 18 +++- .../TestConfigurableServiceConnection.java | 90 ++++++++++++++++++- 5 files changed, 138 insertions(+), 7 deletions(-) diff --git a/src/tap/config/ConfigurableServiceConnection.java b/src/tap/config/ConfigurableServiceConnection.java index 0d4add6..ab4be58 100644 --- a/src/tap/config/ConfigurableServiceConnection.java +++ b/src/tap/config/ConfigurableServiceConnection.java @@ -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); diff --git a/src/tap/config/TAPConfiguration.java b/src/tap/config/TAPConfiguration.java index 436ec66..f49fa7f 100644 --- a/src/tap/config/TAPConfiguration.java +++ b/src/tap/config/TAPConfiguration.java @@ -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> diff --git a/src/tap/config/tap_configuration_file.html b/src/tap/config/tap_configuration_file.html index 091ad61..fd8ab7c 100644 --- a/src/tap/config/tap_configuration_file.html +++ b/src/tap/config/tap_configuration_file.html @@ -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; diff --git a/src/tap/config/tap_full.properties b/src/tap/config/tap_full.properties index f89fb2f..666f8da 100644 --- a/src/tap/config/tap_full.properties +++ b/src/tap/config/tap_full.properties @@ -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 = diff --git a/test/tap/config/TestConfigurableServiceConnection.java b/test/tap/config/TestConfigurableServiceConnection.java index 11bfd22..d232be8 100644 --- a/test/tap/config/TestConfigurableServiceConnection.java +++ b/test/tap/config/TestConfigurableServiceConnection.java @@ -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é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é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(){} + + } + } -- GitLab