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.easysiter;
17  
18  import java.io.ByteArrayInputStream;
19  import java.io.ByteArrayOutputStream;
20  import java.io.File;
21  import java.io.FileInputStream;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.sql.Connection;
25  import java.sql.DriverManager;
26  import java.sql.PreparedStatement;
27  import java.sql.ResultSet;
28  import java.sql.SQLException;
29  import java.util.HashMap;
30  import java.util.Map;
31  import java.util.regex.Matcher;
32  import java.util.regex.Pattern;
33  
34  import net.sf.exorcist.api.ContentException;
35  import net.sf.exorcist.api.ContentExporter;
36  import net.sf.exorcist.api.ContentState;
37  import net.sf.exorcist.core.memory.MemoryContentState;
38  
39  import org.apache.commons.codec.binary.Base64;
40  import org.apache.xml.serialize.OutputFormat;
41  import org.apache.xml.serialize.XMLSerializer;
42  import org.xml.sax.ContentHandler;
43  import org.xml.sax.SAXException;
44  
45  
46  public class EasySiterExporter implements ContentExporter {
47  
48      private static final String NAMESPACE =
49          "http://ns.yukatan.fi/2005/easysiter";
50  
51      private static final String PREFIX = "easy";
52  
53      private String database;
54  
55      private String username;
56  
57      private String password;
58  
59      private String filepath;
60  
61      private boolean extended;
62  
63      private Connection connection;
64  
65      private ContentState target;
66  
67      private ContentHandler handler;
68  
69      private Map users = new HashMap();
70  
71      private Map services = new HashMap();
72  
73      public void setDatabase(String database) {
74          this.database = database;
75      }
76  
77      public void setUsername(String username) {
78          this.username = username;
79      }
80  
81      public void setPassword(String password) {
82          this.password = password;
83      }
84  
85      public void setFilepath(String filepath) {
86          this.filepath = filepath;
87      }
88  
89      public void setExtended(String extended) {
90          this.extended = Boolean.valueOf(extended).booleanValue();
91      }
92  
93      public void exportContent(ContentState target) throws ContentException {
94          try {
95              ByteArrayOutputStream xml = new ByteArrayOutputStream();
96              OutputFormat format = new OutputFormat();
97              format.setIndenting(true);
98              XMLSerializer serializer = new XMLSerializer(xml, format);
99              
100             this.target = target;
101             this.handler = serializer.asContentHandler();
102             connection =
103                 DriverManager.getConnection(database, username, password);
104             try {
105                 initUsers();
106                 initServices();
107 
108                 handler.startDocument();
109                 handler.startPrefixMapping(PREFIX, NAMESPACE);
110                 startElement("site");
111                 exportGroups();
112                 exportMenus(0);
113                 endElement("site");
114                 handler.endPrefixMapping(PREFIX);
115                 handler.endDocument();
116             } finally {
117                 try { connection.close(); } catch (Exception e) {}
118             }
119 
120             target.setContent(new ByteArrayInputStream(xml.toByteArray()));
121         } catch (SQLException e) {
122             throw new ContentException(e);
123         } catch (SAXException e) {
124             throw new ContentException(e);
125         } catch (IOException e) {
126             throw new ContentException(e);
127         }
128     }
129 
130     private void startElement(String name) throws SAXException {
131         handler.startElement(NAMESPACE, name, PREFIX + ":" + name, null);
132     }
133     
134     private void endElement(String name) throws SAXException {
135         handler.endElement(NAMESPACE, name, PREFIX + ":" + name);
136     }
137 
138     private void addElement(String name, String content) throws SAXException {
139         startElement(name);
140         if (content != null) {
141             char [] characters = content.replaceAll("\r\n", "\n").toCharArray();
142             handler.characters(characters, 0, characters.length);
143         }
144         endElement(name);
145     }
146 
147     private void exportGroups() throws SQLException, SAXException {
148         PreparedStatement ps = connection.prepareStatement(
149                 "SELECT id,name FROM groups ORDER BY id");
150         try {
151             ResultSet rs = ps.executeQuery();
152             try {
153                 while (rs.next()) {
154                     startElement("group");
155                     addElement("name", rs.getString(2));
156                     exportUsers(rs.getInt(1));
157                     endElement("group");
158                 }
159             } finally {
160                 try { rs.close(); } catch (Exception e) {}
161             }
162         } finally {
163             try { ps.close(); } catch (Exception e) {}
164         }
165     }
166     
167     private void exportUsers(int group) throws SQLException, SAXException {
168         PreparedStatement ps = connection.prepareStatement(
169                 "SELECT name, passwd,"
170                 + " IF(nimi IS NULL OR nimi = '',name,nimi),"
171                 + " osoite, email, puhelin,"
172                 + " IFNULL(NULLIF(created,0),modified),"
173                 + " IFNULL(createdby,modifiedby),"
174                 + " modified, modifiedby"
175                 + " FROM users WHERE groupid = ? AND disabled = 0"
176                 + " AND (expires IS NULL OR expires > NOW()) ORDER BY id");
177         try {
178             ps.setInt(1, group);
179             ResultSet rs = ps.executeQuery();
180             try {
181                 while (rs.next()) {
182                     startElement("user");
183                     addElement("username", rs.getString(1));
184                     addElement("password", rs.getString(2));
185                     addElement("name", rs.getString(3));
186                     addElement("address", rs.getString(4));
187                     addElement("email", rs.getString(5));
188                     addElement("phone", rs.getString(6));
189                     addElement("created", rs.getString(7));
190                     addElement("createdby", getUser(rs.getInt(8)));
191                     addElement("modified", rs.getString(9));
192                     addElement("modifiedby", getUser(rs.getInt(10)));
193                     endElement("user");
194                 }
195             } finally {
196                 try { rs.close(); } catch (Exception e) {}
197             }
198         } finally {
199             try { ps.close(); } catch (Exception e) {}
200         }
201     }
202 
203     private void initUsers() throws SQLException {
204         PreparedStatement ps =
205             connection.prepareStatement("SELECT id, name FROM users");
206         try {
207             ResultSet rs = ps.executeQuery();
208             try {
209                 while (rs.next()) {
210                     users.put(new Integer(rs.getInt(1)), rs.getString(2));
211                 }
212             } finally {
213                 try { rs.close(); } catch (Exception e) {}
214             }
215         } finally {
216             try { ps.close(); } catch (Exception e) {}
217         }
218     }
219 
220     private String getUser(int id) {
221         return (String) users.get(new Integer(id));
222     }
223 
224     private void initServices() throws SQLException {
225         PreparedStatement ps =
226             connection.prepareStatement("SELECT id, name FROM services");
227         try {
228             ResultSet rs = ps.executeQuery();
229             try {
230                 while (rs.next()) {
231                     services.put(new Integer(rs.getInt(1)), rs.getString(2));
232                 }
233             } finally {
234                 try { rs.close(); } catch (Exception e) {}
235             }
236         } finally {
237             try { ps.close(); } catch (Exception e) {}
238         }
239     }
240 
241     private String getService(int id) {
242         return (String) services.get(new Integer(id));
243     }
244 
245     private void exportMenus(int parent)
246             throws SQLException, IOException, SAXException {
247         String sql;
248         if (extended) {
249             sql = "SELECT id, name, service,"
250                 + " IFNULL(NULLIF(publish,0),modified),"
251                 + " IFNULL(NULLIF(created,0),modified),"
252                 + " IFNULL(NULLIF(createdby,''),modifiedby),"
253                 + " modified, modifiedby"
254                 + " FROM menu WHERE subid = ? AND deleted = 0 AND disabled = 0"
255                 + " ORDER BY pos, id";
256         } else {
257             sql = "SELECT id, name, service,"
258                 + " IFNULL(NULLIF(publish,0),NOW()), NOW(), '', NOW(), ''"
259                 + " FROM menu WHERE subid = ? AND deleted = 0 ORDER BY pos, id";
260         }
261         PreparedStatement ps = connection.prepareStatement(sql);
262         try {
263             ps.setInt(1, parent);
264             ResultSet rs = ps.executeQuery();
265             try {
266                 while (rs.next()) {
267                     startElement("menu");
268                     addElement("name", unword(rs.getString(2)));
269                     addElement("service", getService(rs.getInt(3)));
270                     addElement("publish", rs.getString(4));
271                     addElement("created", rs.getString(5));
272                     addElement("createdby", getUser(rs.getInt(6)));
273                     addElement("modified", rs.getString(7));
274                     addElement("modifiedby", getUser(rs.getInt(8)));
275                     exportWWW(rs.getInt(1));
276                     exportNews(rs.getInt(1));
277                     exportMenus(rs.getInt(1));
278                     endElement("menu");
279                 }
280             } finally {
281                 try { rs.close(); } catch (Exception e) {}
282             }
283         } finally {
284             try { ps.close(); } catch (Exception e) {}
285         }
286     }
287 
288     private void exportWWW(int menu)
289             throws SQLException, IOException, SAXException {
290         String sql;
291         if (extended) {
292             sql = "SELECT data,"
293                 + " IFNULL(NULLIF(created,0),modified),"
294                 + " IFNULL(NULLIF(createdby,''),modifiedby),"
295                 + " modified, modifiedby"
296                 + " FROM datawww WHERE menuid = ? AND deleted = 0 ORDER BY id";
297         } else {
298             sql = "SELECT data, NOW(), '', NOW(), ''"
299                 + " FROM datawww WHERE menuid = ? AND deleted = 0 ORDER BY id";
300         }
301         PreparedStatement ps = connection.prepareStatement(sql);
302         try {
303             ps.setInt(1, menu);
304             ResultSet rs = ps.executeQuery();
305             try {
306                 while (rs.next()) {
307                     startElement("www");
308                     String data = getClean(rs.getString(1));
309                     String html = getFormatted(data);
310                     addElement("title", unword(getTitle(data)));
311                     addElement("data", html);
312                     addElement("created", rs.getString(2));
313                     addElement("createdby", getUser(rs.getInt(3)));
314                     addElement("modified", rs.getString(4));
315                     addElement("modifiedby", getUser(rs.getInt(5)));
316                     exportImages(html);
317                     endElement("www");
318                 }
319             } finally {
320                 try { rs.close(); } catch (Exception e) {}
321             }
322         } finally {
323             try { ps.close(); } catch (Exception e) {}
324         }
325     }
326 
327     private void exportNews(int menu)
328             throws SQLException, IOException, SAXException {
329         PreparedStatement ps = connection.prepareStatement(
330                 "SELECT data, mod, IFNULL(NULLIF(publish,0),mod)"
331                 + " FROM datanews WHERE menuid = ? AND deleted = 0"
332                 + " ORDER BY id");
333         try {
334             ps.setInt(1, menu);
335             ResultSet rs = ps.executeQuery();
336             try {
337                 while (rs.next()) {
338                     startElement("news");
339                     String data = getClean(rs.getString(1));
340                     String html = getFormatted(data);
341                     addElement("title", unword(getTitle(data)));
342                     addElement("data", html);
343                     addElement("mod", rs.getString(2));
344                     addElement("publish", rs.getString(3));
345                     exportImages(html);
346                     endElement("news");
347                 }
348             } finally {
349                 try { rs.close(); } catch (Exception e) {}
350             }
351         } finally {
352             try { ps.close(); } catch (Exception e) {}
353         }
354     }
355 
356     private String getClean(String data) {
357         if (data == null) {
358             return "";
359         } else {
360             return data.replaceAll("\0", "").replaceAll("\r\n", "\n");
361         }
362     }
363 
364     private String getTitle(String data) {
365         data = data.replace('\0', ' ');
366         Matcher matcher =
367             Pattern.compile("<ts (.*?)>(.*?)</ts>").matcher(data);
368         if (matcher.find()) {
369             return matcher.group(2).replaceAll("<[^>]+>", "");
370         } else {
371             Matcher matcher2 =
372                 Pattern.compile("(.*?)\r?\n").matcher(data);
373             if (matcher2.find()) {
374                 return matcher2.group(1).replaceAll("<[^>]+>", "");
375             } else {
376                 return "";
377             }
378         }
379     }
380 
381     private String getFormatted(String data) {
382         data = data.replaceAll(
383                 "<ts (.*?)>(.*?)</ts>", "<span class=\"$1\">$2</span>");
384         data = data.replaceAll(
385                 "<colou?r (.*?)>(.*?)</colou?r>",
386                 "<span style=\"color: #$1\">$2</span>");
387         data = data.replaceAll(
388                 "<url (.*?) +([a-z]+=.*?)>(.*?)</url>", "<a href=\"$1\">$3</a>");
389         data = data.replaceAll(
390                 "<url (.*?) *>(.*?)</url>", "<a href=\"$1\">$2</a>");
391         data = data.replaceAll(
392                 "<email (.*?) *>(.*?)</email>", "<a href=\"mailto:$1\">$2</a>");
393         data = data.replaceAll(
394                 "<kuva (.*?) +kuvateksti=(.*?) +kuvacss=(.*?) +paikka=oikea +hspace=(.*?) vspace=(.*?)>",
395                 "<img src=\"$1\" alt=\"$2\" class=\"$3\" hspace=\"$4\" vspace=\"$5\" align=\"right\" />");
396         data = data.replaceAll(
397                 "<kuva (.*?) +kuvateksti=(.*?) +kuvacss=(.*?) +hspace=(.*?) +vspace=(.*?) tasaus=(.*?)>",
398                 "<img src=\"$1\" alt=\"$2\" class=\"$3\" hspace=\"$4\" vspace=\"$5\" align=\"$6\" />");
399         data = data.replaceAll(
400                 "<kuva (.*?) +hspace=(.*?) +vspace=(.*?) +tasaus=(.*?)>",
401                 "<img src=\"$1\" hspace=\"$2\" vspace=\"$3\" align=\"$4\" />");
402         data = data.replaceAll(
403                 "<kuva ([^=]*?) +kuvateksti=(.*?) +tasaus=(.*?)>", "<img src=\"$1\" alt=\"$2\" align=\"$3\" />");
404         data = data.replaceAll(
405                 "<kuva ([^=]*?) +tasaus=(.*?)>", "<img src=\"$1\" align=\"$2\" />");
406         data = data.replaceAll(
407                 "<kuva ([^=]*?) +([a-z]+=.*?)>", "<img src=\"$1\" />");
408         data = data.replaceAll(
409                 "<kuva (.*?) *>", "<img src=\"$1\" />");
410         data = data.replaceAll(
411                 "<img src=\"([^\">]+)>", "<img src=\"$1\" />");
412         return unword(data);
413     }
414 
415     private static final String unword(String data) {
416         data = data.replace('\u0080', '\u20ac');
417         data = data.replace('\u0091', '\'');
418         data = data.replace('\u0092', '\'');
419         data = data.replace('\u0093', '"');
420         data = data.replace('\u0094', '"');
421         data = data.replace('\u0096', '-');
422         return data;
423     }
424 
425     private void exportImages(String html) throws SAXException, IOException {
426         Matcher matcher = Pattern.compile("<img src=\"(.*?)\"").matcher(html);
427         while (matcher.find()) {
428             String name = matcher.group(1);
429             File file = new File(filepath, name);
430             if (file.exists()) {
431                 InputStream input = new FileInputStream(file);
432                 try {
433                     String hash = target.addAttachment(input);
434                     startElement("image");
435                     addElement("name", name);
436                     addElement("data", hash);
437                     endElement("image");
438                     System.out.println("Added image: " + name);
439                 } finally {
440                     try { input.close(); } catch (Exception e) {}
441                 }
442             }
443         }
444     }
445 
446 }