Java tutorial
/* ***** BEGIN LICENSE BLOCK ***** * Version: GPL 2.0 * * The contents of this file are subject to the GNU General Public * License Version 2 or later (the "GPL"). * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Initial Developer of the Original Code is * MiniG.org project members * * ***** END LICENSE BLOCK ***** */ package org.minig.imap.sieve; import java.io.InputStream; import java.net.SocketAddress; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.mina.common.ConnectFuture; import org.apache.mina.common.IoHandler; import org.apache.mina.common.IoSession; import org.apache.mina.transport.socket.nio.SocketConnector; import org.minig.imap.sieve.commands.SieveActivate; import org.minig.imap.sieve.commands.SieveAuthenticate; import org.minig.imap.sieve.commands.SieveDeleteScript; import org.minig.imap.sieve.commands.SieveListscripts; import org.minig.imap.sieve.commands.SievePutscript; import org.minig.imap.sieve.commands.SieveUnauthenticate; public class SieveClientSupport { private static final Log logger = LogFactory.getLog(SieveClientSupport.class); private Semaphore lock; private IoSession session; private List<SieveResponse> lastResponses; private SieveAuthenticate authenticate; public SieveClientSupport(String login, String password) { this.lock = new Semaphore(1); this.lastResponses = new LinkedList<SieveResponse>(); this.authenticate = new SieveAuthenticate(login, password); } private void lock() { try { boolean ret = lock.tryAcquire(1000, TimeUnit.MILLISECONDS); if (!ret) { throw new RuntimeException("cannot acquire lock !!!"); } } catch (InterruptedException e) { logger.error(e.getMessage()); } } public boolean login(SocketConnector connector, SocketAddress sa, IoHandler handler) { if (session != null && session.isConnected()) { throw new IllegalStateException("Already connected. Disconnect first."); } try { // wait for // "IMPLEMENTATION" "Cyrus timsieved v2.2.13-Debian-2.2.13-10" // "SASL" "PLAIN" // "SIEVE" // "fileinto reject envelope vacation imapflags notify subaddress relational comparator-i;ascii-numeric regex" // "STARTTLS" // OK lock(); ConnectFuture cf = connector.connect(sa, handler); cf.join(); if (!cf.isConnected()) { return false; } session = cf.getSession(); if (logger.isDebugEnabled()) { logger.debug("Connection established, sending login."); } return run(authenticate); } catch (Exception e) { logger.error("login error", e); return false; } } public void logout() { if (session != null) { session.close().join(); session = null; } } private <T> T run(SieveCommand<T> cmd) { if (logger.isDebugEnabled()) { logger.debug("running command " + cmd); } // grab lock, this one should be ok, except on first call // where we might wait for sieve welcome text. lock(); cmd.execute(session, lastResponses); lock(); // this one should wait until this.setResponses is called try { cmd.responseReceived(lastResponses); } catch (Throwable t) { logger.error("receiving/parsing sieve response to cmd " + cmd.getClass().getSimpleName(), t); } finally { lock.release(); } return cmd.getReceivedData(); } public void setResponses(ArrayList<SieveResponse> copy) { if (logger.isDebugEnabled()) { logger.debug("in setResponses on " + Integer.toHexString(hashCode())); } lastResponses.clear(); lastResponses.addAll(copy); lock.release(); } public List<SieveScript> listscripts() { return run(new SieveListscripts()); } public boolean putscript(String name, InputStream scriptContent) { return run(new SievePutscript(name, scriptContent)); } public void unauthenticate() { run(new SieveUnauthenticate()); } public boolean deletescript(String name) { return run(new SieveDeleteScript(name)); } public void activate(String newName) { run(new SieveActivate(newName)); } }