/**
 * @author  srangan.in
 * @version 1.0

 *
 * Development Environment        :  JDeveloper 2.0
 * Name of the Application        :  sqljLOBSample.java
 * Creation/Modification History  :
 *
 *    srangan.in       10-JAN-1998      Created

 *
 * Overview of Application        :
 *
 * This sample illustrates access and manipulation of CLOB and BLOB columns
 * using SQLJ.
 *
 * The sample illustrates the above operations on CLOB and BLOB columns in the

 * AIRPORT_LOB_DETAILS table. It inserts sample .gif and .txt file contents,
 * into the LOB columns for the chosen airport. If LOB data already exists for
 * the chosen airport, it retrieves and displays them. It also
 * illustrates manipulation of LOB columns, by allowing users to enter text to
 * be appended to the CLOB column.
 *
 */


// SQLJ runtime classes
import sqlj.runtime.*;
import sqlj.runtime.ref.*;

import java.io.*;
import java.sql.*; //Package for JDBC classes

//Package for Oracle Extensions to JDBC
import oracle.sql.*;

import oracle.jdbc.driver.*;

// Iterator to retrieve airport records
#sql iterator AirportIter (String code, String description, String city);

// Iterator to retrieve LOB details for an airport. This is a Positional
// iterator declaration
#sql iterator AirportLobIter (BLOB, CLOB);

public class sqljLOBSample {


  DefaultContext m_ctx;     //Database Connection Context
  sqljLOBFrame m_GUI;  // The GUI handler for the sample

  // Sample file names
  static final String s_MapFileName = "map.gif";
  static final String s_SugBookFileName = "suggestionbook.txt";

  /**
  *  Constructor. Initializes GUI
  **/

  public sqljLOBSample() {
    try {
      m_GUI = new sqljLOBFrame(this);
    } catch (Exception ex) {
      m_GUI.putStatus("Error in GUI initialization\n"+ex.toString());
    }
  }

  /**
  *  Main entry point for the class. Instantiates the root frame,
  *  sets up the database connection and populates the JTable with AIRPORTS rows
  **/

  public static void main(String[] args) {
    sqljLOBSample lobs = new sqljLOBSample(); // Instantiate root frame
    lobs.m_GUI.setVisible(true);
    lobs.dbConnection();          // Setup db connection
    if (lobs.m_ctx != null)
      lobs.populateAirports();        // Populate the JTable with all airports rows
  }

  /**
  *  Dispatches the GUI events to the appropriate method, which performs
  *  the required JDBC operations. This method is invoked when event occurs
  *  in the GUI (like table Selection, Button clicks etc.).
  **/

  public void dispatchEvent (String p_eventName) {

    //Dispatch Event
    if (p_eventName.equals("Load Sample Files"))
       loadSamples(m_GUI.getSelectedCode());
    else if (p_eventName.equals("Add Suggestions")) {
       String l_suggestions = m_GUI.getSuggestionText();
       if (!l_suggestions.equals("CANCEL")) {
         addSuggestions(m_GUI.getSelectedCode(),l_suggestions);
         m_GUI.m_sugArea.append(new String(l_suggestions));
       }
    } else if (p_eventName.equals("Airport Selected in Table"))
       airportSelected(m_GUI.getSelectedCode());
    else if (p_eventName.equals("EXIT"))

       exitApplication();
  }


