1   /****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  package org.apache.james.mailboxmanager.mock;
21  
22  import java.sql.Connection;
23  import java.sql.DatabaseMetaData;
24  import java.sql.ResultSet;
25  import java.sql.SQLException;
26  import java.util.Locale;
27  
28  import org.apache.commons.configuration.BaseConfiguration;
29  import org.apache.james.imap.functional.ExperimentalHostSystem;
30  import org.apache.james.mailboxmanager.manager.MailboxManagerProvider;
31  import org.apache.james.mailboxmanager.torque.TorqueMailboxManager;
32  import org.apache.james.mailboxmanager.torque.om.MailboxRowPeer;
33  import org.apache.james.mailboxmanager.torque.om.MessageBodyPeer;
34  import org.apache.james.mailboxmanager.torque.om.MessageFlagsPeer;
35  import org.apache.james.mailboxmanager.torque.om.MessageHeaderPeer;
36  import org.apache.james.mailboxmanager.torque.om.MessageRowPeer;
37  import org.apache.torque.Torque;
38  import org.apache.torque.util.BasePeer;
39  import org.apache.torque.util.Transaction;
40  
41  public class TorqueMailboxManagerProviderSingleton {
42  
43      // TODO: replicates code in server
44      private static final String[] tableNames = new String[] {
45              MailboxRowPeer.TABLE_NAME, MessageRowPeer.TABLE_NAME,
46              MessageFlagsPeer.TABLE_NAME, MessageHeaderPeer.TABLE_NAME,
47              MessageBodyPeer.TABLE_NAME };
48  
49      // TODO: replicates code in server
50      private static final String[] CREATE_STATEMENTS = {
51              "CREATE TABLE mailbox"
52                      + "("
53                      + "  mailbox_id BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY,"
54                      + "        name VARCHAR(255) NOT NULL,"
55                      + "        uid_validity BIGINT NOT NULL,"
56                      + "        last_uid BIGINT NOT NULL,"
57                      + "        message_count INTEGER default 0,"
58                      + "        size BIGINT default 0,"
59                      + "        PRIMARY KEY(mailbox_id),"
60                      + "        UNIQUE (name))",
61              "        CREATE TABLE message"
62                      + "    ("
63                      + "        mailbox_id BIGINT NOT NULL,"
64                      + "        uid BIGINT NOT NULL,"
65                      + "        internal_date TIMESTAMP,"
66                      + "        size INTEGER,"
67                      + "        PRIMARY KEY(mailbox_id,uid),"
68                      + "        FOREIGN KEY (mailbox_id) REFERENCES mailbox (mailbox_id)"
69                      + "            ON DELETE CASCADE" + "      )",
70              "CREATE TABLE message_flags"
71                      + "    ("
72                      + "        mailbox_id BIGINT NOT NULL,"
73                      + "        uid BIGINT NOT NULL,"
74                      + "        answered INTEGER default 0 NOT NULL,"
75                      + "        deleted INTEGER default 0 NOT NULL,"
76                      + "        draft INTEGER default 0 NOT NULL,"
77                      + "        flagged INTEGER default 0 NOT NULL,"
78                      + "        recent INTEGER default 0 NOT NULL,"
79                      + "        seen INTEGER default 0 NOT NULL,"
80                      + "        PRIMARY KEY(mailbox_id,uid),"
81                      + "        FOREIGN KEY (mailbox_id, uid) REFERENCES message (mailbox_id, uid)"
82                      + "            ON DELETE CASCADE" + "      )",
83              "CREATE TABLE message_header"
84                      + "    ("
85                      + "        mailbox_id BIGINT NOT NULL,"
86                      + "        uid BIGINT NOT NULL,"
87                      + "        line_number INTEGER NOT NULL,"
88                      + "        field VARCHAR(256) NOT NULL,"
89                      + "        value VARCHAR(1024) NOT NULL,"
90                      + "        PRIMARY KEY(mailbox_id,uid,line_number),"
91                      + "        FOREIGN KEY (mailbox_id, uid) REFERENCES message (mailbox_id, uid)"
92                      + "            ON DELETE CASCADE" + "      )",
93              "CREATE TABLE message_body"
94                      + "    ("
95                      + "        mailbox_id BIGINT NOT NULL,"
96                      + "        uid BIGINT NOT NULL,"
97                      + "        body BLOB NOT NULL,"
98                      + "        PRIMARY KEY(mailbox_id,uid),"
99                      + "        FOREIGN KEY (mailbox_id, uid) REFERENCES message (mailbox_id, uid)"
100                     + "            ON DELETE CASCADE" + "      )" };
101 
102     // TODO: replicates code in server
103     public static void initialize() throws Exception {
104         BaseConfiguration torqueConf = configureDefaults();
105         Connection conn = null;
106         Torque.init(torqueConf);
107         conn = Transaction.begin(MailboxRowPeer.DATABASE_NAME);
108 
109         DatabaseMetaData dbMetaData = conn.getMetaData();
110 
111         for (int i = 0; i < tableNames.length; i++) {
112             if (!tableExists(dbMetaData, tableNames[i])) {
113                 BasePeer.executeStatement(CREATE_STATEMENTS[i], conn);
114                 System.out.println("Created table " + tableNames[i]);
115                 System.out.println(CREATE_STATEMENTS[i]);
116             }
117         }
118 
119         Transaction.commit(conn);
120         System.out.println("MailboxManager has been initialized");
121     }
122 
123     // TODO: replicates code in server
124     private static boolean tableExists(DatabaseMetaData dbMetaData,
125             String tableName) throws SQLException {
126         return (tableExistsCaseSensitive(dbMetaData, tableName)
127                 || tableExistsCaseSensitive(dbMetaData, tableName
128                         .toUpperCase(Locale.US)) || tableExistsCaseSensitive(
129                 dbMetaData, tableName.toLowerCase(Locale.US)));
130     }
131 
132     // TODO: replicates code in server
133     private static boolean tableExistsCaseSensitive(
134             DatabaseMetaData dbMetaData, String tableName) throws SQLException {
135         ResultSet rsTables = dbMetaData.getTables(null, null, tableName, null);
136         try {
137             boolean found = rsTables.next();
138             return found;
139         } finally {
140             if (rsTables != null) {
141                 rsTables.close();
142             }
143         }
144     }
145 
146     // TODO: replicates code in server
147     public static BaseConfiguration configureDefaults()
148             throws org.apache.commons.configuration.ConfigurationException {
149         BaseConfiguration torqueConf = new BaseConfiguration();
150         torqueConf.addProperty("torque.database.default", "mailboxmanager");
151         torqueConf.addProperty("torque.database.mailboxmanager.adapter",
152                 "derby");
153         torqueConf.addProperty("torque.dsfactory.mailboxmanager.factory",
154                 "org.apache.torque.dsfactory.SharedPoolDataSourceFactory");
155         torqueConf.addProperty(
156                 "torque.dsfactory.mailboxmanager.connection.driver",
157                 "org.apache.derby.jdbc.EmbeddedDriver");
158         torqueConf.addProperty(
159                 "torque.dsfactory.mailboxmanager.connection.url",
160                 "jdbc:derby:target/testdb;create=true");
161         torqueConf.addProperty(
162                 "torque.dsfactory.mailboxmanager.connection.user", "app");
163         torqueConf.addProperty(
164                 "torque.dsfactory.mailboxmanager.connection.password", "app");
165         torqueConf.addProperty(
166                 "torque.dsfactory.mailboxmanager.pool.maxActive", "100");
167         return torqueConf;
168     }
169 
170     private static TorqueMailboxManager torqueMailboxManager;
171 
172     private static SimpleUserManager userManager;
173 
174     private static SimpleMailboxManagerProvider provider;
175 
176     public static final ExperimentalHostSystem host = new ExperimentalHostSystem();
177 
178     public synchronized static MailboxManagerProvider getTorqueMailboxManagerProviderInstance()
179             throws Exception {
180         if (provider == null) {
181             getMailboxManager();
182             provider = new SimpleMailboxManagerProvider();
183             provider.setMailboxManager(torqueMailboxManager);
184         }
185         return provider;
186 
187     }
188 
189     public static void addUser(String user, String password) {
190         userManager.addUser(user, password);
191     }
192 
193     private static TorqueMailboxManager getMailboxManager() throws Exception {
194         if (torqueMailboxManager == null) {
195             userManager = new SimpleUserManager();
196             initialize();
197             torqueMailboxManager = new TorqueMailboxManager(userManager);
198         }
199         return torqueMailboxManager;
200     }
201 
202     public static void reset() throws Exception {
203         getMailboxManager().deleteEverything();
204     }
205 
206 }