// package clt.taglibs.sql2xml;

import java.beans.*;
import java.io.*;
import java.sql.*;
import java.lang.reflect.*;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.TagSupport;

public class XmlForQueryTag  extends TagSupport {
  // ------------------------------------------------------------- Properties
  String conn    = null;
  String sql     = null;
  String rootTag = "ROWSET";
  String rowTag  = "ROW"; 
 
  public void setConn(String _conn) {
    conn = _conn;
  }
  public void setSql(String _sql) {
    sql = _sql;
  }
  public void setRootTag(String _rootTag) {
    rootTag = _rootTag;
  }
  public void setRowTag(String _rowTag) {
    rowTag = _rowTag;
  } 
  // ----------------------------------------------------------------------------- Public Method 
  public int doStartTag() throws JspException {
    // 
    Object o = pageContext.findAttribute(conn);
    
    if (o == null) {
      throw new JspException("Missing JSP bean '" + conn + "'");
    }
    if (sql == null) {
      throw new JspException("Missing SQL string: '" + sql + "'");
    }  
    // Render the contents of this bean to our writer
    try {
        JspWriter out = pageContext.getOut();
        String xml = getXmlForQuery(createStatement(o), sql, rootTag,  rowTag);
        out.print(xml);
    } catch (Exception e) {
        throw new JspException("Error writing output: " + e.toString());
    }
    // Skip the body of this tag (which should be empty anyway)
    return (SKIP_BODY);
  } //DoStartTag
  
  public void release() {
    conn = null;
    sql = null;
  }
  //-----------------------------------------------------------------------------
  private Statement createStatement(Object bean) throws JspException {
    // 
        Statement stmt = null;
	if (bean == null) {
	    throw new JspException("[createStatement Error]:Missing bean");
	} else {
	    try {
                stmt = ((Connection) bean).createStatement();
                /*
		Method method = bean.getClass().getMethod("createStatement", new Class[0]);
		stmt = (Statement) method.invoke(bean, new Object[0]);
                */
	    } catch (Exception e) {
		throw new JspException(e.toString());
	    }
	}
        return stmt;
  }
   private String getXmlForQuery(Statement stmt, String sql, String rootTag, String rowTag) throws SQLException {
      String    rv = null;
      ResultSet rs = null;
      try {
          rs = stmt.executeQuery(sql);
          rv = getXmlForResultSet(rs, rootTag, rowTag);
      }
      catch (Exception e) {
         // errorgram
         rv = "<?xml version=\"1.0\"?>" +
                    "<ERROR code='1001'>" +
                       "<SQL>" + sql + "</SQL>" +
                       "<MSG>" + e.getMessage() + "</MSG>" +
                    "</ERROR>";
      }
      finally {
        try {
          rs.close(); 
        }
        catch (Exception ex) {/* ignore */ }
      }
      return rv;
   }

   private String getXmlForResultSet(ResultSet rs, String rootTag, String rowTag) throws SQLException {
      ResultSetMetaData rsMeta = rs.getMetaData();
      int Count;
      StringBuffer buf = new StringBuffer();
      buf.append("<?xml version=\"1.0\" encoding=\"Big5\"?>\n");
      Count = rsMeta.getColumnCount();
      // 
      buf.append('<'); buf.append(rootTag); buf.append(">\n");
      while(rs.next()) {
         buf.append('<'); buf.append(rowTag); buf.append(">\n");
         for(int i=1; i <= Count; i++) {
             String cName=rsMeta.getColumnName(i);
             String value = rs.getString(cName);
             buf.append('<');  buf.append(cName); buf.append('>');
             if(!rs.wasNull()) buf.append(value);
             buf.append("</"); buf.append(cName); buf.append(">\n");
         } // For
         buf.append("</"); buf.append(rowTag); buf.append(">\n");
      }  // While
      buf.append("</"); buf.append(rootTag); buf.append(">\n");
      return (buf.toString());
   }
}

