001: /*
002: * (C) Copyright 2004 Nabh Information Systems, Inc.
003: *
004: * All copyright notices regarding Nabh's products MUST remain
005: * intact in the scripts and in the outputted HTML.
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public License
008: * as published by the Free Software Foundation; either version 2.1
009: * of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: *
020: */
021: package com.nabhinc.portlet.mvcportlet.actionprocessor;
022:
023: import java.io.IOException;
024: import java.sql.Connection;
025: import java.sql.PreparedStatement;
026: import java.sql.SQLException;
027: import java.text.ParseException;
028:
029: import javax.portlet.ActionRequest;
030: import javax.portlet.ActionResponse;
031: import javax.portlet.PortletException;
032:
033: import org.w3c.dom.Element;
034:
035: import com.nabhinc.portlet.mvcportlet.core.ActionConfig;
036: import com.nabhinc.portlet.mvcportlet.core.ActionProcessor;
037: import com.nabhinc.portlet.mvcportlet.core.BaseRequestProcessor;
038: import com.nabhinc.portlet.mvcportlet.core.ControllerPortletConfig;
039: import com.nabhinc.util.db.IDCreationUtil;
040: import com.nabhinc.util.StringUtil;
041: import com.nabhinc.util.XMLUtil;
042: import com.nabhinc.util.db.DBConfigUtil;
043: import com.nabhinc.util.db.DBParamUtil;
044: import com.nabhinc.util.db.DBUtil;
045: import com.nabhinc.util.db.IDCreator;
046:
047: /**
048: * Inserts or updates one or more database records<p>
049: * Required configuration parameters
050: * <ul>
051: * <li>sql - SQL used to update or insert a record.</li>
052: * </ul>
053: * Optional configuration parameters
054: * <ul>
055: * <li>params - Comma separated list of names of SQL parameters to be
056: * inserted. In general, these are the request parameter names. The
057: * following specialtokens are used to insert other values:
058: * <ul>
059: * <li>$userName - Current user name returned by request.getRemoteUser()</li>
060: * <li>$currentDate - Today's date</li>
061: * <li>$currentTimestamp - Current time</li>
062: * </ul>
063: * </li>
064: * <li>param-types - Comma separated list of SQL parameter types. This
065: * parameter must be specified if "params" are specified. Possible parameter
066: * types are: VARCHAR, INTEGER, DECIMAL, BOOLEAN, SMALLINT, DATE,
067: * TIME, TIMESTAMP, FLOAT, DOUBLE, ARRAY, BIGINT, BINARY, BIT,
068: * BLOB, CHAR, CLOB, LONGVARBINARY, LONGVARCHAR, JAVA_OBJECT
069: * </li>
070: * </ul>
071: *
072: * @author Padmanabh Dabke
073: * (c) 2004 Nabh Information Systems, Inc. All Rights Reserved.
074: */
075:
076: public class InsertUpdateRecord extends BaseRequestProcessor implements
077: ActionProcessor {
078:
079: private class OperationInfo {
080: public boolean isMultiple = true;
081: public String sql = null;
082: public String[] params = null;
083: public int[] paramTypes = null;
084:
085: public OperationInfo(boolean mult, String sq, String[] pa,
086: int[] paTypes) {
087: isMultiple = mult;
088: sql = sq;
089: params = pa;
090: paramTypes = paTypes;
091: }
092: }
093:
094: private IDCreator irIDCreator = null;
095: private OperationInfo[] irOpInfo = null;
096:
097: /**
098: * Initialization.
099: * @param config XML configuration element
100: * @throws PortletException Thrown if sql parameter is not specified,
101: * "params" parameter is specified but corresponding "param-types"
102: * are not specified.
103: */
104: public void init(Element config, ControllerPortletConfig cpConfig)
105: throws PortletException {
106: super .init(config, cpConfig);
107: Element idCreatorElem = XMLUtil.getSubElement(config,
108: "id-creator");
109: if (idCreatorElem != null) {
110: try {
111: irIDCreator = (IDCreator) Class.forName(
112: XMLUtil.getSubElementText(idCreatorElem,
113: "class")).newInstance();
114: irIDCreator.init(idCreatorElem);
115: } catch (Exception ex) {
116: throw new PortletException(
117: "Failed to create ID creator.", ex);
118: }
119: }
120: Element[] opElems = XMLUtil.getSubElements(config,
121: "transaction");
122: if (opElems == null || opElems.length == 0) {
123: throw new PortletException(
124: "InsertUpdateRecord configuration requires at least one transaction.");
125: }
126: irOpInfo = new OperationInfo[opElems.length];
127: for (int i = 0; i < opElems.length; i++) {
128: irOpInfo[i] = constructOperationInfo(opElems[i]);
129: }
130: }
131:
132: private OperationInfo constructOperationInfo(Element config)
133: throws PortletException {
134: String sql = XMLUtil.getSubElementText(config, "sql");
135: if (sql == null)
136: throw new PortletException("Missing required element: sql.");
137: boolean isMultiple = "true".equals(config
138: .getAttribute("multiple"));
139:
140: String params = XMLUtil.getSubElementText(config, "params");
141: if (params != null) {
142: String[] paramArray = StringUtil.split(params, ",");
143: String paramTypes = XMLUtil.getSubElementText(config,
144: "param-types");
145: if (paramTypes == null) {
146: throw new PortletException(
147: "You must specify param-types if you specify params.");
148: }
149: String[] typeArray = StringUtil.split(paramTypes, ",");
150: if (typeArray.length != paramArray.length) {
151: throw new PortletException(
152: "Number of param-types must be equal to number of params.");
153: }
154: int[] paramTypeCodes = new int[typeArray.length];
155: for (int i = 0; i < typeArray.length; i++) {
156: try {
157: paramTypeCodes[i] = DBConfigUtil
158: .getSQLType(typeArray[i]);
159: } catch (Exception ex) {
160: throw new PortletException(
161: "Failed to parse sql type.", ex);
162: }
163: }
164: return new OperationInfo(isMultiple, sql, paramArray,
165: paramTypeCodes);
166: }
167:
168: return new OperationInfo(isMultiple, sql, null, null);
169: }
170:
171: /**
172: * Inserts or updates a database record<p>
173: * @param request Action request
174: * @param response Action response
175: * @param config Action config
176: * @return "success"
177: * @throws PortletException
178: * @throws IOException
179: */
180: public String process(ActionRequest request,
181: ActionResponse response, ActionConfig config)
182: throws PortletException, IOException {
183:
184: Connection conn = null;
185: PreparedStatement st = null;
186:
187: try {
188: conn = brpConfig.getDataSource().getConnection();
189: conn.setAutoCommit(false);
190:
191: int id = IDCreationUtil.getRecordID(irIDCreator, conn,
192: request);
193: for (int count = 0; count < irOpInfo.length; count++) {
194: String sql = irOpInfo[count].sql;
195: String[] params = irOpInfo[count].params;
196: int[] paramTypes = irOpInfo[count].paramTypes;
197: boolean isMult = irOpInfo[count].isMultiple;
198:
199: st = conn.prepareStatement(sql);
200: //Form form = config.getForm();
201: if (isMult) {
202: DBParamUtil.setSQLParam(st, 0, params[0],
203: paramTypes[0], request, id);
204: String[] values = request
205: .getParameterValues(params[1]);
206: if (values != null) {
207: for (int i = 0; i < values.length; i++) {
208: st.setString(2, values[i]);
209: st.execute();
210: }
211: }
212: } else {
213: if (params != null) {
214: for (int i = 0; i < params.length; i++) {
215: /*
216: String defaul = null;
217: if (form != null && (! params[i].startsWith("$"))) {
218: if (form.getField(params[i]) != null)
219: defaul = form.getField(params[i]).getDefaultValue();
220: }
221: */
222: DBParamUtil.setSQLParam(st, i, params[i],
223: paramTypes[i], request,
224: /*defaul,*/id);
225: }
226: }
227: st.execute();
228: }
229: }
230: conn.commit();
231: return "success";
232:
233: } catch (SQLException sqe) {
234: try {
235: conn.rollback();
236: } catch (SQLException se) {
237: }
238: throw new PortletException("Database exception.", sqe);
239: } catch (ParseException pex) {
240: try {
241: conn.rollback();
242: } catch (SQLException se) {
243: }
244: throw new PortletException("Malformed request parameter.",
245: pex);
246: } catch (Throwable e) {
247: try {
248: conn.rollback();
249: } catch (SQLException se) {
250: }
251: throw new PortletException("Unknown exception.", e);
252: } finally {
253: DBUtil.close(st);
254: DBUtil.close(conn);
255: }
256: }
257: }
|