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.maildir.user; 020 021import java.io.BufferedReader; 022import java.io.File; 023import java.io.FileReader; 024import java.io.FileWriter; 025import java.io.IOException; 026import java.io.PrintWriter; 027import java.util.ArrayList; 028import java.util.Collections; 029import java.util.HashSet; 030import java.util.List; 031import java.util.Set; 032 033import org.apache.james.mailbox.exception.SubscriptionException; 034import org.apache.james.mailbox.maildir.MaildirStore; 035import org.apache.james.mailbox.store.transaction.NonTransactionalMapper; 036import org.apache.james.mailbox.store.user.SubscriptionMapper; 037import org.apache.james.mailbox.store.user.model.Subscription; 038import org.apache.james.mailbox.store.user.model.impl.SimpleSubscription; 039 040public class MaildirSubscriptionMapper extends NonTransactionalMapper implements SubscriptionMapper { 041 042 private static final String FILE_SUBSCRIPTION = "subscriptions"; 043 private MaildirStore store; 044 045 public MaildirSubscriptionMapper(MaildirStore store) { 046 this.store = store; 047 } 048 049 /** 050 * @see org.apache.james.mailbox.store.user.SubscriptionMapper#delete(org.apache.james.mailbox.store.user.model.Subscription) 051 */ 052 @Override 053 public void delete(Subscription subscription) throws SubscriptionException { 054 // TODO: we need some kind of file locking here 055 Set<String> subscriptionNames = readSubscriptionsForUser(subscription.getUser()); 056 boolean changed = subscriptionNames.remove(subscription.getMailbox()); 057 if (changed) { 058 try { 059 writeSubscriptions(new File(store.userRoot(subscription.getUser())), subscriptionNames); 060 } catch (IOException e) { 061 throw new SubscriptionException(e); 062 } 063 } 064 } 065 066 /** 067 * @see org.apache.james.mailbox.store.user.SubscriptionMapper#findSubscriptionsForUser(java.lang.String) 068 */ 069 @Override 070 public List<Subscription> findSubscriptionsForUser(String user) throws SubscriptionException { 071 Set<String> subscriptionNames = readSubscriptionsForUser(user); 072 ArrayList<Subscription> subscriptions = new ArrayList<Subscription>(); 073 for (String subscription : subscriptionNames) { 074 subscriptions.add(new SimpleSubscription(user, subscription)); 075 } 076 return subscriptions; 077 } 078 079 /** 080 * @see org.apache.james.mailbox.store.user.SubscriptionMapper#findMailboxSubscriptionForUser(java.lang.String, java.lang.String) 081 */ 082 @Override 083 public Subscription findMailboxSubscriptionForUser(String user, String mailbox) throws SubscriptionException { 084 File userRoot = new File(store.userRoot(user)); 085 Set<String> subscriptionNames; 086 try { 087 subscriptionNames = readSubscriptions(userRoot); 088 } catch (IOException e) { 089 throw new SubscriptionException(e); 090 } 091 if (subscriptionNames.contains(mailbox)) 092 return new SimpleSubscription(user, mailbox); 093 return null; 094 } 095 096 /** 097 * @see org.apache.james.mailbox.store.user.SubscriptionMapper#save(org.apache.james.mailbox.store.user.model.Subscription) 098 */ 099 @Override 100 public void save(Subscription subscription) throws SubscriptionException { 101 // TODO: we need some kind of file locking here 102 Set<String> subscriptionNames = readSubscriptionsForUser(subscription.getUser()); 103 boolean changed = subscriptionNames.add(subscription.getMailbox()); 104 if (changed) { 105 try { 106 writeSubscriptions(new File(store.userRoot(subscription.getUser())), subscriptionNames); 107 } catch (IOException e) { 108 throw new SubscriptionException(e); 109 } 110 } 111 } 112 113 /** 114 * @see org.apache.james.mailbox.store.transaction.TransactionalMapper#endRequest() 115 */ 116 @Override 117 public void endRequest() { 118 // nothing to do 119 } 120 121 122 /** 123 * Read the subscriptions for a particular user 124 * @param user The user to get the subscriptions for 125 * @return A Set of names of subscribed mailboxes of the user 126 * @throws SubscriptionException 127 */ 128 private Set<String> readSubscriptionsForUser(String user) throws SubscriptionException { 129 File userRoot = new File(store.userRoot(user)); 130 Set<String> subscriptionNames; 131 try { 132 subscriptionNames = readSubscriptions(userRoot); 133 } catch (IOException e) { 134 throw new SubscriptionException(e); 135 } 136 return subscriptionNames; 137 } 138 139 /** 140 * Read the names of the mailboxes which are subscribed from the specified folder 141 * @param mailboxFolder The folder which contains the subscription file 142 * @return A Set of names of subscribed mailboxes 143 * @throws IOException 144 */ 145 private Set<String> readSubscriptions(File mailboxFolder) throws IOException { 146 File subscriptionFile = new File(mailboxFolder, FILE_SUBSCRIPTION); 147 HashSet<String> subscriptions = new HashSet<String>(); 148 if (!subscriptionFile.exists()) { 149 return subscriptions; 150 } 151 FileReader fileReader = new FileReader(subscriptionFile); 152 BufferedReader reader = new BufferedReader(fileReader); 153 String subscription; 154 while ((subscription = reader.readLine()) != null) 155 if (!subscription.equals("")) 156 subscriptions.add(subscription); 157 reader.close(); 158 fileReader.close(); 159 return subscriptions; 160 } 161 162 /** 163 * Write the set of mailbox names into the subscriptions file in the specified folder 164 * @param mailboxFolder Folder which contains the subscriptions file 165 * @param subscriptions Set of names of subscribed mailboxes 166 * @throws IOException 167 */ 168 private void writeSubscriptions(File mailboxFolder, final Set<String> subscriptions) throws IOException { 169 List<String> sortedSubscriptions = new ArrayList<String>(subscriptions); 170 Collections.sort(sortedSubscriptions); 171 if (!mailboxFolder.exists()) 172 if (!mailboxFolder.mkdirs()) 173 throw new IOException("Could not create folder " + mailboxFolder); 174 175 File subscriptionFile = new File(mailboxFolder, FILE_SUBSCRIPTION); 176 if (!subscriptionFile.exists()) 177 if (!subscriptionFile.createNewFile()) 178 throw new IOException("Could not create file " + subscriptionFile); 179 180 FileWriter fileWriter = new FileWriter(subscriptionFile); 181 PrintWriter writer = new PrintWriter(fileWriter); 182 for (String subscription : sortedSubscriptions) 183 writer.println(subscription); 184 writer.close(); 185 fileWriter.close(); 186 } 187 188}