001 /*
002 GRANITE DATA SERVICES
003 Copyright (C) 2012 GRANITE DATA SERVICES S.A.S.
004
005 This file is part of Granite Data Services.
006
007 Granite Data Services is free software; you can redistribute it and/or modify
008 it under the terms of the GNU Library General Public License as published by
009 the Free Software Foundation; either version 2 of the License, or (at your
010 option) any later version.
011
012 Granite Data Services is distributed in the hope that it will be useful, but
013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015 for more details.
016
017 You should have received a copy of the GNU Library General Public License
018 along with this library; if not, see <http://www.gnu.org/licenses/>.
019 */
020
021 package org.granite.client.tide.impl;
022
023 import java.util.concurrent.ExecutionException;
024
025 import org.granite.client.messaging.events.CancelledEvent;
026 import org.granite.client.messaging.events.FailureEvent;
027 import org.granite.client.messaging.events.FaultEvent;
028 import org.granite.client.messaging.events.ResultEvent;
029 import org.granite.client.messaging.events.TimeoutEvent;
030 import org.granite.client.tide.Context;
031 import org.granite.client.tide.server.Component;
032 import org.granite.client.tide.server.ComponentListener;
033 import org.granite.client.tide.server.FaultException;
034 import org.granite.client.tide.server.TideResponder;
035
036 /**
037 * @author William DRAI
038 */
039 public class ComponentListenerImpl<T> implements ComponentListener<T> {
040
041 private Context sourceContext;
042 private Component component;
043 private String componentName;
044 private String operation;
045 private Object[] args;
046 private Handler<T> handler;
047 private TideResponder<T> tideResponder;
048 private Object info;
049 private boolean waiting = false;
050 private Runnable responseHandler = null;
051 private T result = null;
052 private Exception exception = null;
053
054
055 public ComponentListenerImpl(Context sourceContext, Handler<T>handler, Component component, String operation, Object[] args, Object info, TideResponder<T> tideResponder) {
056 this.sourceContext = sourceContext;
057 this.handler = handler;
058 this.component = component;
059 this.componentName = component != null ? component.getName() : null;
060 this.operation = operation;
061 this.args = args;
062 this.tideResponder = tideResponder;
063 this.info = info;
064 }
065
066 public String getOperation() {
067 return operation;
068 }
069
070 public Object[] getArgs() {
071 return args;
072 }
073 public void setArgs(Object[] args) {
074 this.args = args;
075 }
076
077 public Context getSourceContext() {
078 return sourceContext;
079 }
080
081 public Component getComponent() {
082 return component;
083 }
084
085 public T getResult() throws InterruptedException, ExecutionException {
086 synchronized (this) {
087 if (responseHandler == null && exception == null) {
088 waiting = true;
089 wait();
090 }
091 if (responseHandler != null)
092 responseHandler.run();
093 }
094 if (exception instanceof ExecutionException)
095 throw (ExecutionException)exception;
096 else if (exception instanceof InterruptedException)
097 throw (InterruptedException)exception;
098 return result;
099 }
100
101 public void setResult(T result) {
102 this.result = result;
103 }
104
105 @Override
106 public void onResult(ResultEvent event) {
107 Runnable h = handler.result(sourceContext, event, info, componentName, operation, tideResponder, this);
108 synchronized (this) {
109 responseHandler = h;
110 if (waiting)
111 notifyAll();
112 else
113 sourceContext.callLater(h);
114 }
115 }
116
117 @Override
118 public void onFault(FaultEvent event) {
119 Runnable h = handler.fault(sourceContext, event, info, componentName, operation, tideResponder, this);
120 synchronized (this) {
121 responseHandler = h;
122 exception = new FaultException(event);
123 if (waiting)
124 notifyAll();
125 else
126 sourceContext.callLater(h);
127 }
128 }
129
130 @Override
131 public void onFailure(final FailureEvent event) {
132 synchronized (this) {
133 exception = new ExecutionException(event.getCause());
134 if (waiting)
135 notifyAll();
136 }
137 }
138
139 @Override
140 public void onTimeout(TimeoutEvent event) {
141 synchronized (this) {
142 exception = new InterruptedException("timeout");
143 if (waiting)
144 notifyAll();
145 }
146 }
147
148 @Override
149 public void onCancelled(CancelledEvent event) {
150 synchronized (this) {
151 exception = new InterruptedException("cancel");
152 if (waiting)
153 notifyAll();
154 }
155 }
156 }