blob: d1d8955991fcfc4b16d2ee5a7b1931664802a368 [file] [log] [blame]
/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/
/* -*-C++-*-
******************************************************************************
*
* File: LmJavaSignature.cpp
* Description: Java Signature
*
* Created: 06/17/2003
* Language: C++
*
*
******************************************************************************
*/
#include "LmParameter.h"
#include "LmJavaType.h"
#include "LmJavaSignature.h"
#include "LmJavaSignatureHelpers.h"
//
// Constructor
//
// This class uses the heap parameter if provided. Other wise
// uses global heap to allocate memory. This is to facilitate
// DDOL code calls into this class. DDOL code does not use any
// classes from /common directory.
//
LmJavaSignature::LmJavaSignature(const char* encodedSignature, void* heap)
: heap_(NULL),
encodedSignature_(NULL),
unpackedSignatureSize_(-1),
numParams_(-1)
{
if (heap != NULL)
heap_ = (NAMemory *) heap;
if (encodedSignature == NULL)
{
encodedSignature_ = NULL;
}
else
{
UInt32 siglen = strlen(encodedSignature);
if (heap_ == NULL)
encodedSignature_ = new char[siglen + 1];
else
encodedSignature_ = new (heap_) char[siglen + 1];
strcpy(encodedSignature_, encodedSignature);
// Compute the numParams_ value
::getUnpackedSignatureSize(encodedSignature_, &numParams_);
}
}
// Destructor
LmJavaSignature::~LmJavaSignature()
{
if (encodedSignature_ != NULL)
{
if (heap_)
NADELETEBASIC(encodedSignature_, heap_);
else
delete encodedSignature_;
}
}
//
// createSig() : Creates a Java signature for the specifed SQL attributes.
// If optionalSig is specified, it contains the string entered in the
// EXTERNAL NAME field of the CREATE PROCEDURE command, and is validated
// in this function. The returned signature is built in the sigBuf parameter.
//
// Returns: LM_OK on success
// LM_ERR on failure
//
LmResult
LmJavaSignature::createSig(ComFSDataType paramType[],
ComUInt32 paramSubType[],
ComColumnDirection direction[],
ComUInt32 numParam,
ComFSDataType resultType,
ComUInt32 resultSubType,
ComUInt32 numResultSets,
const char *optionalSig,
ComBoolean isUdrForJavaMain,
char *sigBuf,
ComUInt32 sigLen,
ComDiagsArea *da)
{
static const char *resultSet = "[Ljava/sql/ResultSet;";
static const Int32 resultSetLen = str_len(resultSet);
ComUInt32 len = 0;
ComUInt32 idx = 0;
ComBoolean lookForTrailingParams = FALSE;
const char *type;
char *optc = NULL, *optsig = NULL, *optype = NULL;
if (optionalSig != NULL)
{
len = (ComUInt32) str_len(optionalSig);
optype = optsig = new (heap_) char[len+1];
str_cpy_all(optsig, optionalSig, (Lng32) len);
optsig[len] = '\0';
if (*optype != '(')
{
// Error: Missing parentheses.
*da << DgSqlCode(-LME_SIGNATURE_INVALID1);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
optype++;
} //if (optionalSig...)
//
// Build the Java signature in the sig buffer.
// Start of method's parameter list.
//
// In this method we check for space in sigBuf everytime
// we write something into it.
//
if (idx + 1 > sigLen)
{
*da << DgSqlCode(-LME_SIGNATURE_INVALID5);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
sigBuf[idx++] = '(';
//
// Special treatment for UDR-MAIN
//
// Check if optional signature is java.lang.String[]
// Then write "[Ljava/lang/String;" to sigBuf
//
if (isUdrForJavaMain)
{
if (optionalSig != NULL)
{
char * endOfOptSig= strchr(optype, ')');
if (endOfOptSig == NULL)
{
// Error: Missing parantheses
*da << DgSqlCode(-LME_SIGNATURE_INVALID1);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
*endOfOptSig = '\0';
optype = strip_spaces(optype);
len = (ComUInt32) str_len(optype);
if (len >= 2)
{
if (optype[len-2] != '[' || optype[len-1] != ']')
{
*da << DgSqlCode(-LME_SIGNATURE_INVALID8);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
else
{
optype[len-2] = '\0';
optype = strip_spaces(optype);
}
}
if (str_cmp_ne(optype, "java.lang.String") != 0)
{
*da << DgSqlCode(-LME_SIGNATURE_INVALID8);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
// Move optype to point to next of ')' in optional signature
optype = endOfOptSig + 1;
}
if (idx + 19 > sigLen)
{
*da << DgSqlCode(-LME_SIGNATURE_INVALID5);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
str_cpy_all(&sigBuf[idx], "[Ljava/lang/String;", 19);
idx += 19;
}
else if (((Int32)numParam == 0) && optype && (numResultSets > 0))
{
lookForTrailingParams = true;
}
else if (((Int32)numParam == 0) && optype && (numResultSets == 0))
{
//
// Case: numParam is 0. '()', '(void)' in optsig are valid
//
optc = strchr(optype, ')');
if (optc == NULL)
{
// Error: Missing parantheses
*da << DgSqlCode(-LME_SIGNATURE_INVALID1);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
*optc = '\0';
optype = strip_spaces(optype);
if ((!* optype) || (str_cmp_ne(optype, "void") == 0))
optype = optc + 1;
else
{
// Case: Params specified in opt sig are more than expected
*da << DgSqlCode(-LME_SIGNATURE_INVALID2)
<< DgInt0((Lng32) numParam);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
} // if ((int)numParam...)
//
// Travel through the parameters. The following steps are performed
// in the 'for' loop.
// 1. For UDr-MAIN, check all types are CHAR/VARCHAR and mode is IN
// 2. Get the type from the optional signature if there is one.
// 3. Enfore '[]' for OUT/INOUT types in optional signature.
// 4. Call getJavaTypeName() to get java name of the type.
// 5. Write the type name into sigBuf
//
for (Int32 i = 1; i <= (Int32)numParam; i++)
{
//
// Special treatment for UDR-MAIN
//
// All the parameters should be IN.
//
// We don't need to check here if the correct type is
// specified in the optional signature. This is already
// done above.
//
// Just check if the parameter is String type. We allow
// only String types to main method.
//
// We don't need to write the type name to sigBuf. We can
// directly write ')' after this 'for' loop
//
if (isUdrForJavaMain)
{
if (direction[i-1] != COM_INPUT_COLUMN)
{
*da << DgSqlCode(-LME_SIGNATURE_INVALID9);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
LmParameter lmParam((paramType[i-1]), (short) paramSubType[i-1]);
LmJavaType jType(&lmParam);
type = jType.getJavaTypeName(len);
if (str_cmp_ne(type, "Ljava/lang/String;") != 0)
{
*da << DgSqlCode(-LME_SIGNATURE_INVALID10);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
continue;
}
if (optionalSig)
{
optc = strchr(optype, ',');
if (optc != NULL)
{
*optc = '\0';
optype = strip_spaces(optype);
if ((i == (Int32)numParam) && (numResultSets == 0))
{
// Case: Params specified in opt sig are more than expected
*da << DgSqlCode(-LME_SIGNATURE_INVALID2)
<< DgInt0((Lng32) numParam);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
lookForTrailingParams = true;
}
else // first if (optc != NULL)
{
optc = strchr(optype, ')');
if (optc != NULL)
{
*optc = '\0';
optype = strip_spaces(optype);
if ((i < (Int32)numParam) || ((numParam ==1)&& !(*optype)))
{
// Case: Params specified in opt sig are less than expected
// Case: sig is () but numParam is 1
*da << DgSqlCode(-LME_SIGNATURE_INVALID2)
<< DgInt0((Lng32) numParam);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
lookForTrailingParams = FALSE;
}
else // second if (optc != NULL)
{
// Error: Missing parentheses.
*da << DgSqlCode(-LME_SIGNATURE_INVALID1);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
} // first if (optc != NULL)
} // if (optionalSig)
// For OUT/INOUT params, [] in optional signature is mandatory.
if (optype)
{
ComUInt32 optlen = (ComUInt32) str_len(optype);
if (direction[i-1] == COM_INOUT_COLUMN ||
direction[i-1] == COM_OUTPUT_COLUMN)
{
if (optlen > 2 && optype[optlen-2] == '[' && optype[optlen-1] == ']')
{
optype[optlen-2] = '\0';
optype = strip_spaces(optype); // Allow spaces btw TYPE and []
}
else
{
// Error: Missing [] for OUT/INOUT param
*da << DgSqlCode(-LME_SIGNATURE_INVALID3)
<< DgInt0(i);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
}
}
//
// Get the Java type for the param's SQL <type,subtype>
// First check if the type is base type. Next check if it
// is Object type. For object types optional type should
// be there.
//
LmParameter lmParam(paramType[i-1], (short) paramSubType[i-1]);
LmJavaType baseType(&lmParam);
LmJavaType::TypeElement *e = baseType.getTypeElement();
if (e != NULL)
{
type = e->javaTypeName;
len = e->javaTypeNameLen;
}
if (e == NULL || (optype && (str_cmp_ne(e->javaText, optype) != 0)))
{
// User wants the object type. So look for Object type
// in type table only if optional signature is specified
if (optype)
{
lmParam.setObjMapping();
LmJavaType objType(&lmParam);
if ((e = objType.getTypeElement()) != NULL)
{
type = e->javaTypeName;
len = e->javaTypeNameLen;
}
}
}
if (e == NULL || (optype && (str_cmp_ne(e->javaText, optype) != 0)))
{
// Error: Unknown parameter type used.
*da << DgSqlCode(-LME_SIGNATURE_INVALID4)
<< DgInt0(i);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
// Out mode params are specified using an array for the given type.
if (direction[i-1] == COM_INOUT_COLUMN ||
direction[i-1] == COM_OUTPUT_COLUMN)
{
if ((idx + 1) > sigLen)
{
*da << DgSqlCode(-LME_SIGNATURE_INVALID5);
if (optsig != NULL) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
sigBuf[idx++] = '[';
}
if ((idx + len) > sigLen)
{
*da << DgSqlCode(-LME_SIGNATURE_INVALID5);
if (optsig != NULL) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
// Add the Java type to the sig buffer.
str_cpy_all(&sigBuf[idx], type, (Lng32) len);
idx += len;
// move optype to point to next type in optional sig
if (optype) optype = optc + 1;
} // for()
if(lookForTrailingParams)
{
Int32 numTrailingParams = 0;
while(true)
{
numTrailingParams++;
optc = strchr(optype, ',');
if (optc != NULL)
{
*optc = '\0';
optype = strip_spaces(optype); // Allow spaces btw TYPE and comma
ComUInt32 optlen = (ComUInt32) str_len(optype);
if (optlen > 2 && optype[optlen-2] == '[' && optype[optlen-1] == ']')
{
optype[optlen-2] = '\0';
optype = strip_spaces(optype); // Allow spaces btw TYPE and []
if (str_cmp_ne(optype, "java.sql.ResultSet") == 0)
{
// Ensure buffer accomodates ResultSet
if (idx + resultSetLen > sigLen)
{
*da << DgSqlCode(-LME_SIGNATURE_INVALID5);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
str_cpy_all(&sigBuf[idx], resultSet, resultSetLen);
idx += resultSetLen;
// move optype to point to next type in optional sig
if (optype) optype = optc + 1;
}
else
{
//Error: Not a java.sql.ResultSet[]
*da << DgSqlCode(-LME_SIGNATURE_INVALID11)
<< DgInt0((Lng32)numParam + numTrailingParams);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
}
else
{
// Error: Not a java.sql.ResultSet[]
*da << DgSqlCode(-LME_SIGNATURE_INVALID11)
<< DgInt0((Lng32)numParam + numTrailingParams);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
}
else
{
optc = strchr(optype, ')');
if (optc != NULL)
{
*optc = '\0';
optype = strip_spaces(optype); // Allow spaces btw TYPE and comma
ComUInt32 optlen = (ComUInt32) str_len(optype);
if (optlen > 2 && optype[optlen-2] == '[' && optype[optlen-1] == ']')
{
optype[optlen-2] = '\0';
optype = strip_spaces(optype); // Allow spaces btw TYPE and []
if (str_cmp_ne(optype, "java.sql.ResultSet") == 0)
{
// Ensure buffer accomodates ResultSet
if (idx + resultSetLen > sigLen)
{
*da << DgSqlCode(-LME_SIGNATURE_INVALID5);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
str_cpy_all(&sigBuf[idx], resultSet, resultSetLen);
idx += resultSetLen;
// move optype to point to next type in optional sig
if (optype) optype = optc + 1;
break;
}
else
{
//Error: not a java.sql.ResultSet[]
*da << DgSqlCode(-LME_SIGNATURE_INVALID11)
<< DgInt0((Lng32)numParam + numTrailingParams);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
}
else
{
// Error: not a java.sql.ResultSet[]
*da << DgSqlCode(-LME_SIGNATURE_INVALID11)
<< DgInt0((Lng32)numParam + numTrailingParams);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
}
else
{
// Error: Missing parentheses.
*da << DgSqlCode(-LME_SIGNATURE_INVALID1);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
}//end else
}//end while
}//end if lookForTrailingPrams
if ((idx + 1) > sigLen)
{
*da << DgSqlCode(-LME_SIGNATURE_INVALID5);
if (optsig != NULL) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
for(int i = 0; i < numResultSets; i++)
{
if (idx + resultSetLen > sigLen)
{
*da << DgSqlCode(-LME_SIGNATURE_INVALID5);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
str_cpy_all(&sigBuf[idx], resultSet, resultSetLen);
idx += resultSetLen;
}
// End of method's parameter list.
sigBuf[idx++] = ')';
//
// Now write the signature element for Return type
//
// If optional sig, ensure no return type is specified.
if ((optsig != NULL) && (*optype))
{
*da << DgSqlCode(-LME_SIGNATURE_INVALID6);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
// Get the Java type for the return type's SQL <type,subtype>.
LmParameter lmParam(resultType, (short) resultSubType);
LmJavaType jType(&lmParam);
type = jType.getJavaTypeName(len);
if (type == NULL)
{
// Error: Unknown or unsupported type used as a return type.
*da << DgSqlCode(-LME_SIGNATURE_INVALID7);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
// Ensure buffer accomodates return type and '\0'.
if ((idx + len + 1) > sigLen)
{
*da << DgSqlCode(-LME_SIGNATURE_INVALID5);
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_ERR;
}
// Add the method's return type to the sig Buffer.
str_cpy_all(&sigBuf[idx], type, (Lng32) len);
sigBuf[idx+len] = '\0';
if (optsig) NADELETEBASIC(optsig, heap_);
return LM_OK;
}
//
// unpackSignature(): Unpacks a Java signature.
// Callers has to call getUnpackedSignatureSize() first and then allocate
// so many bytes before calling unpackSignature().
//
// Example: For procedure proc(IN int, IN NUMERIC (9,3), INOUT char(50)),
// packed signature is (ILjava/math/BigDecimal;[Ljava/lang/String;)V
// unpacked signature is (int,java.math.BigDecimal,java.lang.String[])
//
// Note: This method does not do extensive error checking. For example,
// there is no checks for improper placement of '(', '[' etc. We assume
// that this method is called with proper unpackedSignature, that was
// generated by us.
//
Int32
LmJavaSignature::unpackSignature(char *unpackedSignature)
{
return ::unpackSignature(encodedSignature_, unpackedSignature);
}
//
// getUnpackedSignatureSize() : Calculates the bytes required if
// the given (Java) signture is unpacked.
// returns size of unpacked signature string
// -1 if unrecognized type is in signature
//
Int32
LmJavaSignature::getUnpackedSignatureSize()
{
if (unpackedSignatureSize_ == -1)
unpackedSignatureSize_ = ::getUnpackedSignatureSize(encodedSignature_);
return unpackedSignatureSize_;
}