package SMDTest.conf;
import java.util.*;
public class AccessTimeRange {
public Vector TimeList; // must be Date
public Vector TimeRangeList; // must be DTimeRange public native int GetTimeRangeList(String DBPath, String DBEnv,
String NoteID, String FieldName); public native int SetTimeRangeList(String DBPath, String DBEnv,
String NoteID, String FieldName); static { System.loadLibrary("AccessTimeRange");
}
}运行时调用GetTimeRangeList 报Java.lang.UnsstisfiedLinkError这个异常,
程序是应该找到这个dll的,不知道为什么会出现这个问题。
import java.util.*;
public class AccessTimeRange {
public Vector TimeList; // must be Date
public Vector TimeRangeList; // must be DTimeRange public native int GetTimeRangeList(String DBPath, String DBEnv,
String NoteID, String FieldName); public native int SetTimeRangeList(String DBPath, String DBEnv,
String NoteID, String FieldName); static { System.loadLibrary("AccessTimeRange");
}
}运行时调用GetTimeRangeList 报Java.lang.UnsstisfiedLinkError这个异常,
程序是应该找到这个dll的,不知道为什么会出现这个问题。
Exception in thread "Thread-0" java.lang.UnsatisfiedLinkError: SMDTest.conf.AccessTimeRange.GetTimeRangeList(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I
at SMDTest.conf.AccessTimeRange.GetTimeRangeList(Native Method)
at SMDTest.conf.AutoSchedule.Enable(AutoSchedule.java:96)
at SMDTest.conf.DBAction.SC_ActionTriggerandWait(DBAction.java:891)
at SMDTest.SMDTest.triggerScanAction(SMDTest.java:1227)
at SMDTest.SMDTest.testDB(SMDTest.java:1125)
at SMDTest.SMDTest.run(SMDTest.java:183)
at lotus.domino.NotesThread.run(Unknown Source)
并且放在了目录下面
是否是debug的?
//include basic header files
#include "jni.h"
#include "SMDTest_conf_AccessTimeRange.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
//include Notes head files
#include "global.h"
#include "nsfdata.h"
#include "names.h"
#include "nsfnote.h"
#include "osfile.h"
#include "nsfdb.h"
#include "misc.h"
#include "pool.h"
#include "osmem.h"
#include "ostime.h"
//in Note.DLL, NoteID should be DWord
/*convert TimeDate to Java's Date and save into Vector of timeList
Can't directly convert TIMEDATE to Java Date
struct tagTIMEDATE {
DWORD Innards[2];
} TIMEDATE;
TIMEDATE->SimpleDateFormat->JavaDate
*/static jobject ConvTimeDatetoJavaDate(JNIEnv *env, FILE *logfile, TIMEDATE pTimeDate){
TIME far *tempTime;
char TimeStr[50];
char TempStr[20];
char TempDPattern[50];
jclass DateCls=NULL;
jclass SDFCls=NULL;
jclass PrsPosCLS=NULL;
jobject jPrsPosObj;
jobject jTempDate;
jmethodID jmCreatDateID,jmCreatePrsPosID;
jmethodID jmCreatSDFID,jmParsID;
jstring jDPattern,jDateStr;
jobject jSDFObj;
// MessageBox(NULL, "Debug2", "Debug2", MB_OK); //DEBUG POINT
tempTime=malloc(sizeof(TIME));
tempTime->GM=pTimeDate;
if (TimeGMToLocal(tempTime)){
fprintf(logfile,"Error number %d, can't convert Time.GM to LocalTime\n", 6);
}
//convert TIME to String that Java can accept.
/*
typedef struct {
int year; // 1-32767 omit
int month; // 1-12 omit
int day; // 1-31 omit
int weekday; // 1-7, Sunday is 1 omit
int hour; // 0-23 enable
int minute; // 0-59 enable
int second; // 0-59 enable
int hundredth; // 0-99
int dst; // FALSE or TRUE
int zone; // -11 to +11
TIMEDATE GM;
} TIME;
*/
//construct "yyyy-MM-dd HH:mm:ss" String
TimeStr[0]='\0';
if (tempTime->year!=-1){
_itoa( tempTime->year, TempStr, 10 );
fprintf(logfile,"year:%s\n",TempStr);
strncat(TimeStr,TempStr, strlen(TempStr)+1);
}
if (tempTime->month!=-1){
_itoa( tempTime->month, TempStr, 10 );
fprintf(logfile,"month:%s\n",TempStr);
strcat(TimeStr,"/");
strncat(TimeStr,TempStr,strlen(TempStr)+1);
}
if (tempTime->day!=-1){
_itoa( tempTime->day, TempStr, 10);
fprintf(logfile,"day:%s\n",TempStr);
strcat(TimeStr,"/");
strncat(TimeStr,TempStr,strlen(TempStr)+1);
strcat(TimeStr," ");
}
_itoa( tempTime->hour, TempStr, 10);
fprintf(logfile,"hour:%s\n",TempStr);
strncat(TimeStr,TempStr,strlen(TempStr)+1);
strcat(TimeStr,":");
_itoa( tempTime->minute, TempStr, 10);
fprintf(logfile,"minute:%s\n",TempStr);
strncat(TimeStr,TempStr,strlen(TempStr)+1);
strcat(TimeStr,":");
_itoa( tempTime->second, TempStr, 10);
fprintf(logfile,"second:%s\n",TempStr);
strncat(TimeStr,TempStr,strlen(TempStr)+1);
fprintf(logfile,"Zone:%d\n",tempTime->zone);
fprintf(logfile,"Date String:%s \n",TimeStr);
fclose(logfile);
logfile=fopen( "DateAccessLog.txt", "a+" );
//Convert TimeStr into jTempDate***********
DateCls=(*env)->FindClass(env, "java/util/Date");
if (DateCls == NULL) {
fprintf(logfile,"Error: can't find DateCls");
}
// fclose(logfile);
// logfile=fopen( "DateAccessLog.txt", "a+" );
jmCreatDateID=(*env)->GetMethodID(env, DateCls, "<init>", "()V");
if (jmCreatDateID == NULL) {
fprintf(logfile,"Error: can't find jmCreatDateID");
}
jTempDate= (*env)->NewObject(env, DateCls, jmCreatDateID);
(*env)->DeleteLocalRef(env, DateCls);
SDFCls=(*env)->FindClass(env, "java/text/SimpleDateFormat");
if (SDFCls == NULL) {
fprintf(logfile,"Error: can't find SDFCls");
}
// fclose(logfile);
// logfile=fopen( "DateAccessLog.txt", "a+" );
jmCreatSDFID=(*env)->GetMethodID(env, SDFCls, "<init>", "(Ljava/lang/String;)V");
if (jmCreatSDFID == NULL) {
fprintf(logfile,"Error: can't find jmCreatSDFID");
}
fflush(logfile);
//Convert Char* to jString
TempDPattern[0]='\0';
strncpy(TempDPattern, "yyyy/MM/dd HH:mm:ss", 50);
else
strncpy(TempDPattern, "HH:mm:ss", 50);
free(tempTime);
jDPattern=(*env)->NewStringUTF(env,TempDPattern);
jSDFObj= (*env)->NewObject(env, SDFCls, jmCreatSDFID,jDPattern);
jDateStr= (*env)->NewStringUTF(env,TimeStr);
jmParsID=(*env)->GetMethodID(env, SDFCls, "parse", "(Ljava/lang/String;Ljava/text/ParsePosition;)Ljava/util/Date;");
PrsPosCLS=(*env)->FindClass(env, "java/text/ParsePosition");
if (PrsPosCLS == NULL) {
fprintf(logfile,"Error: can't find PrsPosCLS");
}
fflush(logfile);
jmCreatePrsPosID=(*env)->GetMethodID(env, PrsPosCLS, "<init>", "(I)V");
if (jmCreatePrsPosID == NULL) {
fprintf(logfile,"Error: can't find jmCreatePrsPosID");
}
jPrsPosObj=(*env)->NewObject(env,PrsPosCLS,jmCreatePrsPosID,0);
jTempDate=(*env)->CallObjectMethod(env, jSDFObj,jmParsID,jDateStr,jPrsPosObj);
(*env)->DeleteLocalRef(env, PrsPosCLS);
(*env)->DeleteLocalRef(env, SDFCls);
fflush(logfile);
return jTempDate;
}JNIEXPORT jint JNICALL Java_AccessTimeRange_GetTimeRangeList
(JNIEnv *env, jobject ATR_Obj, jstring DBPath, jstring DBEnv, jstring NoteID, jstring FieldName)
{
int ret=-1;//correct return value
int i,j;
STATUS error;
DWORD Block_len;
FILE *logfile;
BYTE *pvoidItemValue;
RANGE *pRange;
TIMEDATE *pTimeDate;
//TIMEDATE SingleTimeDate;
TIMEDATE LTimePoint,UTimePoint;
TIMEDATE_PAIR *pTimeDatePair;
int TPCount,RGCount;
char far *fullpath_name=malloc((size_t)MAXPATH);//fullpath, need header file: names.h
//note related type
DBHANDLE db_handle;
NOTEHANDLE note_handle;
NOTEID dwNoteID;
BLOCKID value_bid;
WORD TR_datatype=TYPE_TIME_RANGE;
//END note related type
jobject jVTimeList,jVTimePairList;
jobject jTempDate,jDTimeRange,jStartDate,jEndDate;
jmethodID jmCreatDTimeRID,jmSetBegDTimeRID,jmSetEndDTimeRID;
jmethodID jmVaddID;
jboolean jAddOK;
jfieldID fid1,fid2;
jclass ATRcls;
jclass DTimeRCls;
jclass VectCls;
char far *strDBEnv, *strDBPath;
char far *strNoteID, *strFieldName;
// MessageBox(NULL, "Debug1", "Debug1", MB_OK); //DEBUG POINT
//Open Log File
if ((logfile=fopen( "DateAccessLog.txt", "a+" )) == NULL )
return 1;
fprintf(logfile,"call_Java_AccessTimeRange_GetTimeRangeList\n");
//found Fields
ATRcls = (*env)->GetObjectClass(env, ATR_Obj);
fid1 = (*env)->GetFieldID(env, ATRcls, "TimeList", "Ljava/util/Vector;");
if (fid1 == NULL) {
fprintf(logfile,"Error: can't access field1");
ret=-2;
goto OUT0;
}
jVTimeList = (*env)->GetObjectField(env, ATR_Obj, fid1);
fid2 = (*env)->GetFieldID(env, ATRcls, "TimeRangeList", "Ljava/util/Vector;");
if (fid1 == NULL) {
fprintf(logfile,"Error: can't access field2");
ret=-2;
goto OUT0;
}
jVTimePairList = (*env)->GetObjectField(env, ATR_Obj, fid2);
//get databaseHandle by DBPath and DBEnv
strDBEnv=(char far *)(*env)->GetStringUTFChars(env, DBEnv, NULL);
strDBPath=(char far *)(*env)->GetStringUTFChars(env, DBPath, NULL);
if (strlen(strDBEnv))
{
if (error = OSPathNetConstruct(NULL, strDBEnv, strDBPath, fullpath_name)) //need osfile.h
{
fprintf(logfile,"Error number is %d, can't generate OSPath\n", error);
ret=2;
goto OUT0;
}
}
else{
strcpy(fullpath_name, strDBPath);
fprintf(logfile, "fullPath_name:%s\n",fullpath_name);
}
fflush(logfile);
if (error = NSFDbOpen(fullpath_name, &db_handle)) //need nsfdb.h
{
fprintf(logfile,"Error number is %d, can't open DB\n", error);
ret=3;
goto OUT0;
}
(*env)->ReleaseStringUTFChars(env, DBEnv, strDBEnv);
(*env)->ReleaseStringUTFChars(env, DBPath, strDBPath);
free(fullpath_name);
//get NoteHandle by NoteID
strNoteID=(char far *)(*env)->GetStringUTFChars(env, NoteID, NULL);
//dwNoteID=atoi(strNoteID);
sscanf(strNoteID, "%lx", &dwNoteID);
fprintf(logfile,"Successfully open DB, and NoteID is %lX\n", dwNoteID);
// fclose(logfile);
// if ((logfile=fopen( "DateAccessLog.txt", "a+" )) == NULL )
// return 1;
if (error = NSFNoteOpen(db_handle, dwNoteID, 0, ¬e_handle)) //need nsfnote.h
{
fprintf(logfile,"Error number is %d, can't open Note\n", error);
ret=4;
goto OUT0;
}
(*env)->ReleaseStringUTFChars(env, NoteID, strNoteID);
fprintf(logfile,"successfully open the Note\n");
fflush(logfile);
//get Item info
strFieldName=(char far *)(*env)->GetStringUTFChars(env, FieldName, NULL);
error=NSFItemInfo(note_handle,
strFieldName,
(WORD)strlen(strFieldName),
NULL,
&TR_datatype,
&value_bid,
&Block_len);
if (error!=NOERROR){
fprintf(logfile,"Error number is %d, can't get ItemInfo\n", error);
ret= 5;
goto OUT0;
}
fprintf(logfile,"successfully get ItemInfo of the Note\n");
fflush(logfile); /*WORD far *value_datatype,
BLOCKID far *value_blockid,
DWORD far *value_len*/
(*env)->ReleaseStringUTFChars(env, FieldName, strFieldName);
if (TR_datatype!=TYPE_TIME&&TR_datatype!=TYPE_TIME_RANGE){
fprintf(logfile,"not a time related Item!\n");
ret= 6;
goto OUT0;
}
//else is TYPE_TIME_RANGE
//locate ItemInfoblock
pvoidItemValue = OSLockBlock(BYTE,value_bid);
pvoidItemValue += sizeof(WORD);
fprintf(logfile,"step over Data-type-word\n");
if (TR_datatype==TYPE_TIME){
pTimeDate = (TIMEDATE*)pvoidItemValue;
jTempDate=ConvTimeDatetoJavaDate(env, logfile, *pTimeDate);
VectCls=(*env)->FindClass(env, "java/util/Vector");
jmVaddID = (*env)->GetMethodID(env, VectCls, "add", "(Ljava/lang/Object;)Z");
jAddOK=(*env)->CallBooleanMethod(env,jVTimeList,jmVaddID,jTempDate);
if (!jAddOK)
fprintf(logfile,"Error:can't add jTempDate to jVTimeList!\n");
else
fprintf(logfile,"successfully add jTempDate to jVTimeList\n");
fflush(logfile);
ret=0;
goto OUT1;
}
pRange=(RANGE*)pvoidItemValue;
TPCount=pRange->ListEntries;
fprintf(logfile,"TPCount:%d\n",TPCount);
RGCount=pRange->RangeEntries;
fprintf(logfile,"RGCount:%d\n",RGCount);
fflush(logfile);
//create TimeList instance from InfoBlock
pRange++;
//pRange += sizeof(WORD);
pTimeDate = (TIMEDATE*)pRange;
VectCls=(*env)->FindClass(env, "java/util/Vector");
jmVaddID = (*env)->GetMethodID(env, VectCls, "add", "(Ljava/lang/Object;)Z");
fprintf(logfile,"Finish preparation before extract TIMEDATE \n");
for (i=0;i<TPCount;i++){
jTempDate=ConvTimeDatetoJavaDate(env, logfile, pTimeDate[i]);
fprintf(logfile,"extract TIMEDATE one:%d\n",i);
//assigned TempDate into TimeList of AccessTimeRange Class
jAddOK=(*env)->CallBooleanMethod(env,jVTimeList,jmVaddID,jTempDate);
if (!jAddOK){
fprintf(logfile,"Error:can't add jTempDate to jVTimeList!\n");
goto OUT1;
}else{
fprintf(logfile,"successfully add jTempDate to jVTimeList\n");
}
}
//create TimeRangeList Instance from InfoBlock
pTimeDatePair=(TIMEDATE_PAIR *)&(pTimeDate[TPCount]);
fprintf(logfile,"Finish preparation before extract TIMEDATE_PAIR \n");
for (j=0;j<RGCount;j++){
//convert TimeDate_pair to custom-define DTimeRange and save into TimeRangeList
/*typedef struct {
TIMEDATE Lower;
TIMEDATE Upper;
} TIMEDATE_PAIR;*/
LTimePoint=pTimeDatePair[j].Lower;
UTimePoint=pTimeDatePair[j].Upper;
fprintf(logfile,"success get LTimePoint and UTimePoint-%d \n",j);
//get Java_StartDate and Java_EndDate
jStartDate=ConvTimeDatetoJavaDate(env, logfile, LTimePoint);
jEndDate=ConvTimeDatetoJavaDate(env, logfile, UTimePoint);
//construct jDTimeRange Object
DTimeRCls=(*env)->FindClass(env, "DTimeRange");
if (DTimeRCls==NULL)
fprintf(logfile,"can't get DTimeRCls\n");
jmCreatDTimeRID=(*env)->GetMethodID(env, DTimeRCls, "<init>", "()V");
if (jmCreatDTimeRID == NULL) {
fprintf(logfile,"Error: can't find jmCreatDTimeRID");
goto OUT1;
}
fprintf(logfile,"Start construct jDTimeRange Object \n");
jDTimeRange=(*env)->NewObject(env, DTimeRCls, jmCreatDTimeRID);
jmSetBegDTimeRID=(*env)->GetMethodID(env, DTimeRCls, "SetBeginTime", "(Ljava/util/Date;)V");
(*env)->CallVoidMethod(env,jDTimeRange,jmSetBegDTimeRID,jStartDate);
jmSetEndDTimeRID=(*env)->GetMethodID(env, DTimeRCls, "SetEndTime", "(Ljava/util/Date;)V");
(*env)->CallVoidMethod(env,jDTimeRange,jmSetEndDTimeRID,jEndDate);
fprintf(logfile,"End construct jDTimeRange Object \n");
//add jDTimeRange object into TimeRangeList
jAddOK=(*env)->CallBooleanMethod(env,jVTimePairList,jmVaddID,jDTimeRange);
if (!jAddOK){
fprintf(logfile,"Error:can't add jDTimeRange to jVTimePairList!\n");
goto OUT1;
}else{
fprintf(logfile,"successfully add jDTimeRange to jVTimePairList\n");
}
fflush(logfile);
}
//free blockID
ret=0;
OUT1 : OSUnlockBlock(value_bid);
OUT0 : if (fclose(logfile)!=0)
ret=-1;
return ret;
}static TIMEDATE ConvJavaDatetoTimeDate(JNIEnv *env, FILE *logfile, jobject jDateTime, jmethodID *jmDateEleIDArr)
{
int Year,Month,Day,Hour,Min,Sec,Weekday;
int Zone,DST;
int i;
int MethodIDValid=1;
TIMEDATE retTimeDate;
TIME far *tempTime;
int DateInvalid=0;
int TimeInvalid=0;// MessageBox(NULL, "Debug4", "Debug4", MB_OK);//debug point
tempTime=malloc(sizeof(TIME));
for (i=0;i<6;i++){
if (jmDateEleIDArr[i]==NULL) {
MethodIDValid=0;
break;
}
}
if (MethodIDValid==1) {
fprintf(logfile,"MethodID is valid\n");
Year=(*env)->CallIntMethod(env, jDateTime,jmDateEleIDArr[0]);
Year+=1900;
if (Year<0||DateInvalid) {
Year=-1;
DateInvalid=1;
}
Month=(*env)->CallIntMethod(env, jDateTime,jmDateEleIDArr[1]);
Month+=1;
if (Month<0||DateInvalid) {
Month=-1;
DateInvalid=1;
}
Day=(*env)->CallIntMethod(env, jDateTime,jmDateEleIDArr[2]);
if (Day<0||DateInvalid) {
Day=-1;
DateInvalid=1;
}
Hour=(*env)->CallIntMethod(env, jDateTime,jmDateEleIDArr[3]);
if (Hour<0||TimeInvalid) {
Hour=-1;
TimeInvalid=1;
}
Min=(*env)->CallIntMethod(env, jDateTime,jmDateEleIDArr[4]);
if (Min<0||TimeInvalid) {
Min=-1;
TimeInvalid=1;
}
Sec=(*env)->CallIntMethod(env, jDateTime,jmDateEleIDArr[5]);
if (Sec<0||TimeInvalid) {
Sec=-1;
TimeInvalid=1;
}
Weekday=(*env)->CallIntMethod(env, jDateTime,jmDateEleIDArr[6]);
if (Weekday<0||DateInvalid) {
Weekday=-1;
DateInvalid=1;
}
OSCurrentTimeZone((int far *)&Zone,(int far *)&DST);
fprintf(logfile,"yyyy/mm/dd HH:MM:ss Zone|DST--- %d/%d/%d %d:%d:%d %d|%d\n",Year,Month,Day,Hour,Min,Sec,Zone,DST);
fflush(logfile);
if (Year==1970&&Month==1&&Day==1) {
tempTime->year=-1;
tempTime->month = -1;
tempTime->day = -1;
tempTime->zone = 0;
} else {
tempTime->year =Year;
tempTime->month = Month;
tempTime->day = Day;
tempTime->zone = Zone;
}
tempTime->hour =Hour;
tempTime->minute =Min;
tempTime->second =Sec;
tempTime->dst =DST ;
tempTime->weekday =Weekday;
tempTime->hundredth=0;
if (TimeLocalToGM(tempTime))
fprintf(logfile,"Error number %d, can't convert Localtime to GM\n", 6);
retTimeDate=tempTime->GM;
}
else {
fprintf(logfile,"Error:MethodID is not valid\n");
retTimeDate.Innards[0]=0;
retTimeDate.Innards[1]=0;
}
free(tempTime);
fflush(logfile);
return retTimeDate;
}JNIEXPORT jint JNICALL Java_AccessTimeRange_SetTimeRangeList
(JNIEnv *env, jobject ATR_Obj, jstring DBPath, jstring DBEnv, jstring NoteID, jstring FieldName)
{
int ret=-1;//correct return value
int i,j;
char far *strDBEnv, *strDBPath;
char far *strNoteID, *strFieldName;
char far *fullpath_name=malloc((size_t)MAXPATH);//fullpath, need header file: names.h
FILE *logfile;
int TPCount,RGCount;
//Note variable
STATUS error;
DBHANDLE db_handle;
NOTEHANDLE note_handle;
NOTEID dwNoteID;
void far *pvoidItemValue;
TIMEDATE *pTimeDate;
TIMEDATE singleTimeDate;
TIMEDATE_PAIR *pTimeDatePair;
RANGE *pRange;
DWORD dwValueLen;
//JNI variable
jclass ATRcls, VectCls,DateCls,DTRCls;
jfieldID fid1,fid2;
jobject jVTimeList,jVTimePairList,jDateTime,jDateTimeRange,jStartDate, jEndDate;
jmethodID jmVectSizeID,jmVectelemAtID,jmGetStartTimeID,jmGetEndTimeID;
jmethodID jmDateEleIDArr[7];
for (i=0;i<7;i++) {
jmDateEleIDArr[i]=NULL;
}
//Open Log File// MessageBox(NULL, "Debug3", "Debug3", MB_OK);//debug point if ((logfile=fopen( "DateAccessLog.txt", "a+" )) == NULL )
return 1;
fprintf(logfile,"call_Java_AccessTimeRange_SetTimeRangeList\n");
//found Fields
ATRcls = (*env)->GetObjectClass(env, ATR_Obj);
fid1 = (*env)->GetFieldID(env, ATRcls, "TimeList", "Ljava/util/Vector;");
if (fid1 == NULL) {
fprintf(logfile,"Error: can't access field1");
ret=-2;
goto OUT0;
}
jVTimeList = (*env)->GetObjectField(env, ATR_Obj, fid1);
fid2 = (*env)->GetFieldID(env, ATRcls, "TimeRangeList", "Ljava/util/Vector;");
if (fid1 == NULL) {
fprintf(logfile,"Error: can't access field2");
ret=-2;
goto OUT0;
}
jVTimePairList = (*env)->GetObjectField(env, ATR_Obj, fid2);
//get databaseHandle by DBPath and DBEnv
strDBEnv=(char far *)(*env)->GetStringUTFChars(env, DBEnv, NULL);
strDBPath=(char far *)(*env)->GetStringUTFChars(env, DBPath, NULL);
if (strlen(strDBEnv))
{
if (error = OSPathNetConstruct(NULL, strDBEnv, strDBPath, fullpath_name)) //need osfile.h
{
fprintf(logfile,"Error number is %d, can't generate OSPath\n", error);
ret=2;
goto OUT0;
}
}
else{
strcpy(fullpath_name, strDBPath);
fprintf(logfile, "fullPath_name:%s\n",fullpath_name);
}
fflush(logfile);
if (error = NSFDbOpen(fullpath_name, &db_handle)) //need nsfdb.h
{
fprintf(logfile,"Error number is %d, can't open DB\n", error);
ret=3;
goto OUT0;
}