View Javadoc

1   /*
2    * Copyright 2005 Jukka Zitting <jz@yukatan.fi>
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package net.sf.exorcist.midgard;
17  
18  import java.io.ByteArrayInputStream;
19  import java.io.ByteArrayOutputStream;
20  import java.io.File;
21  import java.io.FileFilter;
22  import java.io.FileInputStream;
23  import java.io.IOException;
24  import java.io.InputStream;
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.Iterator;
31  
32  import javax.xml.parsers.ParserConfigurationException;
33  
34  import org.xml.sax.SAXException;
35  
36  import net.sf.exorcist.api.ContentException;
37  import net.sf.exorcist.api.ContentExporter;
38  import net.sf.exorcist.api.ContentState;
39  
40  public class MidgardExporter implements ContentExporter {
41  
42      static {
43          try {
44              Class.forName("com.mysql.jdbc.Driver");
45          } catch (ClassNotFoundException e) {
46              e.printStackTrace();
47          }
48      }
49  
50      private ContentState state;
51  
52      private DOMBuilder builder;
53  
54      private Connection connection;
55  
56      private GUIDResolver guidFinder;
57  
58      private MidgardSchema schema;
59  
60      private int sitegroup;
61  
62      private String database;
63  
64      private String username;
65  
66      private String password;
67  
68      private String filepath;
69  
70      public void setSitegroup(int sitegroup) {
71          this.sitegroup = sitegroup;
72      }
73  
74      public void setSchema(String file)
75              throws IOException, ParserConfigurationException, SAXException {
76          schema = new MidgardSchema();
77          schema.parse(new FileInputStream(file));
78      }
79      
80      public void setFilepath(String filepath) {
81          this.filepath = filepath;
82      }
83  
84      public void setDatabase(String database) {
85          this.database = database;
86      }
87  
88      public void setUsername(String username) {
89          this.username = username;
90      }
91  
92      public void setPassword(String password) {
93          this.password = password;
94      }
95  
96      public void exportContent(ContentState state) throws ContentException {
97          try {
98              if (schema == null) {
99                  InputStream input = MidgardExporter.class.getClassLoader()
100                     .getResourceAsStream("net/sf/exorcist/midgard/midgard.xml");
101                 try {
102                     schema = new MidgardSchema();
103                     schema.parse(input);
104                 } finally {
105                     input.close();
106                 }
107             }
108 
109             this.state = state;
110             this.connection =
111                 DriverManager.getConnection(database, username, password);
112             this.guidFinder = new GUIDResolver(connection);
113 
114             builder = new DOMBuilder(
115                     "site", "http://ns.yukatan.fi/2005/midgard", "mgd");
116             exportAll(schema);
117             ByteArrayOutputStream xml = new ByteArrayOutputStream();
118             builder.write(xml);
119             state.setContent(new ByteArrayInputStream(xml.toByteArray()));
120         } catch (SQLException e) {
121             throw new ContentException(e);
122         } catch (IOException e) {
123             throw new ContentException(e);
124         } catch (SAXException e) {
125             throw new ContentException(e);
126         } catch (ParserConfigurationException e) {
127             throw new ContentException(e);
128         }
129     }
130 
131     private void exportAll(MidgardSchema schema) throws IOException, SQLException {
132         Iterator types = schema.getTypes();
133         while (types.hasNext()) {
134             MidgardType type = (MidgardType) types.next();
135             MidgardProperty primary = type.getPrimary();
136             MidgardProperty parent = type.getParent();
137 
138             StringBuffer sql = new StringBuffer();
139             sql.append("SELECT ");
140             sql.append(primary.getName());
141             Iterator properties = type.getProperties();
142             while (properties.hasNext()) {
143                 MidgardProperty property = (MidgardProperty) properties.next();
144                 if (property != primary && property != parent) {
145                     sql.append(", ");
146                     sql.append(property.getName());
147                 }
148             }
149             sql.append(" FROM ");
150             sql.append(type.getTable());
151             sql.append(" WHERE sitegroup=?");
152             if (parent != null) {
153                 sql.append(" AND ");
154                 sql.append(parent.getName());
155                 sql.append(" = ?");
156             }
157             PreparedStatement ps = connection.prepareStatement(sql.toString());
158             try {
159                 ps.setInt(1, sitegroup);
160                 if (parent != null) {
161                     ps.setInt(2, 0);
162                 }
163 
164                 ResultSet rs = ps.executeQuery();
165                 try {
166                     while (rs.next()) {
167                         builder.startElement(type.getName());
168                         int id = rs.getInt(1);
169                         builder.addContentElement(
170                                 "guid", guidFinder.findGUID(type.getTable(), id));
171                         properties = type.getProperties();
172                         while (properties.hasNext()) {
173                             MidgardProperty property = (MidgardProperty) properties.next();
174                             if (property != primary && property != parent) {
175                                 MidgardType link = property.getLink();
176                                 if (link != null) {
177                                     builder.addContentElement(
178                                             property.getName(),
179                                             guidFinder.findGUID(link.getTable(), rs.getInt(property.getName())));
180                                 } else {
181                                     builder.addContentElement(
182                                             property.getName(),
183                                             rs.getString(property.getName()));
184                                 }
185                             }
186                         }
187                         exportParameters(type.getTable(), id);
188                         exportAttachments(type.getTable(), id);
189                         exportChildren(type, id);
190                         builder.endElement();
191                     }
192                 } finally {
193                     rs.close();
194                 }
195             } finally {
196                 ps.close();
197             }
198         }
199     }
200 
201     private void exportChildren(MidgardType type, int id)
202             throws IOException, SQLException {
203         Iterator children = type.getChildren();
204         while (children.hasNext()) {
205             MidgardType child = (MidgardType) children.next();
206             MidgardProperty primary = child.getPrimary();
207             MidgardProperty parent = child.getParent();
208 
209             StringBuffer sql = new StringBuffer();
210             sql.append("SELECT ");
211             sql.append(primary.getName());
212             Iterator properties = child.getProperties();
213             while (properties.hasNext()) {
214                 MidgardProperty property = (MidgardProperty) properties.next();
215                 if (property != primary && property != parent) {
216                     sql.append(", ");
217                     sql.append(property.getName());
218                 }
219             }
220             sql.append(" FROM ");
221             sql.append(child.getTable());
222             sql.append(" WHERE sitegroup=?");
223             if (parent != null) {
224                 sql.append(" AND ");
225                 sql.append(parent.getName());
226                 sql.append(" = ?");
227             }
228             PreparedStatement ps = connection.prepareStatement(sql.toString());
229             try {
230                 ps.setInt(1, sitegroup);
231                 if (parent != null) {
232                     ps.setInt(2, id);
233                 }
234 
235                 ResultSet rs = ps.executeQuery();
236                 try {
237                     while (rs.next()) {
238                         if (child.getName().equals("midgard_article")
239                             && rs.getInt("type") == 2) {
240                             continue;
241                         }
242                         builder.startElement(child.getName());
243                         int childId = rs.getInt(1);
244                         builder.addContentElement(
245                                 "guid", guidFinder.findGUID(child.getTable(), childId));
246                         properties = child.getProperties();
247                         while (properties.hasNext()) {
248                             MidgardProperty property = (MidgardProperty) properties.next();
249                             if (property != primary && property != parent) {
250                                 MidgardType link = property.getLink();
251                                 if (link != null) {
252                                     builder.addContentElement(
253                                             property.getName(),
254                                             guidFinder.findGUID(link.getTable(), rs.getInt(property.getName())));
255                                 } else {
256                                     builder.addContentElement(
257                                             property.getName(),
258                                             rs.getString(property.getName()));
259                                 }
260                             }
261                         }
262                         exportParameters(child.getTable(), childId);
263                         exportAttachments(child.getTable(), childId);
264                         exportChildren(child, childId);
265                         builder.endElement();
266                     }
267                 } finally {
268                     rs.close();
269                 }
270             } finally {
271                 ps.close();
272             }
273         }
274     }
275 
276     private void exportParameters(String table, int id) throws SQLException {
277         PreparedStatement ps = connection.prepareStatement(
278                 "SELECT domain, name, value FROM record_extension"
279                 + " WHERE tablename = ? AND oid = ? AND sitegroup = ?");
280         try {
281             ps.setString(1, table);
282             ps.setInt(2, id);
283             ps.setInt(3, sitegroup);
284             ResultSet rs = ps.executeQuery();
285             try {
286                 while (rs.next()) {
287                     builder.startElement("parameter");
288                     builder.addContentElement("domain", rs.getString("domain"));
289                     builder.addContentElement("name", rs.getString("name"));
290                     builder.addContentElement("value", rs.getString("value"));
291                     builder.endElement();
292                 }
293             } finally {
294                 rs.close();
295             }
296         } finally {
297             ps.close();
298         }
299     }
300 
301     private void exportAttachments(String table, int id)
302             throws IOException, SQLException {
303         PreparedStatement ps = connection.prepareStatement(
304                 "SELECT id, name, title, location, mimetype, author, created"
305                 + " FROM blobs WHERE ptable = ? AND pid = ? AND sitegroup = ?"
306                 + " ORDER BY score, name");
307         try {
308             ps.setString(1, table);
309             ps.setInt(2, id);
310             ps.setInt(3, sitegroup);
311             ResultSet rs = ps.executeQuery();
312             try {
313                 while (rs.next()) {
314                     String name = rs.getString("name");
315                     String location = rs.getString("location");
316                     File file = new File(filepath, location);
317                     if (file.exists() && !name.startsWith("__")) {
318                         InputStream input = new FileInputStream(filepath + location);
319                         try {
320                             String hash = state.addAttachment(input);
321                             builder.startElement("attachment");
322                             builder.addContentElement(
323                                     "guid", guidFinder.findGUID("blobs", rs.getInt("id")));
324                             builder.addContentElement("name", name);
325                             builder.addContentElement("title", rs.getString("title"));
326                             builder.addContentElement("mimetype", rs.getString("mimetype"));
327                             builder.addContentElement("location", hash);
328                             builder.addContentElement(
329                                     "author", guidFinder.findGUID("person", rs.getInt("author")));
330                             builder.addContentElement("created", rs.getString("created"));
331                             builder.endElement();
332                         } finally {
333                             input.close();
334                         }
335                     }
336                 }
337             } finally {
338                 rs.close();
339             }
340         } finally {
341             ps.close();
342         }
343     }
344 
345 }