001/****************************************************************
002 * Licensed to the Apache Software Foundation (ASF) under one   *
003 * or more contributor license agreements.  See the NOTICE file *
004 * distributed with this work for additional information        *
005 * regarding copyright ownership.  The ASF licenses this file   *
006 * to you under the Apache License, Version 2.0 (the            *
007 * "License"); you may not use this file except in compliance   *
008 * with the License.  You may obtain a copy of the License at   *
009 *                                                              *
010 *   http://www.apache.org/licenses/LICENSE-2.0                 *
011 *                                                              *
012 * Unless required by applicable law or agreed to in writing,   *
013 * software distributed under the License is distributed on an  *
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
015 * KIND, either express or implied.  See the License for the    *
016 * specific language governing permissions and limitations      *
017 * under the License.                                           *
018 ****************************************************************/
019package org.apache.james.mailbox.jpa.migrator.command;
020
021import java.util.List;
022
023import javax.persistence.EntityManager;
024import javax.persistence.Query;
025
026import org.apache.james.mailbox.jpa.migrator.exception.JpaMigrateException;
027
028/**
029 * <p>
030 * JIRA IMAP-168 is "mailboxes can't be identified 100% unambiguously using virtual hosting".
031 * 
032 * MAILBOX.NAME contains data such as 
033 * "#mail.eric@localhost.net"
034 * "#mail.eric@localhost.net.INBOX"
035 * "#mail.eric@localhost.net.INBOX.test"
036 * "#mail.eric@localhost.net.Trash"
037 * 
038 * It needs to be splitted into MAILBOX.NAMESPACE | MAILBOX.USER0 | MAILBOX.NAME with 
039 * "#mail" | "eric@localhost.net" | "" ==> was created before, but is not used anymore
040 * "#mail" | "eric@localhost.net" | "INBOX"
041 * "#mail" | "eric@localhost.net" | "INBOX.test"
042 * "#mail" | "eric@localhost.net" | "Trash"
043 *</p>
044 *
045 * @link https://issues.apache.org/jira/browse/IMAP-168
046 * 
047 */
048public class IMAP168JpaMigrateCommand implements JpaMigrateCommand {
049
050    /**
051     * @see org.apache.james.mailbox.jpa.migrator.command#migrate(javax.persistence.EntityManager)
052     */
053    public void migrate(EntityManager em) throws JpaMigrateException {
054
055        JpaMigrateQuery.executeUpdate(em, "ALTER TABLE MAILBOX ADD COLUMN NAMESPACE VARCHAR(255)");
056        JpaMigrateQuery.executeUpdate(em, "ALTER TABLE MAILBOX ADD COLUMN USER0 VARCHAR(255)");
057
058        Query query = em.createNativeQuery("SELECT NAME FROM MAILBOX");
059        
060        @SuppressWarnings("unchecked")
061        List<String> nameList = query.getResultList();
062        System.out.println("getResultList returned a result=" + nameList.size());
063        for (String name: nameList) {
064            MailboxPath mailboxPath = new MailboxPath(name);
065            System.out.println(mailboxPath);
066            Query update = em.createNativeQuery("UPDATE MAILBOX SET NAMESPACE = ?, USER0 = ?, NAME = ? WHERE NAME = ?");
067            update.setParameter(1, mailboxPath.namespace);
068            update.setParameter(2, mailboxPath.userName);
069            update.setParameter(3, mailboxPath.mailboxName);
070            update.setParameter(4, name);
071            int resultUpdate = update.executeUpdate();
072            System.out.println("ExecuteUpdate returned a result=" + resultUpdate);
073        }
074
075    }
076
077    /**
078     *
079     */
080    private class MailboxPath {
081
082        protected String namespace;
083        protected String userName;
084        protected String mailboxName;
085
086        /**
087         * @param name
088         */
089        public MailboxPath (String name) {
090            
091            if (! name.startsWith("#mail")) {
092                throw new IllegalArgumentException("The name must begin with #private");
093            }
094            
095            namespace = "#mail";
096
097            name = name.substring(6);
098            
099            int atIndex = name.indexOf("@");
100            int firstDotIndex = name.indexOf(".", atIndex);
101            int secondDotIndex = name.indexOf(".", firstDotIndex + 1);
102            
103            if (secondDotIndex > 0) {
104                userName = name.substring(0, secondDotIndex);
105                mailboxName = name.substring(userName.length() + 1);
106            }
107            else {
108                // We don't have a mailbox name...
109                userName = name.substring(0);
110                mailboxName = "";
111            }
112            
113        }
114
115        @Override
116        public String toString() {
117            return "MailboxPath [namespace=" + namespace + 
118                ", userName=" + userName + ", mailboxName=" + mailboxName + "]";
119        }
120
121    }
122
123}