/********************************************************************/ /* */ /* Program name: JSMQPUT based on sample AMQSPUT0 */ /* */ /* Description: Sample C program that puts messages to */ /* a message queue. Message contains RFH2 header */ /* */ /* (c) Copyright IBM Corp. 2002 All rights reserved. */ /* */ /* This sample program is owned by International Business Machines */ /* Corporation or one of its subsidiaries ("IBM") and is copyrighted*/ /* and licensed, not sold. */ /* */ /* The sample program is provided to you on an "AS IS" basis, */ /* without warranty of any kind. IBM HEREBY EXPRESSLY DISCLAIMS */ /* ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND */ /* FITNESS FOR A PARTICULAR PURPOSE. */ /* Some jurisdictions do not allow for the exclusion or limitation */ /* of implied warranties, so the above limitations or exclusions */ /* may not apply to you. IBM shall not be liable for any damages */ /* you suffer as result of using, modifying or distributing the */ /* sample program or its derivatives. */ /* */ /********************************************************************/ /* */ /* Function: */ /* */ /* JSMQPUT is a sample C program to put messages on a message */ /* queue in the format similar to messages generated by an */ /* MQ Java/JMS application. These messages can be retrieved */ /* by an MQ JMS application using message selectors. */ /* All messages contain variable MQRFH2 header. The variable */ /* portion contains and optionally and folders. */ /* The folder is hardcoded to contain the jms text message */ /* type designation (jms_text). */ /* The program prompts user to enter property name and property */ /* value pairs for both and folders. */ /* The folder contains JMS header fields and JMSX properties*/ /* The folder properties and their allowed values are listed*/ /* in the "Using Java" manual. */ /* The folder contains application defined properties whose */ /* name/value pairs are dynamically obtained from the input file. */ /* The text of a message (i.e. message body) comes also from */ /* the input file. */ /* */ /* -- messages are sent to the queue named by the parameter */ /* */ /* -- prompts and gets lines from StdIn for the and */ /* folders property name/value pairs and a message text. */ /* Property name and value pairs are placed in the */ /* and folders of an RFH2. */ /* -- RFH2 header is generated and a message text (body) is */ /* appended. Thus constructed message is put on a queue */ /* -- program stops when null line or EOF is read */ /* */ /* -- issues a message for each MQI reason other than */ /* MQRC_NONE; stops if there is a MQI completion code */ /* of MQCC_FAILED */ /* */ /* Program logic: */ /* MQOPEN target queue for OUTPUT */ /* while end of input file not reached, */ /* . prompt and read line of text */ /* . generate RFH2 and message body */ /* . MQPUT datagram message with RFH2 */ /* MQCLOSE target queue */ /* */ /* */ /********************************************************************/ /* */ /* JSMQPUT has 2 parameters */ /* - the name of the target queue (required) */ /* - queue manager name (optional) */ /* */ /********************************************************************/ #include #include #include /* includes for MQI */ #include void getProperties(char *folder, char *prop_data, int max_prop_len, FILE *fp); int main(int argc, char **argv) { /* Declare file and character for sample input */ FILE *fp; /* Declare MQI structures needed */ MQOD od = {MQOD_DEFAULT}; /* Object Descriptor */ MQMD md = {MQMD_DEFAULT}; /* Message Descriptor */ MQPMO pmo = {MQPMO_DEFAULT}; /* put message options */ MQRFH2 rfh2= {MQRFH2_DEFAULT}; /* MQRFH2 header */ MQHCONN Hcon; /* connection handle */ MQHOBJ Hobj; /* object handle */ MQLONG O_options; /* MQOPEN options */ MQLONG C_options; /* MQCLOSE options */ MQLONG CompCode; /* completion code */ MQLONG OpenCode; /* MQOPEN completion code */ MQLONG Reason; /* reason code */ MQLONG CReason; /* reason code for MQCONN */ MQLONG mq_messlen; /* MQ message length */ char QMName[50]; /* queue manager name */ char mcd_data[100]; /* folder area */ char jms_data[1020]; /* folder area */ char usr_data[1020]; /* folder area */ char prop_data[1000]; char msg_data[1000]; /* message body area */ struct MQRFH2 *rfh2_ptr; MQLONG mcd_len; MQLONG usr_len; MQLONG msg_len; MQLONG jms_len; MQLONG bufflen; MQLONG rfh2_len; char *mq_mess_ptr; char *wrk_ptr; printf("JSMQPUT started\n"); if (argc < 2) { printf("Required parameter missing - queue name\n"); exit(99); } /******************************************************************/ /* */ /* Connect to queue manager */ /* */ /******************************************************************/ QMName[0] = 0; /* default */ if (argc > 2) strcpy(QMName, argv[2]); MQCONN(QMName, /* queue manager */ &Hcon, /* connection handle */ &CompCode, /* completion code */ &CReason); /* reason code */ /* report reason and stop if it failed */ if (CompCode == MQCC_FAILED) { printf("MQCONN ended with reason code %ld\n", CReason); exit( (int)CReason ); } /******************************************************************/ /* */ /* Use parameter as the name of the target queue */ /* */ /******************************************************************/ strncpy(od.ObjectName, argv[1], (size_t)MQ_Q_NAME_LENGTH); printf("target queue is %s\n", od.ObjectName); /******************************************************************/ /* */ /* Open the target message queue for output */ /* */ /******************************************************************/ O_options = MQOO_OUTPUT /* open queue for output */ + MQOO_FAIL_IF_QUIESCING; /* but not if MQM stopping */ MQOPEN(Hcon, /* connection handle */ &od, /* object descriptor for queue */ O_options, /* open options */ &Hobj, /* object handle */ &OpenCode, /* MQOPEN completion code */ &Reason); /* reason code */ /* report reason, if any; stop if failed */ if (Reason != MQRC_NONE) { printf("MQOPEN ended with reason code %ld\n", Reason); } if (OpenCode == MQCC_FAILED) { printf("unable to open queue for output\n"); } /******************************************************************/ /* */ /* Read property value/pairs for and folders */ /* */ /* Create rfh2 header with the variable portion containing a */ /* , and folders. */ /* An folder is hardcoded to specify one Msd property with*/ /* value of "jms_text" (text message format) */ /* */ /* Add sample msg text data and PUT message to a queue. */ /* Loop until no more user's input or end of file, */ /* or there is a failure */ /* */ /******************************************************************/ CompCode = OpenCode; /* use MQOPEN result for initial test */ fp = stdin; memcpy(md.Format, MQFMT_RF_HEADER_2, (size_t)MQ_FORMAT_LENGTH); while (CompCode != MQCC_FAILED) { jms_data[0] = '\0'; usr_data[0] = '\0'; /* get jms related properties */ getProperties( "jms", prop_data, sizeof(prop_data), fp ); if ( strlen(prop_data) > 0 ) { /* anything was entered? */ /* yes, create folder */ strcat(jms_data, ""); strcat(jms_data, prop_data ); strcat(jms_data, "" ); } else { /* no, add Dst property (not required)*/ strcat(jms_data, ""); strcat(jms_data, "queue:///"); strcat(jms_data, od.ObjectName ); strcat(jms_data, "" ); strcat(jms_data, "" ); } /* get user defined properties */ getProperties( "usr", prop_data, sizeof(prop_data), fp ); if ( strlen(prop_data) > 0 ) { /* anything was entered? */ /* yes, create folder */ strcat(usr_data, ""); strcat(usr_data, prop_data ); strcat(usr_data, "" ); } /* create mcd folder with the msg type set to jms_text */ strcpy(mcd_data, "jms_text"); /* get message text */ printf("\nEnter text for the message body: "); if (fgets(msg_data, sizeof(msg_data), fp) != NULL) { bufflen = strlen(msg_data); /* length without null */ if (msg_data[bufflen-1] == '\n') { /* last char is a new-line */ msg_data[bufflen-1] = '\0'; /* replace new-line with null */ } } else msg_data[0] = '\0'; /* treat EOF same as null line */ /* determine folder length and round it up to multiple of 4 */ usr_len = ((strlen(usr_data)-1)/4)*4 + 4 ; mcd_len = ((strlen(mcd_data)-1)/4)*4 + 4 ; jms_len = ((strlen(jms_data)-1)/4)*4 + 4 ; /* determine message body length */ msg_len = strlen(msg_data); printf("\n length = %ld",mcd_len); printf("\n length = %ld",jms_len); printf("\n length = %ld",usr_len); printf("\nmsg body length = %ld",msg_len); /********************************************************************/ /* Build MQ message with the variable RFH2 header */ /********************************************************************/ /* calculate total mq message length. /* if optional folders exist, account for the length field(s) */ mq_messlen = sizeof(MQRFH2) + mcd_len + usr_len + jms_len + msg_len + sizeof(mcd_len); if ( jms_len > 0 ) mq_messlen = mq_messlen + sizeof(jms_len); if ( usr_len > 0 ) mq_messlen = mq_messlen + sizeof(usr_len); /* allocate storage for the mq message using calculated length */ mq_mess_ptr = malloc(mq_messlen); /* for the mq message */ /* init storage to ' ' */ memset(mq_mess_ptr, ' ', mq_messlen); wrk_ptr = mq_mess_ptr+sizeof(MQRFH2); /* point past fixed RFH2 */ memcpy(wrk_ptr, &mcd_len, sizeof(mcd_len));/* insert length of mcd */ wrk_ptr = wrk_ptr + sizeof(mcd_len); /* point past length */ memcpy(wrk_ptr, mcd_data, strlen(mcd_data)); /* insert mcd folder */ wrk_ptr = wrk_ptr + mcd_len; /* point past mcd */ if ( jms_len > 0 ) { /* is there jms data? */ /* yes, add jms folder */ memcpy(wrk_ptr, &jms_len, sizeof(jms_len));/* insert length of jms */ wrk_ptr = wrk_ptr + sizeof(jms_len); /* point past length */ memcpy(wrk_ptr, jms_data, strlen(jms_data));/* insert jms folder */ wrk_ptr = wrk_ptr + jms_len; /* point past jms */ } if ( usr_len > 0 ) { /* is there usr data? */ /* yes, add usr folder */ memcpy(wrk_ptr, &usr_len, sizeof(usr_len));/* insert length of usr */ wrk_ptr = wrk_ptr + sizeof(usr_len); /* point past length */ memcpy(wrk_ptr, usr_data, strlen(usr_data));/* insert usr folder */ wrk_ptr = wrk_ptr + usr_len; /* point past usr */ } memcpy(wrk_ptr, msg_data, strlen(msg_data));/* insert message body */ /* calculate rfh2 length (fixed + variable portions ) */ rfh2_len = wrk_ptr - mq_mess_ptr; /* set the rfh2 length (fixed+variable) */ rfh2.StrucLength = rfh2_len; /* store length into rfh2 field */ /* set the rfh2 format for the message data (body) */ memcpy(rfh2.Format, MQFMT_STRING, (size_t)MQ_FORMAT_LENGTH); /* insert fixed rfh2 into the mq message area (at the beginning) */ memcpy(mq_mess_ptr, &rfh2, sizeof(MQRFH2)); /****************************************************************/ /* */ /* Put MQ message from the message buffer (mq_mess_ptr) */ /* */ /****************************************************************/ if (strlen(msg_data) > 0) { memcpy(md.MsgId, /* reset MsgId to get a new one */ MQMI_NONE, sizeof(md.MsgId) ); memcpy(md.CorrelId, /* reset CorrelId to get a new one */ MQCI_NONE, sizeof(md.CorrelId) ); printf("\nissuing MQPUT msg with:\n"); printf("\njms properties:\n%s\n", jms_data); printf("\nuser properties:\n%s\n", usr_data); MQPUT(Hcon, /* connection handle */ Hobj, /* object handle */ &md, /* message descriptor */ &pmo, /* default options (datagram) */ mq_messlen, /* message length */ mq_mess_ptr, /* message buffer */ &CompCode, /* completion code */ &Reason); /* reason code */ /* report reason, if any */ if (Reason != MQRC_NONE) { printf("\nMQPUT ended with reason code %ld\n", Reason); } } else { /* satisfy end condition when empty line is read */ CompCode = MQCC_FAILED; printf("\nThe message text was not entered. MQPUT not issued.\n"); } (void)free(mq_mess_ptr); } /******************************************************************/ /* */ /* Close the target queue (if it was opened) */ /* */ /******************************************************************/ if (OpenCode != MQCC_FAILED) { C_options = 0; /* no close options */ MQCLOSE(Hcon, /* connection handle */ &Hobj, /* object handle */ C_options, &CompCode, /* completion code */ &Reason); /* reason code */ /* report reason, if any */ if (Reason != MQRC_NONE) { printf("MQCLOSE ended with reason code %ld\n", Reason); } } /******************************************************************/ /* */ /* Disconnect from MQM if not already connected */ /* */ /******************************************************************/ if (CReason != MQRC_ALREADY_CONNECTED) { MQDISC(&Hcon, /* connection handle */ &CompCode, /* completion code */ &Reason); /* reason code */ /* report reason, if any */ if (Reason != MQRC_NONE) { printf("MQDISC ended with reason code %ld\n", Reason); } } printf("JSMQPUT ended\n"); return(0); } /*******************************************************************************/ /* */ /* getProperties function : */ /* */ /* Loops, prompting a user to enter property name and property value for */ /* a given folder. */ /* Reads entered values and concatenates them into xml-like property data */ /* string. */ /* Stops processing and returns to caller if an empty (null) property name */ /* is received or the concatenated string length exceeds max. size. */ /* */ /*******************************************************************************/ void getProperties(char *folder_name, char *prop_data, int prop_len, FILE *fp) { char prop_name[400]; char prop_value[400]; int more_props = 1; MQLONG bufflen; prop_name[0] = '\0'; prop_data[0] = '\0'; while ( more_props ) { printf("\nEnter <%s> property name: ", folder_name); /* get property name */ if (fgets(prop_name, sizeof(prop_name), fp) != NULL) { bufflen = strlen(prop_name); /* length without null */ if (prop_name[bufflen-1] == '\n') { /* last char is a new-line */ prop_name[bufflen-1] = '\0'; /* replace new-line with null */ } } else prop_name[0] = '\0'; /* treat EOF same as null line */ if ( (more_props = strlen(prop_name)) > 0 ) { /* get property value */ printf("\nEnter value for property <%s>: ", prop_name); if (fgets(prop_value, sizeof(prop_value), fp) != NULL) { bufflen = strlen(prop_value); /* length without null */ if (prop_value[bufflen-1] == '\n') { /* last char is a new-line */ prop_value[bufflen-1] = '\0'; /* replace new-line with null */ } } else prop_value[0] = '\0'; /* treat EOF same as null line */ /* check if there is enough space in prop_data to add new name/value pairs */ if ( strlen(prop_data)+strlen(prop_name)+strlen(prop_value)+5 <= prop_len ) { strcat(prop_data, "<"); strcat(prop_data, prop_name); strcat(prop_data, ">" ); strcat(prop_data, prop_value); strcat(prop_data, "" ); } /* prop_data length exceeded... */ else { printf("\nPre-allocated folder size of %ld exceeded.\nNo more properties for this folder can be added.", prop_len); return; } } } return; }