1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.efaps.db.store;
22
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.OutputStream;
26 import java.sql.Connection;
27 import java.sql.PreparedStatement;
28 import java.sql.ResultSet;
29 import java.sql.SQLException;
30 import java.sql.Statement;
31 import java.util.Map;
32 import java.util.zip.GZIPInputStream;
33 import java.util.zip.ZipInputStream;
34
35 import org.efaps.db.Context;
36 import org.efaps.db.GeneralInstance;
37 import org.efaps.db.Instance;
38 import org.efaps.db.InstanceQuery;
39 import org.efaps.db.databases.AbstractDatabase;
40 import org.efaps.db.transaction.AbstractResource;
41 import org.efaps.db.transaction.ConnectionResource;
42 import org.efaps.db.wrapper.SQLPart;
43 import org.efaps.db.wrapper.SQLSelect;
44 import org.efaps.util.EFapsException;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48
49
50
51
52
53 public abstract class AbstractStoreResource
54 extends AbstractResource
55 implements Resource
56 {
57
58
59
60 public static final String TABLENAME_STORE = "T_CMGENSTORE";
61
62
63
64
65 public static final String COLNAME_FILENAME = "FILENAME";
66
67
68
69
70 public static final String COLNAME_FILELENGTH = "FILELENGTH";
71
72
73
74
75 private static final Logger LOG = LoggerFactory.getLogger(AbstractStoreResource.class);
76
77
78
79
80 private static final SQLSelect SQL_SELECT = new SQLSelect()
81 .column(0, "ID")
82 .column(1, AbstractStoreResource.COLNAME_FILENAME)
83 .column(1, AbstractStoreResource.COLNAME_FILELENGTH)
84 .column(1, "ID")
85 .from(GeneralInstance.TABLENAME, 0)
86 .leftJoin(AbstractStoreResource.TABLENAME_STORE, 1, "ID", 0, "ID");
87
88
89
90
91 private StoreEvent storeEvent = StoreEvent.UNKNOWN;
92
93
94
95
96
97
98 private final byte[] buffer = new byte[1024];
99
100
101
102
103 private Instance instance;
104
105
106
107
108 private Long generalID;
109
110
111
112
113 private boolean[] exist;
114
115
116
117
118 private String fileName = "DEFAULT";
119
120
121
122
123 private Long fileLength = new Long(0);
124
125
126
127
128 private Store store;
129
130
131
132
133 @Override
134 public void initialize(final Instance _instance,
135 final Store _store)
136 throws EFapsException
137 {
138 this.instance = _instance;
139 this.store = _store;
140 final SQLSelect select = AbstractStoreResource.SQL_SELECT.getCopy()
141 .addPart(SQLPart.WHERE)
142 .addColumnPart(0, "INSTTYPEID").addPart(SQLPart.EQUAL)
143 .addValuePart(_instance.getType().getId())
144 .addPart(SQLPart.AND)
145 .addColumnPart(0, "INSTID").addPart(SQLPart.EQUAL).addValuePart(_instance.getId());
146 this.exist = new boolean[1 + add2Select(select)];
147 getGeneralID(select.getSQL());
148
149 }
150
151
152
153
154 @Override
155 public void open(final StoreEvent _event)
156 throws EFapsException
157 {
158 this.storeEvent = _event;
159 super.open();
160 if (getStoreEvent().equals(StoreEvent.READ) || getStoreEvent().equals(StoreEvent.WRITE)) {
161 insertDefaults();
162 }
163 }
164
165
166
167
168
169
170
171
172
173 public void read(final OutputStream _out)
174 throws EFapsException
175 {
176 StoreResourceInputStream in = null;
177 try {
178 in = (StoreResourceInputStream) read();
179 if (in != null) {
180 int length = 1;
181 while (length > 0) {
182 length = in.read(this.buffer);
183 if (length > 0) {
184 _out.write(this.buffer, 0, length);
185 }
186 }
187 }
188 } catch (final IOException e) {
189 throw new EFapsException(AbstractStoreResource.class, "read.IOException", e);
190 } finally {
191 if (in != null) {
192 try {
193 in.closeWithoutCommit();
194 } catch (final IOException e) {
195 AbstractStoreResource.LOG.warn("Catched IOException in class: " + this.getClass());
196 }
197 }
198 }
199 }
200
201
202
203
204 @Override
205 public String getFileName()
206 throws EFapsException
207 {
208 return this.fileName;
209 }
210
211
212
213
214 @Override
215 public Long getFileLength()
216 throws EFapsException
217 {
218 return this.fileLength;
219 }
220
221
222
223
224
225 protected void insertDefaults()
226 throws EFapsException
227 {
228 if (!getExist()[0] && getGeneralID() != null) {
229 try {
230 final ConnectionResource res = Context.getThreadContext().getConnectionResource();
231 final Connection con = res.getConnection();
232 Context.getDbType().newInsert(AbstractStoreResource.TABLENAME_STORE, "ID", false)
233 .column("ID", getGeneralID())
234 .column(AbstractStoreResource.COLNAME_FILENAME, "TMP")
235 .column(AbstractStoreResource.COLNAME_FILELENGTH, 0)
236 .execute(con);
237 res.commit();
238 this.fileName = "TMP";
239 this.fileLength = new Long(0);
240 } catch (final SQLException e) {
241 throw new EFapsException(AbstractStoreResource.class, "insertDefaults", e);
242 }
243 }
244 }
245
246
247
248
249
250
251
252
253 protected void setFileInfo(final String _filename,
254 final long _fileLength)
255 throws EFapsException
256 {
257 if (!_filename.equals(this.fileName) || _fileLength != this.fileLength) {
258 ConnectionResource res = null;
259 try {
260 res = Context.getThreadContext().getConnectionResource();
261 final AbstractDatabase<?> db = Context.getDbType();
262 final StringBuilder cmd = new StringBuilder().append(db.getSQLPart(SQLPart.UPDATE)).append(" ")
263 .append(db.getTableQuote()).append(AbstractStoreResource.TABLENAME_STORE)
264 .append(db.getTableQuote())
265 .append(" ").append(db.getSQLPart(SQLPart.SET)).append(" ")
266 .append(db.getColumnQuote())
267 .append(AbstractStoreResource.COLNAME_FILENAME)
268 .append(db.getColumnQuote()).append(db.getSQLPart(SQLPart.EQUAL)).append("? ")
269 .append(db.getSQLPart(SQLPart.COMMA))
270 .append(db.getColumnQuote())
271 .append(AbstractStoreResource.COLNAME_FILELENGTH)
272 .append(db.getColumnQuote()).append(db.getSQLPart(SQLPart.EQUAL)).append("? ")
273 .append(db.getSQLPart(SQLPart.WHERE)).append(" ")
274 .append(db.getColumnQuote()).append("ID").append(db.getColumnQuote())
275 .append(db.getSQLPart(SQLPart.EQUAL)).append(getGeneralID());
276
277 final PreparedStatement stmt = res.getConnection().prepareStatement(cmd.toString());
278 try {
279 stmt.setString(1, _filename);
280 stmt.setLong(2, _fileLength);
281 stmt.execute();
282 } finally {
283 stmt.close();
284 }
285 res.commit();
286 } catch (final EFapsException e) {
287 res.abort();
288 throw e;
289 } catch (final SQLException e) {
290 res.abort();
291 throw new EFapsException(JDBCStoreResource.class, "write.SQLException", e);
292 }
293 }
294 }
295
296
297
298
299
300
301 protected abstract int add2Select(final SQLSelect _select);
302
303
304
305
306
307
308 private void getGeneralID(final String _complStmt)
309 throws EFapsException
310 {
311 ConnectionResource con = null;
312 try {
313 con = Context.getThreadContext().getConnectionResource();
314
315 final Statement stmt = con.getConnection().createStatement();
316
317 final ResultSet rs = stmt.executeQuery(_complStmt.toString());
318
319 while (rs.next()) {
320 this.generalID = rs.getLong(1);
321 this.fileName = rs.getString(2);
322 if (this.fileName != null && !this.fileName.isEmpty()) {
323 this.fileName = this.fileName.trim();
324 }
325 this.fileLength = rs.getLong(3);
326 for (int i = 0; i < this.exist.length; i++) {
327 this.exist[i] = rs.getLong(4 + i) > 0;
328 }
329 getAdditionalInfo(rs);
330 }
331 rs.close();
332 stmt.close();
333 con.commit();
334 } catch (final SQLException e) {
335 throw new EFapsException(InstanceQuery.class, "executeOneCompleteStmt", e);
336 } finally {
337 if (con != null && con.isOpened()) {
338 con.abort();
339 }
340 }
341 }
342
343
344
345
346
347
348 protected void getAdditionalInfo(final ResultSet _rs)
349 throws SQLException
350 {
351 }
352
353
354
355
356 @Override
357 protected void freeResource()
358 {
359 }
360
361
362
363
364
365
366 protected Instance getInstance()
367 {
368 return this.instance;
369 }
370
371
372
373
374
375
376 protected void setInstance(final Instance _instance)
377 {
378 this.instance = _instance;
379 }
380
381
382
383
384
385
386 protected Compress getCompress()
387 {
388 Compress compress;
389 if (this.store.getResourceProperties().containsKey(Store.PROPERTY_COMPRESS)) {
390 compress = Compress.valueOf(this.store.getResourceProperties().get(Store.PROPERTY_COMPRESS).toUpperCase());
391 } else {
392 compress = Compress.NONE;
393 }
394 return compress;
395 }
396
397
398
399
400
401
402 protected Store getStore()
403 {
404 return this.store;
405 }
406
407
408
409
410
411
412 protected Map<String, String> getProperties()
413 {
414 return this.store.getResourceProperties();
415 }
416
417
418
419
420
421
422 protected boolean[] getExist()
423 {
424 return this.exist;
425 }
426
427
428
429
430
431
432 protected Long getGeneralID()
433 {
434 return this.generalID;
435 }
436
437
438
439
440
441
442 protected StoreEvent getStoreEvent()
443 {
444 return this.storeEvent;
445 }
446
447
448
449
450 protected class StoreResourceInputStream
451 extends InputStream
452 {
453
454
455
456 private final InputStream in;
457
458
459
460
461 private final AbstractStoreResource store;
462
463
464
465
466
467
468 protected StoreResourceInputStream(final AbstractStoreResource _resource,
469 final InputStream _in)
470 throws IOException
471 {
472 this.store = _resource;
473 if (_resource.getCompress().equals(Compress.GZIP)) {
474 this.in = new GZIPInputStream(_in);
475 } else if (_resource.getCompress().equals(Compress.ZIP)) {
476 this.in = new ZipInputStream(_in);
477 } else {
478 this.in = _in;
479 }
480 }
481
482
483
484
485
486
487 protected void beforeClose()
488 throws IOException
489 {
490 if (this.in != null) {
491 this.in.close();
492 }
493 }
494
495
496
497
498
499
500 protected void afterClose()
501 throws IOException
502 {
503 }
504
505
506
507
508
509
510 private void closeWithoutCommit()
511 throws IOException
512 {
513 beforeClose();
514 afterClose();
515 }
516
517
518
519
520
521
522
523
524 @Override
525 public void close()
526 throws IOException
527 {
528 try {
529 super.close();
530 beforeClose();
531 if (this.store.isOpened()) {
532 this.store.commit();
533 }
534 afterClose();
535 } catch (final EFapsException e) {
536 throw new IOException("commit of store not possible", e);
537 } finally {
538 if (this.store.isOpened()) {
539 try {
540 this.store.abort();
541 } catch (final EFapsException e) {
542 throw new IOException("store resource could not be aborted", e);
543 }
544 }
545 }
546 }
547
548
549
550
551
552
553 @Override
554 public int available()
555 throws IOException
556 {
557 return this.in == null ? 1 : this.in.available();
558 }
559
560
561
562
563
564 @Override
565 public void mark(final int _readlimit)
566 {
567 this.in.mark(_readlimit);
568 }
569
570
571
572
573
574 @Override
575 public boolean markSupported()
576 {
577 return this.in.markSupported();
578 }
579
580
581
582
583
584
585 @Override
586 public int read()
587 throws IOException
588 {
589 return this.in.read();
590 }
591
592
593
594
595
596
597
598
599
600 @Override
601 public int read(final byte[] _b)
602 throws IOException
603 {
604 return this.in == null ? -1 : this.in.read(_b);
605 }
606
607
608
609
610
611
612
613
614
615
616
617 @Override
618 public int read(final byte[] _b,
619 final int _off,
620 final int _len)
621 throws IOException
622 {
623 return this.in == null ? -1 : this.in.read(_b, _off, _len);
624 }
625
626
627
628
629
630 @Override
631 public void reset()
632 throws IOException
633 {
634 if (this.in != null) {
635 this.in.reset();
636 }
637 }
638
639
640
641
642
643
644
645 @Override
646 public long skip(final long _n)
647 throws IOException
648 {
649 return this.in == null ? 0 : this.in.skip(_n);
650 }
651 }
652 }