17static json_value* navigateToArrayElement(json_value* jsonValue,
int index);
18static json_value* navigateToObjectElement(json_value* jsonValue,
const char* name);
19static json_value* processArrayReference(json_value* jsonValue,
const char* arrayRef);
20static Value getNamedValueImpl(JNIEnv* env,
Arguments arguments,
char* name,
bool forArray);
21static bool isOnlyNumbers(
char*
string);
37 const struct dsc$descriptor_s* name,
38 const long int* dbinit,
39 const struct msginit* msginit,
40 const long int* query,
50vmsstat_t
init(
const char* processName,
bool initMessageServices)
52 const struct msginit msg_init_s = { 1,
56 $DESCRIPTOR (PROCESS_NAME, processName);
59 initMessageServices ? &msg_init_s : NULL,
60 &((
long)(FALSE)), &((
long)(FALSE)));
92void aidaThrow(JNIEnv* env, vmsstat_t status,
char* exception,
const char* message)
95 if ((*env)->ExceptionCheck(env)) {
96 (*env)->ExceptionClear(env);
99 char vmsErrorMessage[BUFSIZ] = {
'\0' };
100 $DESCRIPTOR(MESSAGE, vmsErrorMessage);
101 struct dsc$descriptor errorMessageDescriptor = { BUFSIZ, DSC$K_DTYPE_T, DSC$K_CLASS_S, (
char*)&vmsErrorMessage };
104 if (!SUCCESS(status)) {
105 ERRTRANSLATE(&status, &errorMessageDescriptor);
106 strncat(errorMessageDescriptor.dsc$a_pointer,
"; ",
107 MIN(strlen(
"; "), BUFSIZ - strlen(errorMessageDescriptor.dsc$a_pointer)));
111 strncat(errorMessageDescriptor.dsc$a_pointer, exception,
112 MIN(strlen(exception), BUFSIZ - strlen(errorMessageDescriptor.dsc$a_pointer)));
116 strncat(errorMessageDescriptor.dsc$a_pointer,
"; ",
117 MIN(strlen(
"; "), BUFSIZ - strlen(errorMessageDescriptor.dsc$a_pointer)));
118 strncat(errorMessageDescriptor.dsc$a_pointer, message,
119 MIN(strlen(message), BUFSIZ - strlen(errorMessageDescriptor.dsc$a_pointer)));
122 fprintf(stderr,
"AIDA Exception: %s: %s\n", exception, errorMessageDescriptor.dsc$a_pointer);
125 char classToCreate[BUFSIZ] =
"edu/stanford/slac/except/";
126 strcat (classToCreate, exception);
129 jclass exceptionClass;
130 exceptionClass = (*env)->FindClass(env, classToCreate);
131 if (!exceptionClass) {
132 fprintf(stderr,
"FATAL: Failed to create object of class: %s\n", classToCreate);
138 (*env)->ThrowNew(env, exceptionClass, errorMessageDescriptor.dsc$a_pointer);
150 if (!str || !suffix) {
153 size_t lenstr = strlen(str);
154 size_t lenSuffix = strlen(suffix);
155 if (lenSuffix > lenstr)
157 return !strncasecmp(str + lenstr - lenSuffix, suffix, lenSuffix);
168 if (!str || !prefix) {
171 size_t lenstr = strlen(str);
172 size_t lenPrefix = strlen(prefix);
173 if (lenPrefix > lenstr)
175 return !strncasecmp(str, prefix, lenPrefix);
187 memset(&noArgument, 0,
sizeof(
Argument));
191 if (!strcasecmp(argument.
name, name)) {
192 if (strlen(argument.
value) > 0) {
213static Value getNamedValueImpl(JNIEnv* env,
Arguments arguments,
char* name,
bool forArray)
219 if (valueArgument.
name && valueArgument.
value) {
221 char* valueToParse = valueArgument.
value;
222 while (isspace(*valueToParse)) {
229 char arrayValueToParse[strlen(valueToParse) + 30];
231 if (*valueToParse ==
'[') {
232 sprintf(arrayValueToParse,
"{\"_array\": %s}", valueToParse);
233 valueToParse = arrayValueToParse;
234 }
else if (forArray) {
235 if (strstr(valueToParse,
"\"") != NULL) {
237 "Unable to parse supplied JSON value string");
239 }
else if (isOnlyNumbers(valueToParse)) {
240 sprintf(arrayValueToParse,
"{\"_array\": [%s]}", valueToParse);
242 sprintf(arrayValueToParse,
"{\"_array\": [\"%s\"]}", valueToParse);
244 valueToParse = arrayValueToParse;
248 if (*valueToParse ==
'{') {
249 value.
value.
jsonValue = json_parse(valueToParse, strlen(valueToParse));
254 "Unable to parse supplied JSON value string");
270static bool isOnlyNumbers(
char*
string)
272 if (
string == NULL) {
275 bool isInNumber =
true;
276 bool afterComma =
false;
277 bool hasDecimalPoint =
false;
278 int len = (int)strlen(
string);
279 for (
int i = 0; i < len; i++) {
281 if (isdigit(
string[i])) {
285 hasDecimalPoint =
false;
289 }
else if (
string[i] ==
'.') {
291 if (!hasDecimalPoint && isInNumber) {
292 hasDecimalPoint =
true;
295 }
else if (
string[i] ==
',') {
302 }
else if (isspace(
string[i])) {
304 if (afterComma || isInNumber) {
324 return getNamedValueImpl(env, arguments, name,
false);
337 return getNamedValueImpl(env, arguments, name,
true);
356 if (!passedInPath || strlen(passedInPath) == 0) {
361 char path[strlen(passedInPath) + 1];
362 strcpy(path, passedInPath);
369 char* token = strtok(path,
".");
374 jsonValue = processArrayReference(jsonValue, token);
375 }
else if ((arrayRef = strstr(token,
"["))) {
377 len = (int)(arrayRef - token);
378 strncpy(name, token, len);
380 jsonValue = navigateToObjectElement(jsonValue, name);
382 jsonValue = processArrayReference(jsonValue, arrayRef);
385 jsonValue = navigateToObjectElement(jsonValue, token);
389 token = strtok(NULL,
".");
406 if (jsonValue->type == json_object && jsonValue->u.object.length == 1
407 && strcmp(jsonValue->u.object.values[0].name,
"_array") == 0) {
408 jsonValue = jsonValue->u.object.values[0].value;
420static json_value* processArrayReference(json_value* jsonValue,
const char* arrayRef)
423 int count = sscanf(arrayRef,
"[%d][%d][%d][%d]", &index[0], &index[1], &index[2], &index[3]);
426 jsonValue = navigateToArrayElement(jsonValue, index[--count]);
437static json_value* navigateToObjectElement(json_value* jsonValue,
const char* name)
439 if (jsonValue->type == json_object) {
440 for (
int i = 0; i < jsonValue->u.object.length; i++) {
441 if (strcasecmp(name, jsonValue->u.object.values[i].name) == 0) {
442 jsonValue = jsonValue->u.object.values[i].value;
455static json_value* navigateToArrayElement(json_value* jsonValue,
int index)
457 if (jsonValue->type == json_array) {
458 if (jsonValue->u.array.length > index) {
459 jsonValue = jsonValue->u.array.values[index];
474 strcpy(groupName, uri);
475 char* groupNameEnd = strrchr(groupName,
':');
491 char uriCopy[strlen(uri) + 1];
492 strcpy(uriCopy, uri);
493 char* secondary = strrchr(uriCopy,
':');
495 memcpy(secn, secondary + 1,
sizeof(int4u));
498 fprintf(stderr,
"Warning: Found corrupt URI when trying to extract secn: %s\n", uri);
509 char* secondary = strrchr(uri,
':');
511 fprintf(stderr,
"Warning: Secondary not found in uri: %s\n", uri);
514 return secondary + 1;
525 unsigned long pmuEnd = strrchr(uri,
':') - uri;
529 strncpy(pmuString, uri, pmuEnd);
530 pmuString[pmuEnd] = 0x0;
545 char* nextPart = strtok(device,
":");
548 len = strlen(nextPart);
553 memcpy(primary, nextPart,
PRIM_LEN);
554 nextPart = strtok(NULL,
":");
556 len = strlen(nextPart);
557 if (len != 4 || !isdigit(nextPart[2]) || !isdigit(nextPart[3])) {
562 nextPart = strtok(NULL,
":");
564 len = strlen(nextPart);
565 if (len < 1 || len > 4 || !isdigit(nextPart[0]) || (len > 1 && !isdigit(nextPart[1]))
566 || (len > 2 && !isdigit(nextPart[2])) || (len > 3 && !isdigit(nextPart[3]))) {
570 *unit = (int4u)atol(nextPart);
585 char* separator = strrchr(uri,
':');
587 memcpy(slcName, uri, separator - uri);
588 memcpy(slcName + (separator - uri),
".", 1);
589 strcpy(slcName + (separator - uri) + 1, separator + 1);
601 char* firstSeparator = strchr(uri,
':');
602 char* secondSeparator = strchr(firstSeparator + 1,
':');
603 char* lastSeparator = strrchr(uri,
':');
605 if (lastSeparator == secondSeparator) {
607 memcpy(legacyName, uri, firstSeparator - uri);
608 memcpy(legacyName + (firstSeparator - uri),
"//", 2);
609 strcpy(legacyName + (firstSeparator - uri) + 2, firstSeparator + 1);
612 memcpy(legacyName, uri, lastSeparator - uri);
613 memcpy(legacyName + (lastSeparator - uri),
"//", 2);
614 strcpy(legacyName + (lastSeparator - uri) + 2, lastSeparator + 1);
629void*
allocateMemory(JNIEnv* env,
void* source,
size_t size,
bool nullTerminate,
char* message)
631 void* data = malloc(size);
637 memcpy(data, source, size - (nullTerminate ? 1 : 0));
639 *(
char*)((
char*)data + size - 1) = 0x0;
#define AIDA_INTERNAL_EXCEPTION
Use this string to signal Internal Exceptions in aidaThrow()
#define UNABLE_TO_GET_DATA_EXCEPTION
Use this string to signal Exceptions when trying to Get Data in aidaThrow()
Value getNamedArrayValue(JNIEnv *env, Arguments arguments, char *name)
Get value from a named argument in the provided arguments structure.
int startsWith(const char *str, char *prefix)
Check if a string starts with another string.
void pmuStringFromUri(char *pmuString, const char *uri)
Get the pmu part of a URI.
const char * secondaryFromUri(const char *uri)
Get secondary from URI.
int groupNameFromUri(char groupName[], const char *uri)
Get the Display group name from a URI.
void secnFromUri(const char *uri, int4u *secn)
Get secondary from pseudo secondary (containing a colon) number from URI e.g.
int endsWith(const char *str, char *suffix)
Check if a string str, ends with another string suffix.
void aidaThrow(JNIEnv *env, vmsstat_t status, char *exception, const char *message)
To log any exceptions and throw back to java.
unsigned long int STANDALONE_INIT(const struct dsc$descriptor_s *name, const long int *dbinit, const struct msginit *msginit, const long int *query, const long int *set)
standalone init is used to initialise standalone processes
vmsstat_t init(const char *processName, bool initMessageServices)
Call standalone_init()
void * allocateMemory(JNIEnv *env, void *source, size_t size, bool nullTerminate, char *message)
Allocate memory and copy the source to it if specified.
json_value * getJsonValue(Value *value, char *passedInPath)
Get the json value from the given value identified by the path.
Argument getArgument(Arguments arguments, char *name)
Get a named argument.
Value getNamedValue(JNIEnv *env, Arguments arguments, char *name)
Get value from a named argument in the provided arguments structure.
json_value * getJsonRoot(json_value *jsonValue)
void uriLegacyName(char legacyName[MAX_URI_LEN], const char *uri)
Convert the given URI to the legacy AIDA name for low level functions that still require it that way.
void aidaThrowNonOsException(JNIEnv *env, char *exception, const char *message)
To log any non-OS exceptions and throw back to java.
void uriToSlcName(char slcName[MAX_URI_LEN], const char *uri)
Convert all URIs to slac names before making queries.
int pmuFromDeviceName(JNIEnv *env, char *device, char *primary, char *micro, int4u *unit)
Get primary, micro and unit from a device name.
The Header File for the Native Channel Provider Server Helper functions.
@ AIDA_JSON_TYPE
Argument was provided as JSON text.
@ AIDA_STRING_TYPE
Represents a string.
@ AIDA_NO_TYPE
Used to indicate that no type was provided as an argument.
#define PRIM_LEN
The length of the primary part of a PMU string.
#define MAX_URI_LEN
The maximum length of a URI.
#define MICRO_LEN
The length of the micro part of a PMU string.
A single request argument.
char * value
The string value of the argument.
char * name
The name of the argument.
An Arguments structure stores all of the arguments passed from the request to the Native Channel Prov...
int argumentCount
The number of arguments sent with this request.
Argument * arguments
The array of Arguments.
This special type represents a Value.
ValueContents value
The value's contents, either a string or parsed json.
Type type
AIDA_STRING_TYPE or AIDA_JSON_TYPE.
json_value * jsonValue
The parsed json_value of this Value if the type is AIDA_JSON_TYPE.
char * stringValue
The string value of this Value if the type is AIDA_STRING_TYPE.