/** * MailArchiver is an application that provides services for storing and managing e-mail messages through a Web Services SOAP interface. * Copyright (C) 2012 Marcio Andre Scholl Levien and Fernando Alberto Reuter Wendt and Jose Ronaldo Nogueira Fonseca Junior * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ /******************************************************************************\ * * This product was developed by * * SERVIÇO FEDERAL DE PROCESSAMENTO DE DADOS (SERPRO), * * a government company established under Brazilian law (5.615/70), * at Department of Development of Porto Alegre. * \******************************************************************************/ package serpro.mailarchiver.session; import java.nio.file.Files; import java.nio.file.Path; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; import java.util.UUID; import java.util.concurrent.BlockingQueue; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.LinkedBlockingQueue; import org.apache.commons.lang3.mutable.MutableBoolean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Configurable; import serpro.mailarchiver.service.Utils; import serpro.mailarchiver.service.dto.TFault; import serpro.mailarchiver.util.Logger; import serpro.mailarchiver.util.LuceneIndex; @Configurable(preConstruction=true) public class Session { private static final Logger log = Logger.getLocalLogger(); @Autowired private Utils utils; private static final InheritableThreadLocal threadSession = new InheritableThreadLocal(); public static void setThreadSession(Session session) { threadSession.set(session); } public static Session getThreadSession() { return threadSession.get(); } public static String internalizeFolderId(String id) { if((id == null) || id.isEmpty() || id.endsWith("home")) { return getHomeFolderId(); } else if(id.endsWith("inbox")) { return getInboxFolderId(); } else if(id.endsWith("outbox")) { return getOutboxFolderId(); } else if(id.endsWith("drafts")) { return getDraftsFolderId(); } else if(id.endsWith("sent")) { return getSentFolderId(); } else if(id.endsWith("spam")) { return getSpamFolderId(); } else if(id.endsWith("trash")) { return getTrashFolderId(); } else { return id; } } public static String getHomeFolderId() { return "_" + getThreadSession().userId.toLowerCase() + "_home"; } public static String getInboxFolderId() { return "_" + getThreadSession().userId.toLowerCase() + "_inbox"; } public static String getOutboxFolderId() { return "_" + getThreadSession().userId.toLowerCase() + "_outbox"; } public static String getDraftsFolderId() { return "_" + getThreadSession().userId.toLowerCase() + "_drafts"; } public static String getSentFolderId() { return "_" + getThreadSession().userId.toLowerCase() + "_sent"; } public static String getSpamFolderId() { return "_" + getThreadSession().userId.toLowerCase() + "_spam"; } public static String getTrashFolderId() { return "_" + getThreadSession().userId.toLowerCase() + "_trash"; } public static LuceneIndex getLuceneIndex() { return getThreadSession().index; } //-------------------------------------------------------------------------- private final String sessionId; private final String userId; private final LuceneIndex index; public Session(String userId) throws Exception { try { sessionId = UUID.randomUUID().toString(); this.userId = userId; Session.setThreadSession(this); SessionMap.put(this); utils.provideMailHome(userId); index = LuceneIndex.getInstance(userId); Path indexAbsolutePath = index.getAbsolutePath(); if(Files.notExists(indexAbsolutePath)) { Files.createDirectory(indexAbsolutePath); } startGateKeeper(); log.info("new session:%s user:%s", sessionId, userId); } catch(Exception ex) { SessionMap.remove(this); Session.setThreadSession(null); throw ex; } } public String getUserId() { return userId; } public String getSessionId() { return sessionId; } public LuceneIndex getIndex() { return index; } //-------------------------------------------------------------------------- private final BlockingQueue queue = new LinkedBlockingQueue(); private final CyclicBarrier barrier = new CyclicBarrier(2); final void startGateKeeper() { new Thread() { @Override public void run() { for(;;) { MutableBoolean waitSlot = null; try { waitSlot = queue.take(); } catch(InterruptedException ex) { log.warn(ex); } synchronized(waitSlot) { waitSlot.setValue(true); waitSlot.notify(); } try { barrier.await(); } catch(InterruptedException ex) { log.warn(ex); } catch(BrokenBarrierException ex) { log.warn(ex); } barrier.reset(); } } } .start(); } public void enroll() { final MutableBoolean waitSlot = new MutableBoolean(false); try { queue.put(waitSlot); } catch(InterruptedException ex) { log.warn(ex); } synchronized(waitSlot) { while(waitSlot.isFalse()) { try { waitSlot.wait(); } catch(InterruptedException ex) { log.warn(ex); } } } } public void depart() { try { barrier.await(); } catch(InterruptedException ex) { log.warn(ex); } catch(BrokenBarrierException ex) { log.warn(ex); } } //-------------------------------------------------------------------------- private TFault lastFault; public TFault getLastFault() { return lastFault; } public void setLastFault(TFault lastFault) { this.lastFault = lastFault; } //-------------------------------------------------------------------------- private final Map statistics = new TreeMap() { @Override public String toString() { StringBuilder sb = new StringBuilder(); for(Entry entry : entrySet()) { if(sb.length() > 0) { sb.append("\n"); } sb.append(entry.getKey()).append(": ").append(entry.getValue()); } return sb.toString(); } }; public void incStatistics(String name) { Long n = statistics.get(name); if(n == null) { statistics.put(name, 1L); } else { statistics.put(name, ++n); } } public void clearStatistics() { statistics.clear(); } public Map getStatistics() { return statistics; } }