/* * JLibs: Common Utilities for Java * Copyright (C) 2009 Santhosh Kumar T <santhosh.tekuri@gmail.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. */ package jlibs.nio.listeners; import jlibs.nio.Connection; import jlibs.nio.Input; import jlibs.nio.Output; import jlibs.nio.Reactor; import static java.nio.channels.SelectionKey.OP_READ; import static java.nio.channels.SelectionKey.OP_WRITE; /** * @author Santhosh Kumar Tekuri */ public class IOListener implements Input.Listener, Output.Listener{ private Task task; public void start(Task task, Input in, Output out){ this.task = task; if(in!=null) in.setInputListener(this); if(out!=null) out.setOutputListener(this); task.init(this, in, out); process(task.firstOp); } public void start(Task task, Connection con){ start(task, con.in(), con.out()); } @Override public void process(Input in){ process(OP_READ); } @Override public void process(Output out){ process(OP_WRITE); } @SuppressWarnings("unchecked") private void process(int readyOp){ Throwable error = null; try{ while(true){ Throwable taskError = null; try{ if(!task.process(readyOp)) return; }catch(Throwable thr){ taskError = thr; } task = taskFinished(taskError); if(task==null) break; readyOp = task.firstOp; } }catch(Throwable thr){ error = thr; } try{ if(callback!=null) callback.completed(attachment, error); else if(error!=null) Reactor.current().handleException(error); }catch(Throwable thr){ Reactor.current().handleException(error); } } private Task taskFinished(Throwable thr) throws Throwable{ if(thr!=null || task.child==null) task.cleanup(thr); if(thr==null && task.child!=null){ Task next = task.child; task.child = null; return next; } Task parent = task.parent; task.parent = null; if(parent==null){ if(thr!=null) throw thr; }else parent.firstOp = parent.childTaskFinished(task, thr); return parent; } public interface Callback<A>{ public void completed(A attachment, Throwable thr); } private Callback callback; private Object attachment; public <A> IOListener setCallback(Callback<A> callback, A attachment){ this.callback = callback; this.attachment = attachment; return this; } }