An example message store adapter

This example creates an adapter for use as an interface to a message store. It uses the standard Java™ i/o classes to manipulate files in the store.

This example is not meant as a replacement for the adapters that are supplied with MQe, but rather as a simple introduction to creating a message store adapter.

A new class file is constructed, inheriting from MQeAdapter. Some variables are defined to hold this adapter's instance information, such as the name of the file/message and the location of the message store.

The MQeAdapter constructor is used for the object, so no additional code needs to be added for the constructor.
public class MyMsgStoreAdapter extends    MQeAdapter
                               implements FilenameFilter
  {
  protected String  filter   = "";              
  /* file type filter    */
  protected String  fileName = "";              
  /* disk file name      */
  protected String  filePath = "";              
  /* drive and directory */
  protected boolean reading  = false;           
/* opened for reading  */
  protected boolean writing  = false;           
Because this adapter implements FilenameFilter, the following method must be coded. This is the filtering mechanism that is used to select files of a certain type within the message store.
  public boolean accept( File dir, String name ) 
    {
    return( name.endsWith( filter ));
    }

Next the activate method is coded. This is the method that extracts, from the file descriptor, the name of the directory to be used to hold all the messages.

The Object parameter on the method call may be an attribute object. If it is, this is the attribute that is used to encode or decode the messages in the message store.

The Object options for this adapter are:
  • MQe_Adapter_READ
  • MQe_Adapter_WRITE
  • MQe_Adapter_UPDATE
Any other options should be ignored.
public void   activate( String  fileDesc,
                       Object  param,
                       Object  options,
                       int     value1,
                       int     value2 ) throws Exception
    {
    super.activate( fileDesc, param, options, lrecl, noRec );
    filePath    = fileId.substring( fileId.indexOf( ':' ) + 1 );
    String Temp = filePath;                     
  /* copy the path data  */
    if ( filePath.endsWith( File.separator ) )  
  /* ending separator ?  */
      Temp      = Temp.substring( 0, Temp.length( ) - 
                                  File.separator.length( ) );
    else
      filePath  = filePath + File.separator;    
  /* add separator       */
    File diskFile = new File( Temp );
    if ( ! diskFile.isDirectory( ) )            
  /* directory ?         */
      if ( ! diskFile.mkdirs( ) )               
  /* does mkDirs work ?  */
        throw new MQeException( MQe.Except_NotAllowed,
                          "mkdirs '" + filePath + "' failed" );
    filePath = diskFile.getAbsolutePath( ) + File.separator;
    this.open( null );
    }
The close method disallows reading or writing.
public void close( Object opt ) throws Exception 
    {
    reading  = false;                           
/* not open for reading*/
    writing  = false;                           
/* not open for writing*/
    }
The control method needs to be coded to handle an MQe_Adapter_LIST that is, a request to list all the files in the directory that satisfy the filter. Also to handle an MQe_Adapter_FILTER that is a request to set a filter to control how the files are listed.
public Object control( Object opt, Object ctrlObj ) throws Exception
    {
    if ( checkOption( opt, MQe.MQe_Adapter_LIST   ) )
      return( new File( filePath ).list( this ) );
    else
    if ( checkOption( opt, MQe.MQe_Adapter_FILTER ) )
      {
      filter = (String) ctrlObj;                
  /* set the filter      */
      return( null );                           
  /* nothing to return   */
      }
    else
    return( super.control( opt, ctrlObj ) );    
  /* try ancestor        */
    }
The erase method is used to remove a message from the message store.
  public void erase( Object opt ) throws Exception 
    {
    if ( opt instanceof String )                
  /* select file ?       */
      {
      String FN = (String) opt;                 
  /* re-type the option  */
      if ( FN.indexOf( File.separator ) > -1 )  
  /* directory ?         */
        throw new MQeException( MQe.Except_Syntax,
              "Not allowed" );
      if ( ! new File( filePath + FN ).delete( ) )
        throw new MQeException( MQe.Except_NotAllowed,
              "Erase failed" );
      }
    else
      throw new MQeException( MQe.Except_NotSupported,
              "Not supported" );
    }
The open method sets the Boolean values that permit either reading of messages or writing of messages.
public void open( Object opt ) throws Exception 
    {
    this.close( null );                         
  /* close any open file */
    fileName = null;                            
  /* clear the filename  */
    if ( opt instanceof String )                
  /* select new file ?   */
      fileName = (String) opt;                  
  /* retype the name     */
    reading  = checkOption( opt, MQe.MQe_Adapter_READ   ) ||
               checkOption( opt, MQe.MQe_Adapter_UPDATE );
    writing  = checkOption( opt, MQe.MQe_Adapter_WRITE  ) ||
               checkOption( opt, MQe.MQe_Adapter_UPDATE );
    }
The readObject method reads a message from the message store and recreates an object of the correct type. It also decrypts and decompresses the data if an attribute is supplied on the activate call. This is a special function in that a request to read a file that satisfies the matching criteria specified in the parameter of the read, returns the first message it encounters that satisfies the match.
public Object readObject( Object opt ) throws Exception 
    {
    if ( reading )
      {
      if ( opt instanceof MQeFields )
        {
        /* 1. list all files in the directory */
        /* 2. read each file in turn and restore as a Fields object */
        /* 3. try an equality check - if equal then return that object */
        String List[] = new File( filePath ).list( this );
        MQeFields Fields = null;
        for ( int i = 0; i < List.length; i = i + 1 )
          try
            {
            fileName = List[i];                 
      /* remember the name   */
            open( fileName );                   
      /* try this file       */
            Fields = (MQeFields) readObject( null );
            if ( Fields.equals( (MQeFields) opt ) )     
      /* match ?     */
              return( Fields );
            }
          catch ( Exception e )                 
      /* error occured       */
            {
            }                                   
      /* ignore error        */
        throw new MQeException( Except_NotFound, "No match" );
        }
      /* read the bytes from disk   */
      File diskFile = new File( filePath + fileName );
      byte data[] = new byte[(int) diskFile.length()];
      FileInputStream InputFile = new FileInputStream( diskFile );
      InputFile.read( data );              /* read the file data  */
      InputFile.close( );                  /* finish with file    */
      /* possible Attribute decode of the data       */
      if ( parameter instanceof MQeAttribute )  
    /* Attribute encoding ?*/
        data = ((MQeAttribute) parameter).decodeData( null,
                                                      data,
                                                      0,
                                                      data.length );
      MQeFields FieldsObject = MQeFields.reMake( data, null );
      return( FieldsObject );
      }
    else
      throw new MQeException( MQe.Except_NotSupported,
              "Not supported" );
    }
The status method returns status information about the adapter. In this examples it can return the filter type or the file name.
public String status( Object  opt  ) throws Exception
    {
    if ( checkOption( opt, MQe.MQe_Adapter_FILTER   ) )
      return( filter   );
    if ( checkOption( opt, MQe.MQe_Adapter_FILENAME ) )
      return( fileName );
    return( super.status( opt ) );
    }
The writeObject method writes a message to the message store. It compresses and encrypts the message object if an attribute is supplied on the activate method call.
public void writeObject( Object  opt,
                           Object  data ) throws Exception 
    {
    if ( writing && (data instanceof MQeFields) )
      {
      byte dump[] = ((MQeFields) data).dump( );         
  /* dump object */
      /* possible Attribute encode of the data                         */
      if ( parameter instanceof MQeAttribute )
        dump = ((MQeAttribute) parameter).encodeData( null,
                                                      dump,
                                                      0,
                                                      dump.length );
      /* write out the object bytes                                    */
      File diskFile = new File( filePath + fileName );
      FileOutputStream OutputFile = new FileOutputStream( diskFile );
      OutputFile.write( dump );                 /* write the data      */
      OutputFile.getFD().sync( );               /* synchronize disk    */
      OutputFile.close();                       /* finish with file    */
      }
    else
      throw new MQeException( MQe.Except_NotSupported, "Not supported" );
    }

This is now a complete (though very simple) message store adapter that reads and writes message objects to a message store.

Variations of this adapter could be coded for example to store messages in a database or in nonvolatile memory.


Terms of use | WebSphere software

(c) Copyright IBM Corporation 2004, 2005. All rights reserved.