1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.dbforms.event.datalist.dao;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27
28 import org.dbforms.config.DbFormsConfigRegistry;
29 import org.dbforms.config.Field;
30 import org.dbforms.config.FieldTypes;
31 import org.dbforms.config.FieldValue;
32 import org.dbforms.config.FieldValues;
33 import org.dbforms.config.ResultSetVector;
34 import org.dbforms.config.Table;
35 import org.dbforms.interfaces.DbEventInterceptorData;
36
37 import org.dbforms.util.FileHolder;
38 import org.dbforms.util.Util;
39
40 import java.io.File;
41 import java.io.IOException;
42
43 import java.sql.Connection;
44 import java.sql.SQLException;
45
46 import java.util.Iterator;
47
48 /***
49 * Abstract base class for DataSource.
50 *
51 * @author hkk
52 */
53 public abstract class AbstractDataSource {
54 /*** log4j category class */
55 private static Log logCat = LogFactory.getLog(AbstractDataSource.class);
56
57 private Table table;
58
59 /***
60 * Creates a new DataSource object.
61 */
62 public AbstractDataSource() {
63 }
64
65 /***
66 * Sets the select data for this dataSource
67 *
68 * @param filterConstraint
69 * FieldValue array used to restrict a set in a resultset
70 * @param orderConstraint
71 * FieldValue array used to build a cumulation of rules for
72 * ordering (sorting)
73 * @param sqlFilter
74 * sql condition to add to where clause
75 * @param sqlFilterParams
76 * list of FieldValues to fill the sqlFilter with
77 */
78 public abstract void setSelect(FieldValue[] filterConstraint,
79 FieldValue[] orderConstraint, String sqlFilter,
80 FieldValue[] sqlFilterParams);
81
82 /***
83 * get count rows from position
84 *
85 * @param position
86 * keyValueStr to the row<br>
87 * key format: FieldID ":" Length ":" Value<br>
88 * example: if key id = 121 and field id=2 then keyValueStr
89 * contains "2:3:121"<br>
90 * If the key consists of more than one fields, the key values
91 * are seperated through "-"<br>
92 * example: value of field 1=12, value of field 3=1992, then
93 * we'll get "1:2:12-3:4:1992"
94 * @param count
95 * count of rows to fetch
96 *
97 * @return the fetched ResultSetVector
98 *
99 * @throws SQLException
100 */
101 public ResultSetVector getCurrent(DbEventInterceptorData interceptorData,
102 String position, int count) throws SQLException {
103 try {
104 open();
105
106 int start = findStartRow(position);
107
108 if (count == 0) {
109 count = size() - start;
110 }
111
112 return getResultSetVector(interceptorData, start, count);
113 } catch (Exception e) {
114 logCat.error("getCurrent", e);
115 close();
116
117 return new ResultSetVector(getTable());
118 }
119 }
120
121 /***
122 * get count rows from first row
123 *
124 * @param count
125 * count of rows to fetch
126 *
127 * @return the fetched ResultSetVector
128 *
129 * @throws SQLException
130 */
131 public ResultSetVector getFirst(DbEventInterceptorData interceptorData,
132 int count) throws SQLException {
133 try {
134 open();
135
136 if (count == 0) {
137 count = size();
138 }
139
140 return getResultSetVector(interceptorData, 0, count);
141 } catch (Exception e) {
142 logCat.error("getFirst", e);
143 close();
144
145
146 return new ResultSetVector(getTable());
147 }
148 }
149
150 /***
151 * get count rows from last row
152 *
153 * @param count
154 * count of rows to fetch
155 *
156 * @return the fetched ResultSetVector
157 *
158 * @throws SQLException
159 */
160 public ResultSetVector getLast(DbEventInterceptorData interceptorData,
161 int count) throws SQLException {
162 try {
163 open();
164
165 return getResultSetVector(interceptorData, size() - 1, -count);
166 } catch (Exception e) {
167 logCat.error("getLast", e);
168 close();
169
170
171 return new ResultSetVector(getTable());
172 }
173 }
174
175 /***
176 * get count next rows from position
177 *
178 * @param position
179 * keyValueStr to the row<br>
180 * key format: FieldID ":" Length ":" Value<br>
181 * example: if key id = 121 and field id=2 then keyValueStr
182 * contains "2:3:121"<br>
183 * If the key consists of more than one fields, the key values
184 * are seperated through "-"<br>
185 * example: value of field 1=12, value of field 3=1992, then
186 * we'll get "1:2:12-3:4:1992"
187 * @param count
188 * count of rows to fetch
189 *
190 * @return the fetched ResultSetVector
191 *
192 * @throws SQLException
193 */
194 public ResultSetVector getNext(DbEventInterceptorData interceptorData,
195 String position, int count) throws SQLException {
196 try {
197 open();
198
199 int start = findStartRow(position) + 1;
200
201 if (count == 0) {
202 count = size() - start;
203 }
204
205 return getResultSetVector(interceptorData, start, count);
206 } catch (Exception e) {
207 logCat.error("getNext", e);
208 close();
209
210
211 return new ResultSetVector(getTable());
212 }
213 }
214
215 /***
216 * get count rows backwards from position
217 *
218 * @param position
219 * keyValueStr to the row<br>
220 * key format: FieldID ":" Length ":" Value<br>
221 * example: if key id = 121 and field id=2 then keyValueStr
222 * contains "2:3:121"<br>
223 * If the key consists of more than one fields, the key values
224 * are seperated through "-"<br>
225 * example: value of field 1=12, value of field 3=1992, then
226 * we'll get "1:2:12-3:4:1992"
227 * @param count
228 * count of rows to fetch
229 *
230 * @return the fetched ResultSetVector
231 *
232 * @throws SQLException
233 */
234 public ResultSetVector getPrev(DbEventInterceptorData interceptorData,
235 String position, int count) throws SQLException {
236 try {
237 open();
238
239 int start = findStartRow(position) - 1;
240
241 if (count == 0) {
242 count = start;
243 }
244
245 return getResultSetVector(interceptorData, start, -count);
246 } catch (Exception e) {
247 logCat.error("getPrev", e);
248 close();
249
250
251 return new ResultSetVector(getTable());
252 }
253 }
254
255 /***
256 * Sets the select data for this dataSource for free form selects. default
257 * methods just raises an exception
258 *
259 * @param tableList
260 * the list of tables involved into the query
261 * @param whereClause
262 * free-form whereClause to be appended to query
263 *
264 * @throws SQLException
265 */
266 public void setSelect(String tableList, String whereClause)
267 throws SQLException {
268 throw new SQLException("Free form select not implemented");
269 }
270
271 /***
272 * gets the Table for the DataSource
273 *
274 * @return Table
275 */
276 public Table getTable() {
277 return table;
278 }
279
280 /***
281 * performs an delete in the DataSource
282 *
283 * @param con
284 * DOCUMENT ME!
285 * @param keyValuesStr
286 * keyValueStr to the row to update<br>
287 * key format: FieldID ":" Length ":" Value<br>
288 * example: if key id = 121 and field id=2 then keyValueStr
289 * contains "2:3:121"<br>
290 * If the key consists of more than one fields, the key values
291 * are seperated through "-"<br>
292 * example: value of field 1=12, value of field 3=1992, then
293 * we'll get "1:2:12-3:4:1992"
294 *
295 * @throws SQLException
296 * if any error occurs
297 */
298 public int doDelete(DbEventInterceptorData interceptorData,
299 String keyValuesStr) throws SQLException {
300 return 0;
301 }
302
303 /***
304 * performs an insert into the DataSource
305 *
306 * @param con
307 * DOCUMENT ME!
308 * @param fieldValues
309 * FieldValues to insert
310 *
311 * @throws SQLException
312 */
313 public int doInsert(DbEventInterceptorData interceptorData,
314 FieldValues fieldValues) throws SQLException {
315 return 0;
316 }
317
318 /***
319 * performs an update into the DataSource
320 *
321 * @param con
322 * DOCUMENT ME!
323 * @param fieldValues
324 * FieldValues to update
325 * @param keyValuesStr
326 * keyValueStr to the row to update<br>
327 * key format: FieldID ":" Length ":" Value<br>
328 * example: if key id = 121 and field id=2 then keyValueStr
329 * contains "2:3:121"<br>
330 * If the key consists of more than one fields, the key values
331 * are seperated through "-"<br>
332 * example: value of field 1=12, value of field 3=1992, then
333 * we'll get "1:2:12-3:4:1992"
334 *
335 * @throws SQLException
336 * if any error occurs
337 */
338 public int doUpdate(DbEventInterceptorData interceptorData,
339 FieldValues fieldValues, String keyValuesStr) throws SQLException {
340 return 0;
341 }
342
343 /***
344 * set the connection parameter for the DataSouce. virtual method, if you
345 * need the connection data you must override this method
346 *
347 * @param con
348 * the JDBC Connection object
349 * @param dbConnectionName
350 * name of the used db connection. Can be used to get an own db
351 * connection, e.g. to hold it during the session (see
352 * DataSourceJDBC for example!)
353 */
354 protected void setConnection(Connection con, String dbConnectionName) {
355 }
356
357 /***
358 * should retrieve the row at an special index as an Object[]
359 *
360 * @param i
361 * index of row to fetch
362 *
363 * @return Object[] of the fetched row
364 *
365 * @throws SQLException
366 */
367 protected abstract Object[] getRow(int i) throws SQLException;
368
369 /***
370 * should close all open datasets
371 */
372 protected abstract void close();
373
374 /***
375 * maps the startRow to the internal index
376 *
377 * @param startRow
378 * keyValueStr to the row<br>
379 * key format: FieldID ":" Length ":" Value<br>
380 * example: if key id = 121 and field id=2 then keyValueStr
381 * contains "2:3:121"<br>
382 * If the key consists of more than one fields, the key values
383 * are seperated through "-"<br>
384 * example: value of field 1=12, value of field 3=1992, then
385 * we'll get "1:2:12-3:4:1992"
386 *
387 * @return the index of the row, 0 as first row if not found
388 *
389 * @throws SQLException
390 */
391 protected abstract int findStartRow(String startRow) throws SQLException;
392
393 /***
394 * return true if there are more records to fetch then the given record
395 * number
396 *
397 * @param i
398 * index of last fetched row.
399 *
400 * @return true if there are more records to fetch then the given record
401 * number
402 *
403 * @throws SQLException
404 */
405 protected abstract boolean hasMore(int i) throws SQLException;
406
407 /***
408 * Will be called to open all datasets
409 *
410 * @throws SQLException
411 */
412 protected abstract void open() throws SQLException;
413
414 /***
415 * Must return the size of the whole resultset with all data fetch
416 *
417 * @return size of whole resultset
418 *
419 * @throws SQLException
420 */
421 protected abstract int size() throws SQLException;
422
423 /***
424 * @param table
425 * The table to set.
426 */
427 protected void setTable(Table table) {
428 this.table = table;
429 }
430
431 /***
432 * deletes the blob files on disk
433 *
434 * @param fieldValues
435 * FieldValues to delete, called by
436 *
437 * @throws SQLException
438 */
439 protected void deleteBlobFilesFromDisk(FieldValues fieldValues)
440 throws SQLException {
441 Iterator iter = fieldValues.keys();
442
443 while (iter.hasNext()) {
444 String fieldName = (String) iter.next();
445 Field curField = table.getFieldByName(fieldName);
446
447 if (curField != null) {
448 int fieldType = curField.getType();
449
450 String directory = null;
451
452 try {
453 directory = DbFormsConfigRegistry.instance().lookup()
454 .replaceVariables(curField.getDirectory());
455 } catch (Exception e) {
456 logCat.error("deleteBlobFilesFromDisk", e);
457 throw new SQLException(e.getMessage());
458 }
459
460 if (fieldType == FieldTypes.DISKBLOB) {
461 String fileName = fieldValues.get(fieldName)
462 .getFieldValue().trim();
463
464
465 if (!Util.isNull(fileName)) {
466
467 File file = new File(directory, fileName);
468
469 if (file.exists()) {
470 file.delete();
471 logCat.info("deleted file " + fileName
472 + " from dir " + directory);
473 } else {
474 logCat.info("delete of file " + fileName
475 + " from dir " + directory
476 + " failed because file not found");
477 }
478 }
479 }
480 }
481 }
482 }
483
484 /***
485 * save the blob files to disk
486 *
487 * @param fieldValues
488 * FieldValues to update
489 *
490 * @throws SQLException
491 * @throws IllegalArgumentException
492 */
493 protected void saveBlobFilesToDisk(FieldValues fieldValues)
494 throws SQLException {
495 Iterator iter = fieldValues.keys();
496
497 while (iter.hasNext()) {
498 String fieldName = (String) iter.next();
499 Field curField = table.getFieldByName(fieldName);
500
501 if (curField != null) {
502 int fieldType = curField.getType();
503
504 if (fieldType == FieldTypes.DISKBLOB) {
505 String directory = curField.getDirectory();
506
507
508 if (directory == null) {
509 throw new IllegalArgumentException(
510 "directory-attribute needed for fields of type DISKBLOB");
511 }
512
513 try {
514 directory = DbFormsConfigRegistry.instance().lookup()
515 .replaceVariables(directory);
516 } catch (Exception e) {
517 logCat.error("saveBlobFilesToDisk", e);
518 }
519
520
521 File dir = new File(directory);
522
523
524 if (!dir.isDirectory()) {
525 throw new IllegalArgumentException("Not a directory: "
526 + directory);
527 }
528
529
530 if (!dir.canWrite()) {
531 throw new IllegalArgumentException("Not writable: "
532 + directory);
533 }
534
535
536 FileHolder fileHolder = fieldValues.get(fieldName)
537 .getFileHolder();
538
539 if (fileHolder != null) {
540 try {
541 fileHolder.writeBufferToFile(dir);
542
543
544 logCat.info("fin + closedy");
545 } catch (IOException ioe) {
546
547
548 logCat.error("saveBlobFilesToDisk", ioe);
549 throw new SQLException("could not store file '"
550 + fileHolder.getFileName() + "' to dir '"
551 + directory + "'");
552 }
553 } else {
554 logCat.info("uh! empty fileHolder");
555 }
556 }
557 }
558 }
559 }
560
561 /***
562 * DOCUMENT ME!
563 *
564 * @param startRow
565 * @param count
566 *
567 * @return the resultsetvector
568 *
569 * @throws SQLException
570 */
571 protected ResultSetVector getResultSetVector(
572 DbEventInterceptorData interceptorData, int startRow, int count)
573 throws SQLException {
574 ResultSetVector result;
575 int cCount = count;
576 do {
577 result = getResultSetVectorInternal(interceptorData, startRow,
578 cCount);
579 if ((count < 0) && result.isFirstPage())
580 break;
581 else if ((count > 0) && result.isLastPage())
582 break;
583 cCount = cCount + (count - result.size());
584 } while (result.size() < Math.abs(count));
585 return result;
586 }
587
588 private ResultSetVector getResultSetVectorInternal(
589 DbEventInterceptorData interceptorData, int startRow, int count)
590 throws SQLException {
591 ResultSetVector result = result = new ResultSetVector(table);
592
593 int begin = 0;
594 int ende = 0;
595
596 Object[] row;
597
598 if (count > 0) {
599 begin = startRow;
600
601 for (ende = begin; ende < (startRow + count); ende++) {
602 row = getRow(ende);
603
604 if (row == null) {
605 break;
606 }
607
608 result.addRow(interceptorData, row);
609 }
610 } else if (count < 0) {
611 begin = startRow + count + 1;
612
613 if (begin < 0) {
614 begin = 0;
615 }
616
617 for (ende = begin; ende <= startRow; ende++) {
618 row = getRow(ende);
619
620 if (row == null) {
621 break;
622 }
623
624 result.addRow(interceptorData, row);
625 }
626 }
627
628 result.setFirstPage(!(begin > 0));
629 result.setLastPage(!hasMore(ende));
630
631 return result;
632 }
633
634 }