package tap; /* * This file is part of TAPLibrary. * * TAPLibrary is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * TAPLibrary is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with TAPLibrary. If not, see . * * Copyright 2012-2020 - UDS/Centre de Données astronomiques de Strasbourg (CDS), * Astronomisches Rechen Institut (ARI) */ import java.util.Collection; import java.util.Iterator; import adql.db.FunctionDef; import tap.db.DBConnection; import tap.db.QueryExecutor; import tap.formatter.OutputFormat; import tap.log.DefaultTAPLog; import tap.log.TAPLog; import tap.metadata.TAPMetadata; import uws.service.UserIdentifier; import uws.service.file.LocalUWSFileManager; import uws.service.file.UWSFileManager; /** * Description and parameters list of a TAP service. * *

* Through this object, it is possible to configure the different limits and * formats, but also to list all available tables and columns, to declare * geometry features as well as all allowed user defined functions and to say * where log and other kinds of files must be stored. *

* * @author Grégory Mantelet (CDS;ARI) * @version 2.4 (08/2020) */ public interface ServiceConnection { /** * List of possible limit units. * * @author Grégory Mantelet (CDS;ARI) * @version 2.3 (04/2019) */ public static enum LimitUnit { rows("row"), bytes("byte"), kilobytes("kilobyte"), megabytes("megabyte"), gigabytes("gigabyte"); private final String str; private LimitUnit(final String str) { this.str = str; } /** * Tells whether the given unit has the same type (bytes or rows). * * @param anotherUnit A unit. * * @return true if the given unit has the same type, * false otherwise. * * @since 1.1 */ public boolean isCompatibleWith(final LimitUnit anotherUnit) { if (this == rows) return anotherUnit == rows; else return anotherUnit != rows; } /** * Gets the factor to convert into bytes the value expressed in this * unit. * *

Note: * if this unit is not a factor of bytes, 1 is returned (so that the * factor does not affect the value). *

* * @return The factor need to convert a value expressed in this unit * into bytes, or 1 if not a bytes derived unit. * * @since 1.1 */ public long bytesFactor() { switch(this) { case bytes: return 1; case kilobytes: return 1000; case megabytes: return 1000000; case gigabytes: return 1000000000l; default: return 1; } } /** * Compares the 2 given values (each one expressed in the given unit). * *

* Conversions are done internally in order to make a correct * comparison between the 2 limits. *

* * @param leftLimit Value/Limit of the comparison left part. * @param leftUnit Unit of the comparison left part value. * @param rightLimit Value/Limit of the comparison right part. * @param rightUnit Unit of the comparison right part value. * * @return the value 0 if x == y; a value less than 0 if x < y; * and a value greater than 0 if x > y * * @throws TAPException If the two given units are not compatible. * * @see #compare(long, tap.ServiceConnection.LimitUnit, long, tap.ServiceConnection.LimitUnit) * * @since 1.1 */ public static int compare(final int leftLimit, final LimitUnit leftUnit, final int rightLimit, final LimitUnit rightUnit) throws TAPException { return compare((long)leftLimit, leftUnit, (long)rightLimit, rightUnit); } /** * Compares the 2 given values (each one expressed in the given unit). * *

* Conversions are done internally in order to make a correct * comparison between the 2 limits. *

* * @param leftLimit Value/Limit of the comparison left part. * @param leftUnit Unit of the comparison left part value. * @param rightLimit Value/Limit of the comparison right part. * @param rightUnit Unit of the comparison right part value. * * @return the value 0 if x == y; * a value less than 0 if x < y; * and a value greater than 0 if x > y * * @throws TAPException If the two given units are not compatible. * * @see tap.ServiceConnection.LimitUnit#isCompatibleWith(tap.ServiceConnection.LimitUnit) * @see #bytesFactor() * @see Integer#compare(int, int) * @see Long#compare(long, long) * * @since 2.3 */ public static int compare(final long leftLimit, final LimitUnit leftUnit, final long rightLimit, final LimitUnit rightUnit) throws TAPException { if (!leftUnit.isCompatibleWith(rightUnit)) throw new TAPException("Limit units (" + leftUnit + " and " + rightUnit + ") are not compatible!"); if (leftUnit == rows || leftUnit == rightUnit) return compare(leftLimit, rightLimit); else return compare(leftLimit * leftUnit.bytesFactor(), rightLimit * rightUnit.bytesFactor()); } /** *

(Strict copy of Integer.compare(long,long) of Java 1.7)

*

* Compares two {@code long} values numerically. * The value returned is identical to what would be returned by: *

*
		 *    Long.valueOf(x).compareTo(Long.valueOf(y))
		 * 
* * @param x the first {@code long} to compare * @param y the second {@code long} to compare * @return the value {@code 0} if {@code x == y}; * a value less than {@code 0} if {@code x < y}; and * a value greater than {@code 0} if {@code x > y} * * @since 1.1 */ public static int compare(long x, long y) { return (x < y) ? -1 : ((x == y) ? 0 : 1); } @Override public String toString() { return str; } } /** * [OPTIONAL] *

* Name of the service provider ; it can be an organization as an * individual person. *

* *

* There is no restriction on the syntax or on the label to use ; this * information is totally free. *

* *

* It will be used as additional information (INFO tag) in any VOTable and * HTML output. *

* * @return The TAP service provider or NULL to leave this field blank. */ public String getProviderName(); /** * [OPTIONAL] *

Description of the service provider.

* *

* It will be used as additional information (INFO tag) in any VOTable * output. *

* * @return The TAP service description or NULL to leave this field blank. */ public String getProviderDescription(); /** * [MANDATORY] *

* This function tells whether the TAP service is available (that's to say, * "able to execute requests" ; resources like /availability, /capabilities * and /tables may still work). *

* *

* A message explaining the current state of the TAP service could be * provided thanks to {@link #getAvailability()}. *

* * @return true to enable all TAP resources, * false to disable all of them (except /availability) */ public boolean isAvailable(); /** * [OPTIONAL] *

* Get an explanation about the current TAP service state (working or not). * This message aims to provide more details to the users about the * availability of this service, or more particularly about its * unavailability. *

* * @return Explanation about the TAP service state. */ public String getAvailability(); /** * [MANDATORY] *

This function sets the state of the whole TAP service. * If true, all TAP resources will be able to execute * resources. If false, /sync and /async won't answer any more * to requests and a HTTP-503 (Service unavailable) error will be returned. *

* * @param isAvailable true to enable all resources, * false to forbid /sync and /async (all * other resources will still be available). * @param message A message describing the current state of the * service. If NULL, a default message may be set by * the library. * * @since 2.0 */ public void setAvailable(final boolean isAvailable, final String message); /** * [OPTIONAL] *

Get the limit of the retention period (in seconds).

* *

* It is the maximum period while an asynchronous job can leave in the jobs * list and so can stay on the server. *

* *

Important notes:

* * * @return NULL if no limit must be set, or a two-items array * ([0]: default value, * [1]: maximum value). */ public int[] getRetentionPeriod(); /** * [OPTIONAL] *

Get the limit of the job execution duration (in milliseconds).

* *

* It is the duration of a running job (including the query execution). * The two first values are used for asynchronous jobs, and the last one * (if provided) for synchronous jobs. *

* *

Important notes:

* * * @return NULL if no limit must be set, or a two- or three-items array * ([0]: default value, * [1]: maximum value, * [2]: value for sync queries). */ public int[] getExecutionDuration(); /** * [OPTIONAL] *

Get the limit of the job execution result.

* *

* This value will limit the size of the query results, either in rows or * in bytes. The type of limit is defined by the function * {@link #getOutputLimitType()}. *

* *

Important notes:

* * *

Important note: * Currently, the default implementations of the library is only able to * deal with output limits in ROWS.
* Anyway, in order to save performances, it is strongly recommended to use * ROWS limit rather than in bytes. Indeed, the rows limit can be taken * into account at the effective execution of the query (so before getting * the result), on the contrary of the bytes limit which will be applied on * the query result. *

* * @return NULL if no limit must be set, or a two-items array * ([0]: default value, * [1]: maximum value). * * @see #getOutputLimitType() */ public int[] getOutputLimit(); /** * [OPTIONAL] *

* Get the type of each output limit set by this service connection (and * accessible with {@link #getOutputLimit()}). *

* *

Important notes:

* * *

Important note: * Currently, the default implementations of the library is only able to * deal with output limits in ROWS.
* Anyway, in order to save performances, it is strongly recommended to use * ROWS limit rather than in bytes. Indeed, the rows limit can be taken * into account at the effective execution of the query (so before getting * the result), on the contrary of the bytes limit which will be applied on * the query result. *

* * @return NULL if limits should be expressed in ROWS, or a two-items array * ([0]: type of getOutputLimit()[0], * [1]: type of getOutputLimit()[1]). * * @see #getOutputLimit() */ public LimitUnit[] getOutputLimitType(); /** * [OPTIONAL] *

* Get the object to use in order to identify users at the origin of * requests. *

* * @return NULL if no user identification should be done, * a {@link UserIdentifier} instance otherwise. */ public UserIdentifier getUserIdentifier(); public QueryExecutor getQueryExecutor(); /** * [MANDATORY] *

This function lets enable or disable the upload capability of this TAP * service.

* *

Note: * If the upload is disabled, the request is aborted and an HTTP-400 error * is thrown each time some tables are uploaded. *

* * @return true to enable the upload capability, * false to disable it. */ public boolean uploadEnabled(); /** * [OPTIONAL] *

Get the maximum size of EACH uploaded table.

* *

* This value is expressed either in rows or in bytes. * The unit limit is defined by the function {@link #getUploadLimitType()}. *

* *

Important notes:

* * *

Important note: * To save performances, it is recommended to use BYTES limit rather than * in rows. Indeed, the bytes limit can be taken into account at directly * when reading the bytes of the request, on the contrary of the rows limit * which requires to parse the uploaded tables. *

* * @return NULL if no limit must be set, * or a two-items array ([0]: default value, [1]: maximum value). * * @see #getUploadLimitType() */ public long[] getUploadLimit(); /** * [OPTIONAL] *

Get the type of each upload limit set by this service connection (and * accessible with {@link #getUploadLimit()}).

* *

Important notes:

* * *

Important note: * To save performances, it is recommended to use BYTES limit rather than * in rows. Indeed, the bytes limit can be taken into account at directly * when reading the bytes of the request, on the contrary of the rows limit * which requires to parse the uploaded tables. *

* * @return NULL if limits should be expressed in ROWS, * or a two-items array ([0]: type of getUploadLimit()[0], * [1]: type of getUploadLimit()[1]). * * @see #getUploadLimit() */ public LimitUnit[] getUploadLimitType(); /** * [OPTIONAL] *

Get the maximum size of the whole set of all tables uploaded in one * request. This size is expressed in bytes.

* *

NOTE: * This value can be negative. In such case, there will be no limit on the * size of an HTTP request. *

* * @return A positive value (>0) corresponding to the maximum number of * bytes of all uploaded tables sent in one request. * A negative value (≤0) means "unlimited". */ public long getMaxUploadSize(); /** * [MANDATORY] *

Get the list of all available tables and columns.

* *

* This object is really important since it lets the library check ADQL * queries properly and set the good type and formatting in the query * results. *

* * @return A TAPMetadata object. NULL is not allowed and will throw a * grave error at the service initialization. */ public TAPMetadata getTAPMetadata(); /** * [OPTIONAL] *

Get the list of all allowed coordinate systems.

* * Special values * *

Two special values can be returned by this function:

* * * List item syntax * *

* Each item of this list is a pattern and not a simple coordinate * system. Thus each item MUST respect the following syntax: *

*
{framePattern} {refposPattern} {flavorPattern}
*

* Contrary to a coordinate system expression, all these 3 information are * required. Each may take 3 kinds of value: *

* *

* For instance: (ICRS|FK4) HELIOCENTER * is a good syntax, * but not ICRS or ICRS HELIOCENTER. *

* *

Note: * Even if not explicitly part of the possible values, the default value of * each part (i.e. UNKNOWNFRAME for frame) is always taken into account by * the library. Particularly, the empty string will always be allowed even * if not explicitly listed in the list returned by this function. *

* * @return NULL to allow ALL coordinate systems, an empty list to allow NO * coordinate system, * or a list of coordinate system patterns otherwise. */ public Collection getCoordinateSystems(); /** * [OPTIONAL] *

Get the list of all allowed geometrical functions.

* * Special values * *

Two special values can be returned by this function:

* * * List item syntax * *

* Each item of the returned list MUST be a function name * (i.e. "CONTAINS", "POINT"). It can also be a type of STC region to * forbid (i.e. "POSITION", "UNION"). *

* *

The given names are not case sensitive.

* * @return NULL to allow ALL geometrical functions, an empty list to allow * NO geometrical function, * or a list of geometrical function names otherwise. * * @since 2.0 */ public Collection getGeometries(); /** * [OPTIONAL] *

Get the list of all allowed User Defined Functions (UDFs).

* * Special values * *

Two special values can be returned by this function:

*
    *
  • NULL which means that all unknown functions (which should be * UDFs) are allowed,
  • *
  • the empty list which means that no unknown functions (which * should be UDFs) is allowed.
  • *
* * List item syntax * *

* Each item of the returned list MUST be an instance of * {@link FunctionDef}. *

* * @return NULL to allow ALL unknown functions, an empty list to allow NO * unknown function, * or a list of user defined functions otherwise. * * @since 2.0 */ public Collection getUDFs(); /** * [OPTIONAL] * *

* Get the maximum number of asynchronous jobs that can run in the same * time. *

* *

* A null or negative value means no limit on the number of running * asynchronous jobs. *

* * @return Maximum number of running jobs (≤0 => no limit). * * @since 2.0 */ public int getNbMaxAsyncJobs(); /** * [MANDATORY] *

* Get the logger to use in the whole service when any error, warning or * info happens. *

* *

IMPORTANT: * If NULL is returned by this function, grave errors will occur while * executing a query or managing an error. It is strongly recommended to * provide a logger, even a basic implementation. *

* *

Piece of advice: * A default implementation like {@link DefaultTAPLog} would be most of * time largely enough. *

* * @return An instance of {@link TAPLog}. */ public TAPLog getLogger(); /** * [MANDATORY] *

* Get the object able to build other objects essentials to configure the * TAP service or to run every queries. *

* *

IMPORTANT: * If NULL is returned by this function, grave errors will occur while * initializing the service. *

* *

Piece of advice: * The {@link TAPFactory} is an interface which contains a lot of functions * to implement. It is rather recommended to extend * {@link AbstractTAPFactory}: just 2 functions * ({@link AbstractTAPFactory#freeConnection(DBConnection)} and * {@link AbstractTAPFactory#getConnection(String)}) will have to be * implemented. *

* * @return An instance of {@link TAPFactory}. * * @see AbstractTAPFactory */ public TAPFactory getFactory(); /** * [MANDATORY] *

* Get the object in charge of the files management. * This object manages log, error, result and backup files of the whole * service. *

* *

IMPORTANT: * If NULL is returned by this function, grave errors will occur while * initializing the service. *

* *

Piece of advice: * The library provides a default implementation of the interface * {@link UWSFileManager}: {@link LocalUWSFileManager}, which stores all * files on the local file-system. *

* * @return An instance of {@link UWSFileManager}. */ public UWSFileManager getFileManager(); /** * [MANDATORY] *

Get the list of all available output formats.

* *

IMPORTANT:

*
    *
  • All formats of this list MUST have a different MIME type.
  • *
  • At least one item must correspond to the MIME type "votable".
  • *
  • If NULL is returned by this function, grave errors will occur while * writing the capabilities of this service.
  • * * * @return An iterator on the list of all available output formats. */ public Iterator getOutputFormats(); /** * [MANDATORY] *

    * Get the output format having the given MIME type * (or short MIME type ~ alias). *

    * *

    IMPORTANT: * This function MUST always return an {@link OutputFormat} instance when * the MIME type "votable" is given in parameter. *

    * * @param mimeOrAlias MIME type or short MIME type of the format to get. * * @return The corresponding {@link OutputFormat} or NULL if not found. */ public OutputFormat getOutputFormat(final String mimeOrAlias); /** * [OPTIONAL] *

    Get the size of result blocks to fetch from the database.

    * *

    * Rather than fetching a query result in a whole, it may be possible to * specify to the database that results may be retrieved by blocks whose * the size can be specified by this function. If supported by the DBMS and * the JDBC driver, this feature may help sparing memory and avoid too much * waiting time from the TAP /sync users (and thus, avoiding some HTTP * client timeouts). *

    * *

    Note: * Generally, this feature is well supported by DBMS. But for that, the * used JDBC driver must use the V3 protocol. If anyway, this feature is * supported neither by the DBMS, the JDBC driver nor your * {@link DBConnection}, no error will be thrown if a value is returned by * this function: it will be silently ignored by the library. *

    * * @return NULL or an array of 1 or 2 integers. * If NULL (or empty array), no attempt to set fetch size * will be done and so, ONLY the default value of the * {@link DBConnection} will be used. * [0]=fetchSize for async queries, * [1]=fetchSize for sync queries. * If [1] is omitted, it will be considered as equals to [0]. * If a fetchSize is negative or null, the default value of your * JDBC driver will be used. * * @since 2.0 */ public int[] getFetchSize(); /** * [MANDATORY] *

    * This function tells whether TAP-Lib should automatically try to fix a * query whose parsing failed because of a token error. After this fix * attempt the query is parsed again for a last time. *

    * * @return true to allow automatic fix attempt in case of * error, * false to disable this option. * * @since 2.3 */ public boolean fixOnFailEnabled(); }