  /**
  *  Creates a database connection object using SQLJ. Please substitute the
  *  database connection parameters with appropriate values in
  *  ConnectionParams.java
  **/
  public void dbConnection(){

    try{
      // Load the Oracle JDBC Driver and register it.
      DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());


      m_GUI.putStatus("Trying to connect to the Database");

      // Form the database connect string(TNSNAMES entry) as a name-value pair
      // using the connection parameters as specified in ConnectionParams.java
      String l_dbConnectString =
          "(DESCRIPTION=(ADDRESS=(HOST="+ConnectionParams.s_hostName+")"+
          "(PROTOCOL=tcp)(PORT="+ConnectionParams.s_portNumber+"))"+
          "(CONNECT_DATA=(SID="+ConnectionParams.s_databaseSID+")))";

      // To Connect to the  Oracle database, use an instance of  the
      // DefaultContext class. The syntax of the DefaultContext constructor is
      // DefaultContext(databaseURL,username,password, boolean auto-commit);
      // The databaseURL syntax is as follows:
      //      "jdbc:oracle:<driver>:@<db connection string>"
      // <driver>, can be 'thin' or 'oci8'
      // <db connect string>, is a Net8 name-value, denoting the TNSNAMES entry

      m_ctx = new DefaultContext(
                  "jdbc:oracle:thin:@"+l_dbConnectString,
                  ConnectionParams.s_userName,
                  ConnectionParams.s_password,
                  false);

      // Set the above connection context as the default context for this
      // application
      DefaultContext.setDefaultContext(m_ctx);

      m_GUI.putStatus("Connected to "+ConnectionParams.s_databaseSID+ " as "+
              ConnectionParams.s_userName);
    } catch(Exception ex){ //Trap SQL errors
      m_GUI.putStatus(
             "Error in Connecting to the Database "+'\n'+ex.toString());
    }
  }



  /**
  * Queries all rows from the AIRPORTS table and populates the JTable with
  * the returned rows
  **/
  public void populateAirports() {
    try {
      m_GUI.appendStatus("\nPopulating Airports. Please wait...");

      // Iterator to hold records returned by the query below
      AirportIter l_airportRecs = null;

      // Embedded SQL: This call selects the code, description and city values
      // for all rows in the AIRPORTS table. The set of rows returned by the query is
      // assigned to the iterator declared above.
      #sql l_airportRecs = {SELECT AIRPORT_CODE code, DESCRIPTION, NAME city
                            FROM AIRPORTS, CITIES

                            WHERE CTY_ID = ID};  

      // Loop through the result set and populate JTable with all airports
      while (l_airportRecs.next()) {
          //Retrieve column values for this row
          String l_code = l_airportRecs.code();
          String l_desc = l_airportRecs.description();
          String l_city = l_airportRecs.city();

          m_GUI.addToJTable(l_code, l_desc, l_city); //Insert into Jtable
      }
      l_airportRecs.close(); // Close the statement, which also closes the ResultSet
      m_GUI.putStatus("Connected to database and retrieved all airport rows");
      m_GUI.appendStatus("\nPlease Choose an airport ");
    } catch  (SQLException ex) {  // Trap SQL errors
      m_GUI.putStatus("Error Querying Airports table: \n"+ex.toString());
    }
  }


  /**
  * Creates a new row for the selected airport in AIRPORT_LOB_DETAILS.
  * It then loads the sample files into the LOB columns, using JDBC.
  **/
  void loadSamples(String p_airportCode) {

    try {
      m_GUI.putStatus("Creating row for airport in AIRPORT_LOB_DETAILS.. ");

      // Embedded SQL: This call creates a new row in the AIRPORT_LOB_DETAILS
      // table for the selected airport. The BLOC and CLOB column values
      // are initialized to empty locator values. The BLOB data will be
      // inserted in the calls below.
       #sql {insert into AIRPORT_LOB_DETAILS
            (AIRPORT_CODE,AIRPORT_MAP,AIRPORT_SUG_BOOK)
            values(:p_airportCode , empty_blob() , empty_clob())}; 

      m_GUI.appendStatus("Created.\nLoading <map.gif> into BLOB column for airport...");

      AirportLobIter l_airportLobs = null;

      BLOB l_mapBLOB = null;
      CLOB l_sugBookCLOB = null;

      // Embedded SQL: Call to retrieve the BLOB and CLOB locators
      // for the chosen airport.
      #sql l_airportLobs = {SELECT AIRPORT_MAP,AIRPORT_SUG_BOOK
            FROM AIRPORT_LOB_DETAILS
            WHERE AIRPORT_CODE= :p_airportCode FOR UPDATE}; 

      // Embedded SQL: Retreive the column locators from the positional iterator
      #sql { fetch :l_airportLobs INTO :l_mapBLOB, :l_sugBookCLOB };


      // Write sample file contents to LOB if the above fetch was successful
      if (!l_airportLobs.endFetch()) {

        // Open the sample file as a stream for insertion into the BLOB column
        File l_mapFile = new File(s_MapFileName);
        InputStream l_sampleFileStream=new FileInputStream(l_mapFile);

        // Buffer to hold chunks of data to being written to the BLOB.

        byte[] l_buffer = new byte[10 * 1024];


        long l_nread = 0;   // Number of bytes read
        long l_offset = 1;  // Offset at which to write

        // Read a chunk of data from the sample file input stream, and write the
        // chunk to the BLOB column using dbms_write. Repeat till file has been
        // fully read.
        while ((l_nread= l_sampleFileStream.read(l_buffer)) != -1) {

          // Embedded SQL call to write the data into the BLOB using the dbms_lob
          // server-side package. The parameters are:
          // 1st parameter - BLOB to write
          // 2nd parameter - Number of bytes to write
          // 3rd parameter - Offset from which to write
          // 4th parameter - The buffer in which the data is held
         #sql { call dbms_lob.write(:INOUT l_mapBLOB, :l_nread, :l_offset, :l_buffer) };
          l_offset += l_nread;
        }
        l_sampleFileStream.close();  // Close file streams


        // Load the suggestion book sample file into the CLOB column
        m_GUI.appendStatus("Done\nLoading <suggestionbook.txt> into CLOB column ..");

        // Open the sample file as a stream for insertion into the CLOB column
        File l_sugbookFile = new File(s_SugBookFileName);
        FileReader l_sugFileReader = new FileReader(l_sugbookFile);

        // Buffer to hold chunks of data to being written to the CLOB.
        char[] l_cbuffer = new char[10* 1024];

        l_nread = 0;      // Number of bytes read from file
        l_offset = 1;     // Offset at which to write

        // Read a chunk of data from the sample file input stream, and write the
        // chunk to the CLOB column using dbms_write. Repeat till file has been
        // fully read.
        while ((l_nread= l_sugFileReader.read(l_cbuffer)) != -1) {
          String l_str = new String(l_cbuffer);

          // Embedded SQL call to write the data into the CLOB using the dbms_lob
          // server-side package. The parameters are:
          // 1st parameter - CLOB to write
          // 2nd parameter - Number of bytes to write

          // 3rd parameter - Offset from which to write
          // 4th parameter - The buffer in which the data is held
        #sql { call dbms_lob.write(:INOUT l_sugBookCLOB, :l_nread, :l_offset, :l_str) };
          l_offset += l_nread;
        }
        l_sugFileReader.close();        // Close File stream

        m_GUI.putStatus("Done Loading sample files");

        m_GUI.appendStatus("\nRetrieving and displaying sample files..");
        // Retrieve and display the LOB data just inserted
        drawBLOB(l_mapBLOB,p_airportCode);
        writeCLOB(l_sugBookCLOB,p_airportCode);
        m_GUI.putStatus("Done loading and displaying LOB data");
      }
      // Close the iterator
      l_airportLobs.close();
    } catch (Exception ex) { // Trap SQL errors
      m_GUI.putStatus("Error loading sample files for the selected airport");
      m_GUI.appendStatus("\n"+ex.toString());
    }
  }

  /**

  * Accepts suggestions from an JOptionPane and  appends the entered
  * suggestions to the CLOB column
  **/
  void addSuggestions(String p_airportCode, String p_suggestions) {

    try {
      m_GUI.putStatus("Appending entered suggestions to CLOB column. Please wait...");

      AirportLobIter l_airportLobs = null;
      BLOB l_blob = null;
      CLOB l_clob = null;

      // Embedded SQL: Call to retrieve the BLOB and CLOB locators
      // for the chosen airport.
      #sql l_airportLobs = {SELECT AIRPORT_MAP,AIRPORT_SUG_BOOK
            FROM AIRPORT_LOB_DETAILS
            WHERE AIRPORT_CODE= :p_airportCode FOR UPDATE};  

      // Embedded SQL: fetch the LOB column locators
      #sql { fetch :l_airportLobs INTO :l_blob, :l_clob };

      // If the above fetch was successful, write to CLOB
      if (!l_airportLobs.endFetch()) {

        long l_length = p_suggestions.length(); // Length of data to be appended


        // Get the length of the CLOB data in the column in database
        long l_clobLen;
       #sql l_clobLen = { VALUES(dbms_lob.getlength(:l_clob)) };

        // Embedded SQL: Append the entered suggestions to the end of the CLOB
        // data, using the dbms_lob server side package
       #sql { call dbms_lob.write(:INOUT l_clob, :l_length, :l_clobLen, :p_suggestions) };
        m_GUI.appendStatus("Done");
      }
      l_airportLobs.close(); // Close statement which also closes open result sets
    } catch(SQLException ex) {
        m_GUI.putStatus("Error appending suggestions to the CLOB column");
      m_GUI.appendStatus("\n"+ex.toString());
    }
  }

  /**
  * This method is called when a row is selected from the airport JTable.
  * It checks if there exists data in AIRPORT_LOB_DETAILS for the selected
  * airport. If there exists data, it calls drawBLOB and writeCLOB to
  * display the data
  **/
  void airportSelected(String p_airportCode) {

    try {

      m_GUI.putStatus("Retrieving LOB details for selected airport..");

      AirportLobIter l_airportLobs = null;
      BLOB l_blob = null;
      CLOB l_clob = null;

      // Embedded SQL: Call to retrieve the BLOB and CLOB locators
      // for the chosen airport.
      #sql l_airportLobs = {SELECT AIRPORT_MAP,AIRPORT_SUG_BOOK
            FROM AIRPORT_LOB_DETAILS
            WHERE AIRPORT_CODE= :p_airportCode FOR UPDATE};  

      // Embedded SQL: Fetch the locators from the positional iterator
     #sql { fetch :l_airportLobs INTO :l_blob, :l_clob };


      // If the above fetch was successful, retrieve and display the LOB data
      // else allow load of sample files
      if (!l_airportLobs.endFetch()) {
        // LOB details exist

        // Display airport map and suggestion book (LOB details)
        drawBLOB(l_blob,p_airportCode);
        writeCLOB(l_clob, p_airportCode);
        m_GUI.putStatus("Done retrieving and displaying LOB details");
      } else {
        // No LOB details

        m_GUI.m_loadButton.setEnabled(true);
        m_GUI.putStatus("No airport map and suggestion book exist for selected airport");
        m_GUI.appendStatus("\nPress <Load Sample Files> to load LOB details");
      }
      l_airportLobs.close();
    }  catch (Exception ex) { // Trap SQL errors
      m_GUI.putStatus("Error retrieving LOB Details for the selected airport");
      m_GUI.appendStatus(ex.toString());
    }


  }

  /**
  * Retrieve the BLOB data from input BLOB column into a local file,
  * and draws the image
  **/
  void drawBLOB(BLOB p_blob, String p_airPCode) {

    try {
      // Open a file stream to save the BLOB data
      FileOutputStream l_fileOutStream = new FileOutputStream(p_airPCode+".gif");

      // Retrieve the length of the BLOB data
      long l_blobLen;
     #sql l_blobLen = { VALUES(dbms_lob.getlength(:p_blob)) };

      long l_readLen; // Length of CLOB data read

      byte[] l_buffer = new byte[100]; // Temoprary buffer to transfer read data into StringBuffer

      for (long i=1;i<=l_blobLen;i+=l_readLen) {
        l_readLen = 1000; // Length of data to be read

        // Embedded SQL call to read the data from the CLOB using the dbms_lob
        // server-side package. The parameters are:
        // 1st parameter - BLOB to read
        // 2nd parameter - Number of bytes to read.(number of bytes actually read)
        // 3rd parameter - Offset
        // 4th parameter - The buffer in which the data is returned
      #sql { call dbms_lob.read(:p_blob, :inout l_readLen, :i, :out l_buffer) };
        l_fileOutStream.write(l_buffer,0,(int)l_readLen); // Save in StringBuffer
      }

      // Flush and close the streams
      l_fileOutStream.flush();
      l_fileOutStream.close();

      m_GUI.drawMap(p_airPCode); // Draw retrieved image to GUI
    } catch (Exception ex) { // Trap SQL and IO errors
      m_GUI.putStatus("Error in retrieving and drawing map for selected airport");
      m_GUI.appendStatus("\n"+ex.toString());
    }
  }

  /**
  * Retrieve the character data from the input CLOB, save in a
  * StringBuffer and display the StringBuffer contents in GUI

  **/
  void writeCLOB(CLOB p_clob, String p_airPCode) {
    try {
      // Holds the CLOB data being read
      StringBuffer l_suggestions = new StringBuffer();

      // Retrieve the length of the CLOB data
      long l_clobLen;
     #sql l_clobLen = { VALUES(dbms_lob.getlength(:p_clob)) };

      long l_readLen; // Length of CLOB data read
      String l_buffer; // Temoprary buffer to transfer read data into StringBuffer
      for (long i=1;i<=l_clobLen;i+=l_readLen) {
        l_readLen = 1000; // Length of data to be read

        // Embedded SQL call to read the data from the CLOB using the dbms_lob
        // server-side package. The parameters are:
        // 1st parameter - CLOB to read
        // 2nd parameter - Number of bytes to read.(number of bytes actually read)
        // 3rd parameter - Offset
        // 4th parameter - The buffer in which the data is returned
      #sql { call dbms_lob.read(:p_clob, :inout l_readLen, :i, :out l_buffer) };
        l_suggestions.append(l_buffer); // Save in StringBuffer
      }

      m_GUI.m_sugArea.append(new String(l_suggestions)); // Display in GUI
    } catch (Exception ex) { // Trap SQL and IO errors
      m_GUI.putStatus("Error in getting and drawing CLOB for the airport, "+p_airPCode+":");
      m_GUI.appendStatus(ex.toString());
    }

  }

  /**
  * Close connection and exit application
  **/
  public void exitApplication() {
    try {
      if (m_ctx != null)
        m_ctx.close();
    } catch (SQLException ex) { // Trap SQL errors
      m_GUI.putStatus("Error closing connection");
      m_GUI.appendStatus(ex.toString());
    }
    System.exit(0);
  }
}

E-mail this page
Printer View Printer View
Oracle Is The Information Company About Oracle | Oracle RSS Feeds | Careers | Contact Us | Site Maps | Legal Notices | Terms of Use | Privacy