001    /*
002    @license.text@
003     */
004    package biz.hammurapi.sql.xml;
005    
006    import java.sql.PreparedStatement;
007    import java.sql.SQLException;
008    import java.util.ArrayList;
009    import java.util.Collection;
010    import java.util.Iterator;
011    
012    import javax.naming.InitialContext;
013    import javax.sql.DataSource;
014    
015    import org.w3c.dom.Element;
016    import org.w3c.dom.Node;
017    
018    import biz.hammurapi.config.ConfigurationException;
019    import biz.hammurapi.config.Context;
020    import biz.hammurapi.config.DomConfigurable;
021    import biz.hammurapi.sql.SQLProcessor;
022    import biz.hammurapi.xml.dom.AbstractDomObject;
023    
024    
025    /**
026     * @author Pavel Vlasov
027     * @version $Revision: 1.2 $
028     */
029    public class SQLCommand extends AbstractDomObject implements DomConfigurable {
030    
031            protected static class Parameterizer implements biz.hammurapi.sql.Parameterizer {
032                    private static class Parameter {
033                            String name;
034                            Object value;
035                    }
036                    
037                    Parameter[] parameters;
038                    
039                    Parameterizer(Collection parameterNames) {
040                            parameters=new Parameter[parameterNames.size()];                        
041                            Iterator it=parameterNames.iterator();
042                            for (int i=0; it.hasNext(); i++) {
043                                    parameters[i]=new Parameter();
044                                    parameters[i].name = (String) it.next();
045                            }
046                    }
047    
048                    public void parameterize(PreparedStatement ps) throws SQLException {
049                            for (int i=0; i<parameters.length; i++) {
050                                    ps.setObject(i+1, parameters[i].value);
051                            }
052                            
053                    }
054                    
055                    boolean setContext(Context context) {
056                            for (int i=0; i<parameters.length; i++) {
057                                    Object o = context.get(parameters[i].name);
058                                    parameters[i].value = o;
059                                    if (parameters[i].value==null) {
060                                            return false;
061                                    }
062                            }
063                            return true;
064                    }               
065            }
066    
067            protected String name;
068            protected String sql;
069            protected Parameterizer parameterizer;
070            protected String errorMessage;
071            private SQLProcessor processor;
072            
073            protected SQLProcessor getProcessor() {
074                    return processor;
075            }
076    
077            public void configure(Node configNode, Context context) throws ConfigurationException {
078                    Element configElement=(Element) configNode;
079                    if (configElement.hasAttribute("name")) {
080                            name=configElement.getAttribute("name");
081                    }
082                    
083                    if (configElement.hasAttribute("error-message")) {
084                            errorMessage=configElement.getAttribute("error-message");
085                    }
086                    
087                    processor=initProcessor(configNode); 
088                    
089                    try {
090                            sql=getElementText(configElement, "sql");
091                            if (sql==null) {
092                                    throw new ConfigurationException("<sql> element not found");
093                            }
094                            
095                            Collection parameters=new ArrayList();
096                            StringBuffer sqlBuf=new StringBuffer(sql);
097                            for (int i=sqlBuf.indexOf("?["); i!=-1; i=sqlBuf.indexOf("?[")) {
098                                    int j=sqlBuf.indexOf("]?", i+2);
099                                    if (j==-1) {
100                                            break;
101                                    } else {
102                                            parameters.add(sqlBuf.substring(i+2, j));
103                                            sqlBuf.delete(i+1, j+2);
104                                    }
105                            }
106                            sql=sqlBuf.toString();
107                            if (!parameters.isEmpty()) {
108                                    parameterizer=new Parameterizer(parameters);
109                            }
110                    } catch (Exception e) {
111                            throw new ConfigurationException(e);
112                    }               
113            }
114    
115            /**
116             * @param configNode
117             * @throws ConfigurationException
118             */
119            static SQLProcessor initProcessor(Node configNode) throws ConfigurationException {
120                    try {
121                            String jndiName=getElementText((Element) configNode, "data-source");
122                            if (jndiName==null) {
123                                    return null;
124                            } else {
125                                    DataSource ds=(DataSource) new InitialContext().lookup(jndiName);
126                                    return new SQLProcessor(ds, null);
127                            }
128                    } catch (Exception e) {
129                            throw new ConfigurationException("Cannot read datasource JNDI name", e);                        
130                    }
131            }
132    
133    }