1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.exorcist.midgard;
17
18 import java.io.File;
19 import java.io.FileFilter;
20 import java.io.FileInputStream;
21 import java.io.FileOutputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.sql.Connection;
26 import java.sql.DriverManager;
27 import java.sql.PreparedStatement;
28 import java.sql.ResultSet;
29 import java.sql.SQLException;
30 import java.util.ArrayList;
31 import java.util.HashSet;
32 import java.util.Iterator;
33 import java.util.Set;
34
35 import javax.xml.parsers.ParserConfigurationException;
36
37 import net.sf.exorcist.api.ContentException;
38 import net.sf.exorcist.api.ContentImporter;
39 import net.sf.exorcist.api.ContentState;
40
41 import org.apache.commons.codec.digest.DigestUtils;
42 import org.xml.sax.SAXException;
43
44
45 public class MidgardImporter implements ContentImporter {
46
47 private static class LinkInfo {
48 int id;
49 String table;
50 String property;
51 String guid;
52 public LinkInfo(int i, String t, String p, String g) {
53 id = i; table = t; property = p; guid = g;
54 }
55 }
56
57 private ContentState state;
58
59 private DOMWalker walker;
60
61 private Connection connection;
62
63 private GUIDResolver guidFinder;
64
65 private MidgardSchema schema;
66
67 private int sitegroup;
68
69 private String database;
70
71 private String username;
72
73 private String password;
74
75 private String filepath;
76
77 private boolean delete = false;
78
79 private Set links;
80 private Set deletes;
81
82 public void setSchema(String file)
83 throws IOException, ParserConfigurationException, SAXException {
84 schema = new MidgardSchema();
85 schema.parse(new FileInputStream(file));
86 }
87
88 public void setSitegroup(String sitegroup) {
89 this.sitegroup = Integer.parseInt(sitegroup);
90 }
91
92 public void setDatabase(String database) {
93 this.database = database;
94 }
95
96 public void setUsername(String username) {
97 this.username = username;
98 }
99
100 public void setPassword(String password) {
101 this.password = password;
102 }
103
104 public void setFilepath(String filepath) {
105 this.filepath = filepath;
106 }
107
108 public void setDelete(boolean delete) {
109 this.delete = delete;
110 }
111
112 private static int guidcount = 0;
113
114 public void importObject(MidgardSchema schema, int parent)
115 throws SQLException, IOException {
116 MidgardType type = schema.getTypeByName(walker.getName());
117 ArrayList properties = new ArrayList();
118 Iterator iterator = type.getProperties();
119 while (iterator.hasNext()) {
120 MidgardProperty property = (MidgardProperty) iterator.next();
121 if (property != type.getPrimary() && property != type.getParent()) {
122 properties.add(property);
123 }
124 }
125
126 System.out.println(parent);
127 String guid = walker.getContent("guid");
128 if (guid == null || guid.length() == 0) {
129 guid = DigestUtils.md5Hex("exorcist:" + System.currentTimeMillis() + ":" + guidcount++);
130 }
131 int id = guidFinder.resolveGUID(guid);
132 StringBuffer sql = new StringBuffer();
133 if (id == 0 && type.getTable().endsWith("_i")) {
134 sql.append("SELECT id FROM ");
135 sql.append(type.getTable());
136 sql.append(" WHERE ");
137 sql.append(type.getParent().getName());
138 sql.append(" = ? AND lang = ?");
139 PreparedStatement ps = connection.prepareStatement(sql.toString());
140 try {
141 ps.setInt(1, parent);
142 ps.setInt(2, Integer.parseInt(walker.getContent("lang")));
143 ResultSet rs = ps.executeQuery();
144 try {
145 if (rs.next()) {
146 id = rs.getInt(1);
147 }
148 } finally {
149 rs.close();
150 }
151 } catch (NumberFormatException e) {
152 } finally {
153 ps.close();
154 }
155 sql = new StringBuffer();
156 }
157 if (id != 0) {
158 sql.append("UPDATE ");
159 sql.append(type.getTable());
160 sql.append(" SET sitegroup=?");
161 if (type.getParent() != null && parent != 0) {
162 sql.append(",");
163 sql.append(type.getParent().getName());
164 sql.append("=?");
165 }
166 for (int i = 0; i < properties.size(); i++) {
167 sql.append(",");
168 sql.append(((MidgardProperty) properties.get(i)).getName());
169 sql.append("=?");
170 }
171 sql.append(" WHERE ");
172 sql.append(type.getPrimary().getName());
173 sql.append("=?");
174 } else {
175 sql.append("INSERT INTO ");
176 sql.append(type.getTable());
177 sql.append("(sitegroup");
178 if (type.getParent() != null) {
179 sql.append(",");
180 sql.append(type.getParent().getName());
181 }
182 for (int i = 0; i < properties.size(); i++) {
183 sql.append(",");
184 sql.append(((MidgardProperty) properties.get(i)).getName());
185 }
186 sql.append(") VALUES (?");
187 if (type.getParent() != null) {
188 if (parent != 0) {
189 sql.append(",?");
190 } else {
191 sql.append(",0");
192 }
193 }
194 for (int i = 0; i < properties.size(); i++) {
195 sql.append(",?");
196 }
197 sql.append(")");
198 }
199
200 PreparedStatement ps = connection.prepareStatement(
201 sql.toString(), PreparedStatement.RETURN_GENERATED_KEYS);
202 try {
203 int col = 1;
204 ps.setInt(col++, sitegroup);
205 if (type.getParent() != null && parent != 0) {
206 ps.setInt(col++, parent);
207 }
208 for (int i = 0; i < properties.size(); i++) {
209 MidgardProperty property = (MidgardProperty) properties.get(i);
210 String value = walker.getContent(property.getName());
211 if (property.getLink() != null) {
212 int link = guidFinder.resolveGUID(value);
213 ps.setInt(col++, link);
214 } else if ("integer".equals(property.getType())) {
215 int val = 0;
216 try {
217 val = Integer.parseInt(value);
218 } catch (NumberFormatException e) {
219 }
220 ps.setInt(col++, val);
221 } else {
222 ps.setString(col++, value);
223 }
224 }
225 if (id != 0) {
226 ps.setInt(col++, id);
227 }
228 ps.executeUpdate();
229 if (id == 0) {
230 ResultSet rs = ps.getGeneratedKeys();
231 try {
232 if (rs.next()) {
233 id = rs.getInt(1);
234 if (guid == null) {
235 guid = guidFinder.findGUID(type.getTable(), id);
236 }
237 PreparedStatement insert = connection.prepareStatement(
238 "INSERT INTO repligard (realm, id, guid,"
239 + " changed, updated, action, sitegroup)"
240 + " VALUES (?, ?, ?, NOW(), NOW(), 'created', ?)");
241 try {
242 insert.setString(1, type.getTable());
243 insert.setInt(2, id);
244 insert.setString(3, guid);
245 insert.setInt(4, sitegroup);
246 insert.executeUpdate();
247 } finally {
248 insert.close();
249 }
250 }
251 } finally {
252 rs.close();
253 }
254 }
255 } finally {
256 ps.close();
257 }
258 deletes.remove(guid);
259
260
261 for (int i = 0; i < properties.size(); i++) {
262 MidgardProperty property = (MidgardProperty) properties.get(i);
263 if (property.getLink() != null) {
264 String value = walker.getContent(property.getName());
265 int link = guidFinder.resolveGUID(value);
266 if (link == 0) {
267 links.add(new LinkInfo(id, type.getTable(), property.getName(), value));
268 }
269 }
270 }
271
272 if (id != 0) {
273 importParameters(type.getTable(), id);
274 importAttachments(type.getTable(), id);
275
276 Iterator children = type.getChildren();
277 while (children.hasNext()) {
278 MidgardType child = (MidgardType) children.next();
279 sql = new StringBuffer();
280 sql.append("SELECT ");
281 sql.append(child.getPrimary().getName());
282 sql.append(" FROM ");
283 sql.append(child.getTable());
284 sql.append(" WHERE sitegroup=? AND ");
285 sql.append(child.getParent().getName());
286 sql.append("=?");
287 ps = connection.prepareStatement(sql.toString());
288 try {
289 ps.setInt(1, sitegroup);
290 ps.setInt(2, id);
291 ResultSet rs = ps.executeQuery();
292 try {
293 while (rs.next()) {
294 guid = guidFinder.findGUID(child.getTable(), rs.getInt(1));
295 deletes.add(guid);
296 }
297 } finally {
298 rs.close();
299 }
300 } finally {
301 ps.close();
302 }
303
304 Object current = walker.getCurrent();
305 while (walker.iterateElements(child.getName(), current)) {
306 importObject(schema, id);
307 }
308 }
309 }
310 }
311
312 public void deleteObject(MidgardSchema schema, String guid) {
313 System.out.println("Removing " + guid);
314
315 }
316
317 public void importContent(ContentState state) throws ContentException {
318 try {
319 if (schema == null) {
320 InputStream input = MidgardExporter.class.getClassLoader()
321 .getResourceAsStream("net/sf/exorcist/midgard/midgard.xml");
322 try {
323 schema = new MidgardSchema();
324 schema.parse(input);
325 } finally {
326 input.close();
327 }
328 }
329
330 this.state = state;
331 InputStream xml = state.getContent();
332 this.walker = new DOMWalker(xml, "http://ns.yukatan.fi/2005/midgard");
333 this.connection =
334 DriverManager.getConnection(database, username, password);
335 this.guidFinder = new GUIDResolver(connection);
336 this.deletes = new HashSet();
337 this.links = new HashSet();
338
339 Iterator types = schema.getTypes();
340 while (types.hasNext()) {
341 MidgardType child = (MidgardType) types.next();
342 Object current = walker.getCurrent();
343 while (walker.iterateElements(child.getName(), current)) {
344 importObject(schema, 0);
345 }
346 }
347 if (delete) {
348 Iterator guids = deletes.iterator();
349 while (guids.hasNext()) {
350 deleteObject(schema, (String) guids.next());
351 }
352 }
353
354 Iterator lis = links.iterator();
355 while (lis.hasNext()) {
356 LinkInfo info = (LinkInfo) lis.next();
357 int tid = guidFinder.resolveGUID(info.guid);
358 if (tid != 0) {
359 PreparedStatement ps = connection.prepareStatement(
360 "UPDATE " + info.table + " SET " + info.property
361 + " = " + tid + " WHERE id = " + info.id);
362 try {
363 ps.executeUpdate();
364 } finally {
365 ps.close();
366 }
367 } else {
368 System.err.println("Broken link: " + info.guid);
369 }
370 }
371
372 xml.close();
373 } catch (SQLException e) {
374 throw new ContentException(e);
375 } catch (IOException e) {
376 throw new ContentException(e);
377 } catch (SAXException e) {
378 throw new ContentException(e);
379 } catch (ParserConfigurationException e) {
380 throw new ContentException(e);
381 }
382 }
383
384 private void importParameters(String table, int id) throws SQLException {
385 PreparedStatement ps = connection.prepareStatement(
386 "SELECT id FROM record_extension WHERE tablename=? AND oid=? AND sitegroup=?");
387 try {
388 ps.setString(1, table);
389 ps.setInt(2, id);
390 ps.setInt(3, sitegroup);
391 ResultSet rs = ps.executeQuery();
392 try {
393 while (rs.next()) {
394 deletes.add(guidFinder.findGUID("record_extension", rs.getInt(1)));
395 }
396 } finally {
397 rs.close();
398 }
399 } finally {
400 ps.close();
401 }
402
403 Object context = walker.getCurrent();
404 while (walker.iterateElements("parameter", context)) {
405 int pid = 0;
406 String guid = walker.getContent("guid");
407 PreparedStatement select = connection.prepareStatement(
408 "SELECT id FROM repligard WHERE guid=?");
409 select.setString(1, guid);
410 ResultSet rs = select.executeQuery();
411 try {
412 PreparedStatement update;
413 if (!rs.next()) {
414 update = connection.prepareStatement(
415 "INSERT INTO record_extension (value,"
416 + " tablename, oid, domain, name, sitegroup)"
417 + " VALUES (?, ?, ?, ?, ?, ?)", PreparedStatement.RETURN_GENERATED_KEYS);
418 } else {
419 pid = rs.getInt(1);
420 update = connection.prepareStatement(
421 "UPDATE record_extension SET value = ?,"
422 + " tablename = ?, oid = ?, domain = ?,"
423 + " name = ?, sitegroup = ? WHERE id=?");
424 }
425 update.setString(1, walker.getContent("value"));
426 update.setString(2, table);
427 update.setInt(3, id);
428 update.setString(4, walker.getContent("domain"));
429 update.setString(5, walker.getContent("name"));
430 update.setInt(6, sitegroup);
431 if (pid != 0) {
432 update.setInt(7, pid);
433 }
434 update.executeUpdate();
435 if (pid == 0) {
436 ResultSet keys = update.getGeneratedKeys();
437 try {
438 if (keys.next()) {
439 pid = keys.getInt(1);
440 if (guid == null || guid.length() == 0) {
441 guid = guidFinder.findGUID("record_extension", pid);
442 }
443 PreparedStatement insert = connection.prepareStatement(
444 "INSERT INTO repligard"
445 + " (realm, id, guid, sitegroup)"
446 + " VALUES (?, ?, ?, ?)");
447 insert.setString(1, "record_extension");
448 insert.setInt(2, pid);
449 insert.setString(3, guid);
450 insert.setInt(4, sitegroup);
451 insert.executeUpdate();
452 insert.close();
453 }
454 } finally {
455 keys.close();
456 }
457 }
458 update.close();
459 } finally {
460 rs.close();
461 }
462 select.close();
463 deletes.remove(guid);
464 }
465 }
466
467 private void importAttachments(String table, int id)
468 throws IOException, SQLException {
469 PreparedStatement ps = connection.prepareStatement(
470 "SELECT id FROM blobs WHERE ptable=? AND pid=? AND sitegroup=?");
471 try {
472 ps.setString(1, table);
473 ps.setInt(2, id);
474 ps.setInt(3, sitegroup);
475 ResultSet rs = ps.executeQuery();
476 try {
477 while (rs.next()) {
478 deletes.add(guidFinder.findGUID("blobs", rs.getInt(1)));
479 }
480 } finally {
481 rs.close();
482 }
483 } finally {
484 ps.close();
485 }
486
487 Object context = walker.getCurrent();
488 while (walker.iterateElements("attachment", context)) {
489 String guid = walker.getContent("guid");
490 String name = walker.getContent("name");
491 String hash = walker.getContent("location");
492 int blobid = 0;
493 String location = null;
494 if (guid != null && guid.length() > 0) {
495 ps = connection.prepareStatement(
496 "SELECT blobs.id, blobs.location FROM blobs, repligard"
497 + " WHERE blobs.id=repligard.id AND repligard.realm='blobs'"
498 + " AND guid=?");
499 try {
500 ps.setString(1, guid);
501 ResultSet rs = ps.executeQuery();
502 try {
503 if (rs.next()) {
504 blobid = rs.getInt(1);
505 location = rs.getString(2);
506 }
507 } finally {
508 rs.close();
509 }
510 } finally {
511 ps.close();
512 }
513 }
514 if (blobid != 0) {
515 ps = connection.prepareStatement(
516 "UPDATE blobs SET score = ?, title = ?,"
517 + " location = ?, mimetype = ?, author = ?,"
518 + " created = ?, ptable = ?, pid = ?, name = ?,"
519 + " lang = 0, sitegroup = ? WHERE id = ?");
520 } else {
521 ps = connection.prepareStatement(
522 "INSERT INTO blobs (score, title, location,"
523 + " mimetype, author, created, ptable, pid,"
524 + " name, lang, sitegroup)"
525 + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?)",
526 PreparedStatement.RETURN_GENERATED_KEYS);
527 location =
528 hash.toUpperCase().charAt(0) + "/"
529 + hash.toUpperCase().charAt(1) + "/"
530 + hash.substring(0, 32);
531 }
532 try {
533 ps.setInt(1, Integer.parseInt(walker.getContent("score")));
534 } catch (NumberFormatException e) {
535 ps.setInt(1, 0);
536 }
537 ps.setString(2, walker.getContent("title"));
538 ps.setString(3, location);
539 ps.setString(4, walker.getContent("mimetype"));
540 ps.setInt(5, guidFinder.resolveGUID(walker.getContent("author")));
541 ps.setString(6, walker.getContent("created"));
542 ps.setString(7, table);
543 ps.setInt(8, id);
544 ps.setString(9, name);
545 ps.setInt(10, sitegroup);
546 if (blobid != 0) {
547 ps.setInt(11, blobid);
548 }
549 ps.executeUpdate();
550 if (blobid == 0) {
551 ResultSet keys = ps.getGeneratedKeys();
552 try {
553 if (keys.next()) {
554 blobid = keys.getInt(1);
555 if (guid == null || guid.length() == 0) {
556 guid = guidFinder.findGUID("blobs", blobid);
557 }
558 PreparedStatement insert = connection.prepareStatement(
559 "INSERT INTO repligard"
560 + " (realm, id, guid, sitegroup)"
561 + " VALUES (?, ?, ?, ?)");
562 insert.setString(1, "blobs");
563 insert.setInt(2, blobid);
564 insert.setString(3, guid);
565 insert.setInt(4, sitegroup);
566 insert.executeUpdate();
567 insert.close();
568 }
569 } finally {
570 keys.close();
571 }
572 }
573 ps.close();
574 deletes.remove(guid);
575
576 File file = new File(filepath, location);
577 file.getParentFile().mkdirs();
578 InputStream input = state.getAttachment(hash);
579 try {
580 OutputStream output = new FileOutputStream(file);
581 try {
582 byte[] buffer = new byte[4096];
583 int n = input.read(buffer);
584 while (n != -1) {
585 output.write(buffer, 0, n);
586 n = input.read(buffer);
587 }
588 } finally {
589 output.close();
590 }
591 } finally {
592 input.close();
593 }
594
595 importParameters("blobs", blobid);
596 }
597 }
598
599 }