View Javadoc

1   /*
2    * $Header: /cvsroot/jdbforms/dbforms/src/org/dbforms/event/classic/InsertEvent.java,v 1.38 2006/01/25 16:35:23 hkollmann Exp $
3    * $Revision: 1.38 $
4    * $Date: 2006/01/25 16:35:23 $
5    *
6    * DbForms - a Rapid Application Development Framework
7    * Copyright (C) 2001 Joachim Peer <joepeer@excite.com>
8    *
9    * This library is free software; you can redistribute it and/or
10   * modify it under the terms of the GNU Lesser General Public
11   * License as published by the Free Software Foundation; either
12   * version 2.1 of the License, or (at your option) any later version.
13   *
14   * This library is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this library; if not, write to the Free Software
21   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22   */
23  
24  package org.dbforms.event.classic;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  
29  import org.dbforms.config.Constants;
30  import org.dbforms.config.DbFormsConfig;
31  import org.dbforms.config.DbFormsConfigRegistry;
32  import org.dbforms.config.Field;
33  import org.dbforms.config.FieldTypes;
34  import org.dbforms.config.FieldValue;
35  import org.dbforms.config.FieldValues;
36  import org.dbforms.config.GrantedPrivileges;
37  import org.dbforms.config.JDBCDataHelper;
38  import org.dbforms.config.ResultSetVector;
39  import org.dbforms.config.MultipleValidationException;
40  
41  
42  import org.dbforms.event.AbstractValidationEvent;
43  import org.dbforms.interfaces.DbEventInterceptorData;
44  import org.dbforms.interfaces.IDbEventInterceptor;
45  
46  import org.dbforms.util.FileHolder;
47  import org.dbforms.util.MessageResourcesInternal;
48  import org.dbforms.util.ParseUtil;
49  import org.dbforms.util.StringUtil;
50  import org.dbforms.util.UniqueIDGenerator;
51  import org.dbforms.util.Util;
52  
53  import java.io.File;
54  import java.io.IOException;
55  import java.io.UnsupportedEncodingException;
56  
57  import java.sql.Connection;
58  import java.sql.PreparedStatement;
59  import java.sql.SQLException;
60  
61  import java.util.Iterator;
62  import java.util.Vector;
63  
64  import javax.servlet.http.HttpServletRequest;
65  
66  
67  
68  /***
69   * DOCUMENT ME!
70   *
71   * @author Joe Peer
72   *
73   * @deprecated This event prepares and performs a SQL-Insert operation.
74   */
75  public class InsertEvent extends AbstractValidationEvent {
76     /*** logging category for this class */
77     static Log logCat = LogFactory.getLog(InsertEvent.class.getName());
78  
79     /***
80      * Creates a new InsertEvent object.
81      *
82      * @param tableId DOCUMENT ME!
83      * @param keyId DOCUMENT ME!
84      * @param request DOCUMENT ME!
85      * @param config DOCUMENT ME!
86      */
87     public InsertEvent(Integer            tableId,
88                        String             keyId,
89                        HttpServletRequest request,
90                        DbFormsConfig      config) {
91        super(tableId.intValue(), keyId, request, config);
92     }
93  
94  
95     /***
96      * Insert actionbutton-strings is as follows: ac_insert_12_root_3 which is
97      * equivalent to: ac_insert  : insert action event 12         : table id
98      * root       : key 3          : button count used to identify individual
99      * insert buttons
100     *
101     * @param action DOCUMENT ME!
102     * @param request DOCUMENT ME!
103     * @param config DOCUMENT ME!
104     */
105    public InsertEvent(String             action,
106                       HttpServletRequest request,
107                       DbFormsConfig      config) {
108       super(StringUtil.getEmbeddedStringAsInteger(action, 2, '_'),
109             StringUtil.getEmbeddedString(action, 3, '_'), request, config);
110    }
111 
112    /***
113     * Get the hash table containing the form field names and values taken from
114     * the request object. <br>
115     * Example of a request parameter:<br>
116     * <code>name  = f_0_insroot_6 value = foo-bar </code>
117     *
118     * @return the hash map containing the names and values taken from the
119     *         request object
120     */
121    public FieldValues getFieldValues() {
122       return getFieldValues(true);
123    }
124 
125 
126    /***
127     * Process this event.
128     *
129     * @param con the jdbc connection object
130     *
131     * @throws SQLException if any data access error occurs
132     * @throws MultipleValidationException if any validation error occurs
133     */
134    public void processEvent(Connection con) throws SQLException, MultipleValidationException {
135       // Applying given security contraints (as defined in dbforms-config xml file)
136       // part 1: check if requested privilge is granted for role
137       if (!hasUserPrivileg(GrantedPrivileges.PRIVILEG_INSERT)) {
138          String s = MessageResourcesInternal.getMessage("dbforms.events.insert.nogrant",
139                                                         getRequest().getLocale(),
140                                                         new String[] {
141                                                            getTable()
142                                                               .getName()
143                                                         });
144          throw new SQLException(s);
145       }
146 
147       FieldValues fieldValues = getFieldValues();
148 
149       if (fieldValues.size() == 0) {
150          throw new SQLException("no parameters");
151       }
152 
153       DbEventInterceptorData interceptorData = new DbEventInterceptorData(getRequest(),
154                                                                getConfig(), con, getTable());
155       interceptorData.setAttribute(DbEventInterceptorData.FIELDVALUES, fieldValues);
156 
157       // process the interceptors associated to this table
158       int operation = getTable()
159                          .processInterceptors(IDbEventInterceptor.PRE_INSERT,
160                                               interceptorData);
161 
162       if ((operation == IDbEventInterceptor.GRANT_OPERATION)
163                 && (fieldValues.size() > 0)) {
164          // End of interceptor processing
165          if (!checkSufficentValues(fieldValues)) {
166             throw new SQLException("unsufficent parameters");
167          }
168 
169          PreparedStatement ps = con.prepareStatement(getTable().getInsertStatement(fieldValues));
170 
171          // now we provide the values;
172          // every key is the parameter name from of the form page;
173          Iterator iter = fieldValues.elements();
174          int      col = 1;
175 
176          while (iter.hasNext()) {
177             FieldValue fv = (FieldValue) iter.next();
178 
179             if (fv != null) {
180                Field curField = fv.getField();
181                logCat.debug("Retrieved curField:" + curField.getName()
182                             + " type:" + curField.getType());
183 
184                int    fieldType = curField.getType();
185                Object value = null;
186 
187                if (fieldType == FieldTypes.BLOB) {
188                   // in case of a BLOB we supply the FileHolder object to SqlUtils for further operations
189                   value = fv.getFileHolder();
190                } else if (fieldType == FieldTypes.DISKBLOB) {
191                   // check if we need to store it encoded or not
192                   FileHolder fileHolder = fv.getFileHolder();
193                   String     fileName = fileHolder.getFileName();
194 
195                   if (curField.hasEncodedSet()) {
196                      int    dotIndex = fileName.lastIndexOf('.');
197                      String suffix = (dotIndex != -1)
198                                      ? fileName.substring(dotIndex)
199                                      : "";
200                      fileHolder.setFileName(UniqueIDGenerator.getUniqueID()
201                                             + suffix);
202 
203                      // a diskblob gets stored to db as an ordinary string (it's only the reference!)
204                      value = fileHolder.getFileName();
205                   } else {
206                      // a diskblob gets stored to db as an ordinary string	 (it's only the reference!)
207                      value = fileName;
208                   }
209                } else {
210                   value = fv.getFieldValueAsObject();
211                }
212 
213                logCat.info("PRE_INSERT: field=" + curField.getName() + " col="
214                            + col + " value=" + value + " type=" + fieldType);
215                JDBCDataHelper.fillWithData(ps, fv.getField().getEscaper(), col,
216                                            value, fieldType,
217                                            getTable().getBlobHandlingStrategy());
218                col++;
219             }
220          }
221 
222          // execute the query & throws an exception if something goes wrong
223          ps.executeUpdate();
224          ps.close(); // #JP Jun 27, 2001
225          iter = fieldValues.keys();
226 
227          while (iter.hasNext()) {
228             String fieldName = (String) iter.next();
229             Field  curField = getTable()
230                                  .getFieldByName(fieldName);
231 
232             if (curField != null) {
233                int    fieldType = curField.getType();
234 
235                String directory = null;
236 
237                try {
238                   directory = DbFormsConfigRegistry.instance().lookup().replaceVariables(curField.getDirectory());
239                } catch (Exception e) {
240                   throw new SQLException(e.getMessage());
241                }
242 
243                if (fieldType == FieldTypes.DISKBLOB) {
244                   // check if directory-attribute was provided
245                   if (directory == null) {
246                      throw new IllegalArgumentException("directory-attribute needed for fields of type DISKBLOB");
247                   }
248 
249                   // instanciate file object for that dir
250                   File dir = new File(directory);
251 
252                   // Check saveDirectory is truly a directory
253                   if (!dir.isDirectory()) {
254                      throw new IllegalArgumentException("Not a directory: "
255                                                         + directory);
256                   }
257 
258                   // Check saveDirectory is writable
259                   if (!dir.canWrite()) {
260                      throw new IllegalArgumentException("Not writable: "
261                                                         + directory);
262                   }
263 
264                   // dir is ok so lets store the filepart
265                   FileHolder fileHolder = ParseUtil.getFileHolder(getRequest(),
266                                                                   "f_"
267                                                                   + getTable().getId()
268                                                                   + "_ins"
269                                                                   + getKeyId()
270                                                                   + "_"
271                                                                   + curField
272                                                                     .getId());
273 
274                   if (fileHolder != null) {
275                      try {
276                         fileHolder.writeBufferToFile(dir);
277 
278                         //filePart.getInputStream().close();
279                         logCat.info("fin + closedy");
280                      } catch (IOException ioe) {
281                         //#checkme: this would be a good place for rollback in database!!
282                         throw new SQLException("could not store file '"
283                                                + fileHolder.getFileName()
284                                                + "' to dir '" + directory + "'");
285                      }
286                   } else {
287                      logCat.info("uh! empty fileHolder");
288                   }
289                }
290             }
291          }
292 
293          //Patch insert nav by Stefano Borghi
294          //Show the last record inserted
295 
296          /***
297           * @todo Will not work if key field is autoinc!!
298           */
299          String       firstPosition = null;
300          Vector       key = getTable()
301                                .getKey();
302          FieldValue[] fvEqual = new FieldValue[key.size()];
303 
304          for (int i = 0; i < key.size(); i++) {
305             Field      field     = (Field) key.elementAt(i);
306             String     fieldName = field.getName();
307             FieldValue fv        = fieldValues.get(fieldName);
308             String     value     = null;
309 
310             if (fv != null) {
311                value = fv.getFieldValue();
312             }
313 
314             FieldValue keyFieldValue = new FieldValue(field, value);
315             fvEqual[i] = keyFieldValue;
316          }
317 
318          ResultSetVector resultSetVector = getTable()
319                                               .doConstrainedSelect(fvEqual,
320                                                                    null, null,
321                                                                    null,
322                                                                    Constants.COMPARE_NONE,
323                                                                    1, interceptorData);
324 
325          if (resultSetVector != null) {
326             resultSetVector.moveFirst();
327             firstPosition = getTable()
328                                .getPositionString(resultSetVector);
329          }
330          // CAPIO - must encode the position as it gets decoded when read.
331          try {
332          	firstPosition = Util.encode(firstPosition, getRequest().getCharacterEncoding());
333 		 } catch (UnsupportedEncodingException ex) {
334 		    logCat.error(ex);
335 			throw new SQLException(ex.getMessage());
336 		 }
337          getRequest()
338             .setAttribute("firstpos_" + getTable().getId(), firstPosition);
339 
340          // finally, we process interceptor again (post-insert)
341          // process the interceptors associated to this table
342          getTable()
343             .processInterceptors(IDbEventInterceptor.POST_INSERT, interceptorData);
344       }
345    }
346 
347 
348    /***
349     * Check if the input hash table has got sufficent parameters.
350     *
351     * @param fieldValues the hash map containing the names and values taken
352     *        from the request object
353     *
354     * @return true  if the hash table has got sufficent parameters, false
355     *         otherwise
356     *
357     * @throws SQLException if any data access error occurs
358     */
359    private boolean checkSufficentValues(FieldValues fieldValues)
360                                  throws SQLException {
361       Vector fields = getTable()
362                          .getFields();
363 
364       for (int i = 0; i < fields.size(); i++) {
365          Field field = (Field) fields.elementAt(i);
366 
367          // if a field is a key and if it is NOT automatically generated,
368          // then it should be provided by the user
369          if (!field.hasAutoIncSet() && field.hasIsKeySet()) {
370             if (fieldValues.get(field.getName()) == null) {
371                throw new SQLException("Field " + field.getName()
372                                       + " is missing");
373             }
374          }
375          // in opposite, if a field is automatically generated by the RDBMS, we need to
376          else if (field.hasAutoIncSet()) {
377             if (fieldValues.get(field.getName()) != null) {
378                throw new SQLException("Field " + field.getName()
379                                       + " should be calculated by RDBMS, remove it from the form");
380             }
381          }
382 
383          // in future we could do some other checks like NOT-NULL conditions,etc.
384       }
385 
386       return true;
387    }
388 }