Newer
Older
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
// 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;
}
}
gmantele
committed
/**
* Initialize the list of all allowed ADQL geometrical functions.
*
* @param tapConfig The content of the TAP configuration file.
*
* @throws TAPException If the corresponding TAP configuration properties are wrong.
*/
private void initADQLGeometries(final Properties tapConfig) throws TAPException{
// Get the property value:
String propValue = getProperty(tapConfig, KEY_GEOMETRIES);
// NO VALUE => ALL FCT ALLOWED!
if (propValue == null)
geometries = null;
// "NONE" => ALL FCT FORBIDDEN (= none of these functions are allowed)!
else if (propValue.equalsIgnoreCase(VALUE_NONE))
geometries = new ArrayList<String>(0);
// "ANY" => ALL FCT ALLOWED (= all of these functions are allowed)!
else if (propValue.equalsIgnoreCase(VALUE_ANY))
geometries = null;
// OTHERWISE, JUST THE ALLOWED ONE ARE LISTED:
else{
// split all the list items:
String[] items = propValue.split(",");
if (items.length > 0){
geometries = new ArrayList<String>(items.length);
for(String item : items){
item = item.trim();
// empty item => ignored
if (item.length() <= 0)
continue;
// if it is a name of known ADQL geometrical function, add it to the list:
else if (item.toUpperCase().matches(GEOMETRY_REGEXP))
geometries.add(item.toUpperCase());
// "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.");
// unknown value => error!
else
throw new TAPException("Unknown ADQL geometrical function: \"" + item + "\"!");
}
// if finally no item has been specified, consider it as "all functions allowed":
if (geometries.size() == 0)
geometries = null;
}else
geometries = null;
}
}
gmantele
committed
/**
* Initialize the list of all known and allowed User Defined Functions.
*
* @param tapConfig The content of the TAP configuration file.
*
* @throws TAPException If the corresponding TAP configuration properties are wrong.
*/
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
private void initUDFs(final Properties tapConfig) throws TAPException{
// Get the property value:
String propValue = getProperty(tapConfig, KEY_UDFS);
// NO VALUE => NO UNKNOWN FCT ALLOWED!
if (propValue == null)
udfs = new ArrayList<FunctionDef>(0);
// "NONE" => NO UNKNOWN FCT ALLOWED (= none of the unknown functions are allowed)!
else if (propValue.equalsIgnoreCase(VALUE_NONE))
udfs = new ArrayList<FunctionDef>(0);
// "ANY" => ALL UNKNOWN FCT ALLOWED (= all of the unknown functions are allowed)!
else if (propValue.equalsIgnoreCase(VALUE_ANY))
udfs = null;
// OTHERWISE, JUST THE ALLOWED ONE ARE LISTED:
else{
char c;
int ind = 0;
short nbComma = 0;
boolean within_item = false, within_params = false, within_classpath = false;
StringBuffer buf = new StringBuffer();
String signature, classpath;
int[] posSignature = new int[]{-1,-1}, posClassPath = new int[]{-1,-1};
signature = null;
classpath = null;
buf.delete(0, buf.length());
while(ind < propValue.length()){
// Get the character:
c = propValue.charAt(ind++);
// If space => ignore
if (!within_params && Character.isWhitespace(c))
continue;
// If inside a parameters list, keep all characters until the list end (')'):
if (within_params){
if (c == ')')
within_params = false;
buf.append(c);
}
// If inside a classpath, keep all characters until the classpath end ('}'):
else if (within_classpath){
if (c == '}')
within_classpath = false;
buf.append(c);
}
// If inside an UDF declaration:
else if (within_item){
switch(c){
case '(': /* start of a parameters list */
within_params = true;
buf.append(c);
break;
case '{': /* start of a class name */
within_classpath = true;
buf.append(c);
break;
case ',': /* separation between the signature and the class name */
// count commas within this item:
if (++nbComma > 1)
// if more than 1, throw an error:
throw new TAPException("Wrong UDF declaration syntax: only two items (signature and class name) can be given within brackets. (position in the property " + KEY_UDFS + ": " + ind + ")");
// end of the signature and start of the class name:
signature = buf.toString();
buf.delete(0, buf.length());
posSignature[1] = ind;
posClassPath[0] = ind + 1;
}
break;
case ']': /* end of a UDF declaration */
within_item = false;
if (nbComma == 0){
signature = buf.toString();
posSignature[1] = ind;
}else{
classpath = (buf.length() == 0 ? null : buf.toString());
if (classpath != null)
posClassPath[1] = ind;
}
buf.delete(0, buf.length());
// no signature...
if (signature == null || signature.length() == 0){
// ...BUT a class name => error
if (classpath != null)
throw new TAPException("Missing UDF declaration! (position in the property " + KEY_UDFS + ": " + posSignature[0] + "-" + posSignature[1] + ")");
// ... => ignore this item
else
continue;
}
// add the new UDF in the list:
try{
// resolve the function signature:
FunctionDef def = FunctionDef.parse(signature);
// resolve the class name:
if (classpath != null){
if (isClassName(classpath)){
Class<? extends UserDefinedFunction> fctClass = null;
try{
// fetch the class:
fctClass = fetchClass(classpath, KEY_UDFS, UserDefinedFunction.class);
// set the class inside the UDF definition:
def.setUDFClass(fctClass);
}catch(TAPException te){
throw new TAPException("Invalid class name for the UDF definition \"" + def + "\": " + te.getMessage() + " (position in the property " + KEY_UDFS + ": " + posClassPath[0] + "-" + posClassPath[1] + ")", te);
}catch(IllegalArgumentException iae){
throw new TAPException("Invalid class name for the UDF definition \"" + def + "\": missing a constructor with a single parameter of type ADQLOperand[] " + (fctClass != null ? "in the class \"" + fctClass.getName() + "\"" : "") + "! (position in the property " + KEY_UDFS + ": " + posClassPath[0] + "-" + posClassPath[1] + ")");
throw new TAPException("Invalid class name for the UDF definition \"" + def + "\": \"" + classpath + "\" is not a class name (or is not surrounding by {} as expected in this property file)! (position in the property " + KEY_UDFS + ": " + posClassPath[0] + "-" + posClassPath[1] + ")");
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
}
// add the UDF:
udfs.add(def);
}catch(ParseException pe){
throw new TAPException("Wrong UDF declaration syntax: " + pe.getMessage() + " (position in the property " + KEY_UDFS + ": " + posSignature[0] + "-" + posSignature[1] + ")", pe);
}
// reset some variables:
nbComma = 0;
signature = null;
classpath = null;
break;
default: /* keep all other characters */
buf.append(c);
break;
}
}
// If outside of everything, just starting a UDF declaration or separate each declaration is allowed:
else{
switch(c){
case '[':
within_item = true;
posSignature[0] = ind + 1;
break;
case ',':
break;
default:
throw new TAPException("Wrong UDF declaration syntax: unexpected character at position " + ind + " in the property " + KEY_UDFS + ": \"" + c + "\"! A UDF declaration must have one of the following syntaxes: \"[signature]\" or \"[signature,{className}]\".");
}
}
}
// If the parsing is not finished, throw an error:
if (within_item)
throw new TAPException("Wrong UDF declaration syntax: missing closing bracket at position " + propValue.length() + "!");
}
}
@Override
public String getProviderName(){
return providerName;
}
@Override
public String getProviderDescription(){
return serviceDescription;
}
@Override
public boolean isAvailable(){
return isAvailable;
}
@Override
public String getAvailability(){
return availability;
}
@Override
public void setAvailable(boolean isAvailable, String message){
this.isAvailable = isAvailable;
availability = message;
}
@Override
public int[] getRetentionPeriod(){
return retentionPeriod;
}
gmantele
committed
/**
* <p>Set the default retention period.</p>
*
* <p>This period is set by default if the user did not specify one before the execution of his query.</p>
*
* <p><em><b>Important note:</b>
* This function will apply the given retention period only if legal compared to the currently set maximum value.
* In other words, if the given value is less or equals to the current maximum retention period.
* </em></p>
*
* @param period New default retention period (in seconds).
*
* @return <i>true</i> if the given retention period has been successfully set, <i>false</i> otherwise.
*/
public boolean setDefaultRetentionPeriod(final int period){
if ((retentionPeriod[1] <= 0) || (period > 0 && period <= retentionPeriod[1])){
retentionPeriod[0] = period;
return true;
}else
return false;
}
gmantele
committed
/**
* <p>Set the maximum retention period.</p>
*
* <p>This period limits the default retention period and the retention period specified by a user.</p>
*
* <p><em><b>Important note:</b>
* This function may reduce the default retention period if the current default retention period is bigger
* to the new maximum retention period. In a such case, the default retention period is set to the
* new maximum retention period.
* </em></p>
*
* @param period New maximum retention period (in seconds).
*/
public void setMaxRetentionPeriod(final int period){
// Decrease the default retention period if it will be bigger than the new maximum retention period:
if (period > 0 && (retentionPeriod[0] <= 0 || period < retentionPeriod[0]))
retentionPeriod[0] = period;
// Set the new maximum retention period:
retentionPeriod[1] = period;
}
@Override
public int[] getExecutionDuration(){
return executionDuration;
}
gmantele
committed
/**
* <p>Set the default execution duration.</p>
*
* <p>This duration is set by default if the user did not specify one before the execution of his query.</p>
*
* <p><em><b>Important note:</b>
* This function will apply the given execution duration only if legal compared to the currently set maximum value.
* In other words, if the given value is less or equals to the current maximum execution duration.
* </em></p>
*
* @param duration New default execution duration (in milliseconds).
*
* @return <i>true</i> if the given execution duration has been successfully set, <i>false</i> otherwise.
*/
public boolean setDefaultExecutionDuration(final int duration){
if ((executionDuration[1] <= 0) || (duration > 0 && duration <= executionDuration[1])){
executionDuration[0] = duration;
return true;
}else
return false;
}
gmantele
committed
/**
* <p>Set the maximum execution duration.</p>
*
* <p>This duration limits the default execution duration and the execution duration specified by a user.</p>
*
* <p><em><b>Important note:</b>
* This function may reduce the default execution duration if the current default execution duration is bigger
* to the new maximum execution duration. In a such case, the default execution duration is set to the
* new maximum execution duration.
* </em></p>
*
* @param duration New maximum execution duration (in milliseconds).
*/
public void setMaxExecutionDuration(final int duration){
// Decrease the default execution duration if it will be bigger than the new maximum execution duration:
if (duration > 0 && (executionDuration[0] <= 0 || duration < executionDuration[0]))
executionDuration[0] = duration;
// Set the new maximum execution duration:
executionDuration[1] = duration;
}
@Override
gmantele
committed
public Iterator<OutputFormat> getOutputFormats(){
return outputFormats.iterator();
}
@Override
gmantele
committed
public OutputFormat getOutputFormat(final String mimeOrAlias){
if (mimeOrAlias == null || mimeOrAlias.trim().isEmpty())
return null;
gmantele
committed
for(OutputFormat f : outputFormats){
if ((f.getMimeType() != null && f.getMimeType().equalsIgnoreCase(mimeOrAlias)) || (f.getShortMimeType() != null && f.getShortMimeType().equalsIgnoreCase(mimeOrAlias)))
return f;
}
return null;
}
gmantele
committed
/**
* <p>Add the given {@link OutputFormat} in the list of output formats supported by the TAP service.</p>
*
* <p><b>Warning:
* No verification is done in order to avoid duplicated output formats in the list.
* NULL objects are merely ignored silently.
* </b></p>
*
* @param newOutputFormat New output format.
*/
gmantele
committed
public void addOutputFormat(final OutputFormat newOutputFormat){
gmantele
committed
if (newOutputFormat != null)
outputFormats.add(newOutputFormat);
}
gmantele
committed
/**
* Remove the specified output format.
*
* @param mimeOrAlias Full or short MIME type of the output format to remove.
*
* @return <i>true</i> if the specified format has been found and successfully removed from the list,
* <i>false</i> otherwise.
*/
public boolean removeOutputFormat(final String mimeOrAlias){
gmantele
committed
OutputFormat of = getOutputFormat(mimeOrAlias);
if (of != null)
return outputFormats.remove(of);
else
return false;
}
@Override
public int[] getOutputLimit(){
return outputLimits;
}
gmantele
committed
/**
* <p>Set the default output limit.</p>
*
* <p>This limit is set by default if the user did not specify one before the execution of his query.</p>
*
* <p><em><b>Important note:</b>
* This function will apply the given output limit only if legal compared to the currently set maximum value.
* In other words, if the given value is less or equals to the current maximum output limit.
* </em></p>
*
* @param limit New default output limit (in number of rows).
*
* @return <i>true</i> if the given output limit has been successfully set, <i>false</i> otherwise.
*/
public boolean setDefaultOutputLimit(final int limit){
if ((outputLimits[1] <= 0) || (limit > 0 && limit <= outputLimits[1])){
outputLimits[0] = limit;
return true;
}else
return false;
}
gmantele
committed
/**
* <p>Set the maximum output limit.</p>
*
* <p>This output limit limits the default output limit and the output limit specified by a user.</p>
*
* <p><em><b>Important note:</b>
* This function may reduce the default output limit if the current default output limit is bigger
* to the new maximum output limit. In a such case, the default output limit is set to the
* new maximum output limit.
* </em></p>
*
* @param limit New maximum output limit (in number of rows).
*/
public void setMaxOutputLimit(final int limit){
// Decrease the default output limit if it will be bigger than the new maximum output limit:
if (limit > 0 && (outputLimits[0] <= 0 || limit < outputLimits[0]))
outputLimits[0] = limit;
// Set the new maximum output limit:
outputLimits[1] = limit;
}
@Override
public final LimitUnit[] getOutputLimitType(){
return new LimitUnit[]{LimitUnit.rows,LimitUnit.rows};
}
@Override
public Collection<String> getCoordinateSystems(){
return lstCoordSys;
}
@Override
public TAPLog getLogger(){
return logger;
}
@Override
gmantele
committed
public TAPFactory getFactory(){
return tapFactory;
}
@Override
gmantele
committed
public UWSFileManager getFileManager(){
return fileManager;
}
@Override
public boolean uploadEnabled(){
return isUploadEnabled;
public void setUploadEnabled(final boolean enabled){
isUploadEnabled = enabled;
}
@Override
public int[] getUploadLimit(){
return uploadLimits;
}
@Override
public LimitUnit[] getUploadLimitType(){
return uploadLimitTypes;
}
gmantele
committed
/**
* Set the unit of the upload limit.
*
* @param type Unit of upload limit (rows or bytes).
*/
public void setUploadLimitType(final LimitUnit type){
if (type != null)
uploadLimitTypes = new LimitUnit[]{type,type};
}
gmantele
committed
/**
* <p>Set the default upload limit.</p>
*
* <p><em><b>Important note:</b>
* This function will apply the given upload limit only if legal compared to the currently set maximum value.
* In other words, if the given value is less or equals to the current maximum upload limit.
* </em></p>
*
* @param limit New default upload limit.
*
* @return <i>true</i> if the given upload limit has been successfully set, <i>false</i> otherwise.
*/
public boolean setDefaultUploadLimit(final int limit){
try{
if ((uploadLimits[1] <= 0) || (limit > 0 && LimitUnit.compare(limit, uploadLimitTypes[0], uploadLimits[1], uploadLimitTypes[1]) <= 0)){
uploadLimits[0] = limit;
return true;
}
}catch(TAPException e){}
return false;
}
gmantele
committed
/**
* <p>Set the maximum upload limit.</p>
*
* <p>This upload limit limits the default upload limit.</p>
*
* <p><em><b>Important note:</b>
* This function may reduce the default upload limit if the current default upload limit is bigger
* to the new maximum upload limit. In a such case, the default upload limit is set to the
* new maximum upload limit.
* </em></p>
*
* @param limit New maximum upload limit.
*/
public void setMaxUploadLimit(final int limit){
try{
gmantele
committed
// Decrease the default output limit if it will be bigger than the new maximum output limit:
if (limit > 0 && (uploadLimits[0] <= 0 || LimitUnit.compare(limit, uploadLimitTypes[1], uploadLimits[0], uploadLimitTypes[0]) < 0))
uploadLimits[0] = limit;
// Set the new maximum output limit:
uploadLimits[1] = limit;
}catch(TAPException e){}
}
@Override
public int getMaxUploadSize(){
return maxUploadSize;
}
gmantele
committed
/**
* <p>Set the maximum size of a VOTable files set that can be uploaded in once.</p>
*
* <p><b>Warning:
* This size can not be negative or 0. If the given value is in this case, nothing will be done
* and <i>false</i> will be returned.
* On the contrary to the other limits, no "unlimited" limit is possible here ; only the
* maximum value can be set (i.e. maximum positive integer value).
* </b></p>
*
* @param maxSize New maximum size (in bytes).
*
* @return <i>true</i> if the size has been successfully set, <i>false</i> otherwise.
*/
public boolean setMaxUploadSize(final int maxSize){
// No "unlimited" value possible there:
if (maxSize <= 0)
return false;
// Otherwise, set the maximum upload file size:
maxUploadSize = maxSize;
return true;
}
@Override
public int getNbMaxAsyncJobs(){
return maxAsyncJobs;
}
@Override
public UserIdentifier getUserIdentifier(){
return userIdentifier;
}
@Override
public TAPMetadata getTAPMetadata(){
return metadata;
}
gmantele
committed
@Override
public Collection<String> getGeometries(){
return geometries;
gmantele
committed
}
@Override
public Collection<FunctionDef> getUDFs(){
gmantele
committed
}
@Override
public int[] getFetchSize(){
return fetchSize;
}