comparison artifact-database/src/main/java/de/intevation/artifactdatabase/Backend.java @ 32:c2d53bd30ab8

Re-factored artifact API for better integration of background processing. artifacts/trunk@78 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Sun, 13 Sep 2009 14:50:53 +0000
parents c4d85a8532d1
children 9935e1c928de
comparison
equal deleted inserted replaced
31:c4d85a8532d1 32:c2d53bd30ab8
1 package de.intevation.artifactdatabase; 1 package de.intevation.artifactdatabase;
2
3 import org.w3c.dom.Document;
4 2
5 import java.util.UUID; 3 import java.util.UUID;
6 4
7 import java.sql.Connection; 5 import java.sql.Connection;
8 import java.sql.SQLException; 6 import java.sql.SQLException;
15 import java.io.IOException; 13 import java.io.IOException;
16 import java.io.ByteArrayInputStream; 14 import java.io.ByteArrayInputStream;
17 import java.io.ByteArrayOutputStream; 15 import java.io.ByteArrayOutputStream;
18 import java.io.ObjectOutputStream; 16 import java.io.ObjectOutputStream;
19 import java.io.ObjectInputStream; 17 import java.io.ObjectInputStream;
20 import java.io.OutputStream;
21 18
22 import java.util.zip.GZIPOutputStream; 19 import java.util.zip.GZIPOutputStream;
23 import java.util.zip.GZIPInputStream; 20 import java.util.zip.GZIPInputStream;
24 21
25 import de.intevation.artifacts.ArtifactFactory;
26 import de.intevation.artifacts.Artifact; 22 import de.intevation.artifacts.Artifact;
27 23
28 import org.apache.log4j.Logger; 24 import org.apache.log4j.Logger;
29 25
30 /** 26 /**
49 public static final String SQL_LOAD_BY_GID = 45 public static final String SQL_LOAD_BY_GID =
50 SQL.get("artifacts.select.gid"); 46 SQL.get("artifacts.select.gid");
51 47
52 protected DatabaseCleaner cleaner; 48 protected DatabaseCleaner cleaner;
53 49
54 /** 50 public final class PersistentArtifact
55 * Used to wrap the calls to invole database actions. 51 extends Id
56 */
57 public class ArtifactProxy
58 implements Artifact
59 { 52 {
60 protected Artifact original; 53 private Artifact artifact;
61 protected int id; 54
62 protected boolean unwritten; 55 public PersistentArtifact(Artifact artifact, int id) {
63 56 super(id);
64 public ArtifactProxy() { 57 this.artifact = artifact;
65 } 58 }
66 59
67 public ArtifactProxy(Artifact original, int id, boolean unwritten) { 60 public Artifact getArtifact() {
68 this.original = original; 61 return artifact;
69 this.id = id; 62 }
70 this.unwritten = unwritten; 63
71 } 64 public void store() {
72 65 Backend.this.store(this);
73 public Artifact getOriginal() { 66 }
74 return original; 67
75 } 68 public void touch() {
76 69 Backend.this.touch(this);
77 public int getId() { 70 }
78 return id; 71 } // class ArtifactWithId
79 }
80
81 public boolean isUnwritten() {
82 return unwritten;
83 }
84
85 public String identifier() {
86 return original.identifier();
87 }
88
89 public String hash() {
90 return original.hash();
91 }
92
93 public Document describe(Object context) {
94 try {
95 return original.describe(context);
96 }
97 finally {
98 touch(this);
99 }
100 }
101
102 public Document advance(Document target, Object context) {
103 try {
104 return original.advance(target, context);
105 }
106 finally {
107 store(this);
108 }
109 }
110
111 public Document feed(Document data, Object context) {
112 try {
113 return original.feed(data, context);
114 }
115 finally {
116 store(this);
117 }
118 }
119
120 public void out(
121 Document format,
122 OutputStream output,
123 Object context
124 )
125 throws IOException
126 {
127 try {
128 original.out(format, output, context);
129 }
130 finally {
131 touch(this);
132 }
133 }
134
135 public void setup(String identifier, ArtifactFactory factory, Object context) {
136 original.setup(identifier, factory, context);
137 }
138
139 public void endOfLife(Object context) {
140 original.endOfLife(context);
141 }
142
143 public byte [] toBytes() {
144 try {
145 ByteArrayOutputStream bos = new ByteArrayOutputStream();
146 GZIPOutputStream gos = new GZIPOutputStream(bos);
147 ObjectOutputStream oos = new ObjectOutputStream(gos);
148
149 oos.writeObject(original);
150 oos.flush();
151 oos.close();
152
153 return bos.toByteArray();
154 }
155 catch (IOException ioe) {
156 logger.error(ioe.getLocalizedMessage(), ioe);
157 throw new RuntimeException(ioe);
158 }
159 }
160 } // class ArtifactProxy
161 72
162 public Backend() { 73 public Backend() {
163 } 74 }
164 75
165 public Backend(DatabaseCleaner cleaner) { 76 public Backend(DatabaseCleaner cleaner) {
166 this.cleaner = cleaner; 77 this.cleaner = cleaner;
167 } 78 }
168 79
169 public Artifact getArtifact(String idenitfier) { 80 public void setCleaner(DatabaseCleaner cleaner) {
170 UUID uuid; 81 this.cleaner = cleaner;
171 82 }
172 try { 83
173 uuid = UUID.fromString(idenitfier); 84 public String newIdentifier() {
85 UUID uuid = UUID.randomUUID();
86 // TODO: check database for collisions.
87 return uuid.toString();
88 }
89
90 public PersistentArtifact storeInitially(
91 Artifact artifact,
92 Long ttl
93 )
94 throws Exception
95 {
96 return new PersistentArtifact(
97 artifact,
98 insertDatabase(artifact, ttl));
99 }
100
101 public PersistentArtifact getArtifact(String identifer) {
102
103 try {
104 UUID.fromString(identifer);
174 } 105 }
175 catch (IllegalArgumentException iae) { 106 catch (IllegalArgumentException iae) {
176 logger.warn(iae.getLocalizedMessage()); 107 logger.warn(iae.getLocalizedMessage());
177 return null; 108 return null;
178 } 109 }
179 110
180 return getArtifactByUUID(uuid);
181 }
182
183 public Artifact createArtifactWithFactory(
184 ArtifactFactory factory, Object context
185 ) {
186 UUID uuid = UUID.randomUUID();
187 Artifact artifact = factory.createArtifact(
188 uuid.toString(), context);
189
190 Long ttl = factory.timeToLiveUntouched(
191 artifact, context);
192
193 try {
194 int id = insertDatabase(uuid, ttl);
195 return new ArtifactProxy(artifact, id, true);
196 }
197 catch (Exception e) {
198 logger.error(e.getLocalizedMessage(), e);
199 }
200 return null;
201 }
202
203 protected Artifact getArtifactByUUID(UUID uuid) {
204
205 Connection connection = null; 111 Connection connection = null;
206 PreparedStatement stmnt_load = null; 112 PreparedStatement stmnt_load = null;
207 ResultSet load_result = null; 113 ResultSet load_result = null;
208 114
209 DataSource dataSource = DBConnection.getDataSource(); 115 DataSource dataSource = DBConnection.getDataSource();
210 try { 116 try {
211 connection = dataSource.getConnection(); 117 connection = dataSource.getConnection();
212 stmnt_load = connection.prepareStatement(SQL_LOAD_BY_GID); 118 stmnt_load = connection.prepareStatement(SQL_LOAD_BY_GID);
213 stmnt_load.setString(1, uuid.toString()); 119 stmnt_load.setString(1, identifer);
214 120
215 load_result = stmnt_load.executeQuery(); 121 load_result = stmnt_load.executeQuery();
216 122
217 if (!load_result.next()) { 123 if (!load_result.next()) {
218 return null; 124 return null;
229 } 135 }
230 } 136 }
231 137
232 byte [] bytes = load_result.getBytes(4); 138 byte [] bytes = load_result.getBytes(4);
233 139
234 if (bytes == null) { 140 Artifact artifact = restoreArtifact(bytes);
235 return null; 141
236 } 142 return artifact == null
237 143 ? null
238 Artifact original = restoreArtifact(bytes); 144 : new PersistentArtifact(artifact, id);
239 if (original == null) {
240 return null;
241 }
242
243 return new ArtifactProxy(original, id, false);
244 } 145 }
245 catch (SQLException sqle) { 146 catch (SQLException sqle) {
246 logger.error(sqle.getLocalizedMessage(), sqle); 147 logger.error(sqle.getLocalizedMessage(), sqle);
247 } 148 }
248 finally { 149 finally {
258 try { connection.close(); } 159 try { connection.close(); }
259 catch (SQLException sqle) {} 160 catch (SQLException sqle) {}
260 } 161 }
261 } 162 }
262 return null; 163 return null;
164 }
165
166 public static byte [] toBytes(Artifact artifact) {
167 try {
168 ByteArrayOutputStream bos = new ByteArrayOutputStream();
169 GZIPOutputStream gos = new GZIPOutputStream(bos);
170 ObjectOutputStream oos = new ObjectOutputStream(gos);
171
172 oos.writeObject(artifact);
173 oos.flush();
174 oos.close();
175
176 return bos.toByteArray();
177 }
178 catch (IOException ioe) {
179 logger.error(ioe.getLocalizedMessage(), ioe);
180 throw new RuntimeException(ioe);
181 }
263 } 182 }
264 183
265 public static Artifact restoreArtifact(byte [] bytes) { 184 public static Artifact restoreArtifact(byte [] bytes) {
266 185
267 if (bytes == null) { 186 if (bytes == null) {
301 if (cleaner != null) { 220 if (cleaner != null) {
302 cleaner.wakeup(); 221 cleaner.wakeup();
303 } 222 }
304 } 223 }
305 224
306 protected int insertDatabase(UUID uuid, Long ttl) { 225 protected int insertDatabase(Artifact artifact, Long ttl) {
226
227 String uuid = artifact.identifier();
228
307 Connection connection = null; 229 Connection connection = null;
308 PreparedStatement stmnt_next_id = null; 230 PreparedStatement stmnt_next_id = null;
309 PreparedStatement stmnt_insert = null; 231 PreparedStatement stmnt_insert = null;
310 ResultSet res_id = null; 232 ResultSet res_id = null;
311 233
325 } 247 }
326 248
327 int id = res_id.getInt(1); 249 int id = res_id.getInt(1);
328 250
329 stmnt_insert.setInt(1, id); 251 stmnt_insert.setInt(1, id);
330 stmnt_insert.setString(2, uuid.toString()); 252 stmnt_insert.setString(2, uuid);
331 if (ttl == null) { 253 if (ttl == null) {
332 stmnt_insert.setNull(3, Types.BIGINT); 254 stmnt_insert.setNull(3, Types.BIGINT);
333 } 255 }
334 else { 256 else {
335 stmnt_insert.setLong(3, ttl.longValue()); 257 stmnt_insert.setLong(3, ttl.longValue());
336 } 258 }
259
260 stmnt_insert.setBytes(4, toBytes(artifact));
337 261
338 stmnt_insert.execute(); 262 stmnt_insert.execute();
339 263
340 connection.commit(); 264 connection.commit();
341 265
368 } 292 }
369 } 293 }
370 throw new RuntimeException("failed insert artifact into database"); 294 throw new RuntimeException("failed insert artifact into database");
371 } 295 }
372 296
373 public void touch(ArtifactProxy proxy) { 297 public void touch(PersistentArtifact artifact) {
374
375 if (proxy.isUnwritten()) {
376 store(proxy);
377 return;
378 }
379 298
380 try { 299 try {
381 Connection connection = null; 300 Connection connection = null;
382 PreparedStatement stmnt_touch = null; 301 PreparedStatement stmnt_touch = null;
383 DataSource dataSource = DBConnection.getDataSource(); 302 DataSource dataSource = DBConnection.getDataSource();
384 try { 303 try {
385 connection = dataSource.getConnection(); 304 connection = dataSource.getConnection();
386 try { 305 try {
387 connection.setAutoCommit(false); 306 connection.setAutoCommit(false);
388 stmnt_touch = connection.prepareStatement(SQL_UPDATE); 307 stmnt_touch = connection.prepareStatement(SQL_UPDATE);
389 stmnt_touch.setInt(1, proxy.getId()); 308 stmnt_touch.setInt(1, artifact.getId());
390 stmnt_touch.execute(); 309 stmnt_touch.execute();
391 connection.commit(); 310 connection.commit();
392 } 311 }
393 catch (SQLException sqle) { 312 catch (SQLException sqle) {
394 connection.rollback(); 313 connection.rollback();
411 catch (Exception e) { 330 catch (Exception e) {
412 logger.error(e.getLocalizedMessage(), e); 331 logger.error(e.getLocalizedMessage(), e);
413 } 332 }
414 } 333 }
415 334
416 public void store(ArtifactProxy proxy) { 335 public void store(PersistentArtifact artifact) {
417 336
418 try { 337 try {
419 Connection connection = null; 338 Connection connection = null;
420 PreparedStatement stmnt_update = null; 339 PreparedStatement stmnt_update = null;
421 DataSource dataSource = DBConnection.getDataSource(); 340 DataSource dataSource = DBConnection.getDataSource();
422 try { 341 try {
423 connection = dataSource.getConnection(); 342 connection = dataSource.getConnection();
424 try { 343 try {
425 connection.setAutoCommit(false); 344 connection.setAutoCommit(false);
426 stmnt_update = connection.prepareStatement(SQL_UPDATE); 345 stmnt_update = connection.prepareStatement(SQL_UPDATE);
427 stmnt_update.setInt(2, proxy.getId()); 346 stmnt_update.setInt(2, artifact.getId());
428 347
429 byte [] bytes = proxy.toBytes(); 348 byte [] bytes = toBytes(artifact.getArtifact());
430 349
431 stmnt_update.setBytes(1, bytes); 350 stmnt_update.setBytes(1, bytes);
432 stmnt_update.execute(); 351 stmnt_update.execute();
433 connection.commit(); 352 connection.commit();
434 } 353 }
452 } 371 }
453 catch (Exception e) { 372 catch (Exception e) {
454 logger.error(e.getLocalizedMessage(), e); 373 logger.error(e.getLocalizedMessage(), e);
455 } 374 }
456 } 375 }
457
458 } 376 }
459 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8: 377 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8:

http://dive4elements.wald.intevation.org