View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.client;
20  
21  import java.nio.ByteBuffer;
22  import java.util.Iterator;
23  import java.util.List;
24  
25  import org.eclipse.jetty.client.api.ContentResponse;
26  import org.eclipse.jetty.client.api.Request;
27  import org.eclipse.jetty.client.api.Response;
28  import org.eclipse.jetty.client.api.Result;
29  import org.eclipse.jetty.http.HttpField;
30  import org.eclipse.jetty.util.log.Log;
31  import org.eclipse.jetty.util.log.Logger;
32  
33  public class ResponseNotifier
34  {
35      private static final Logger LOG = Log.getLogger(ResponseNotifier.class);
36      private final HttpClient client;
37  
38      public ResponseNotifier(HttpClient client)
39      {
40          this.client = client;
41      }
42  
43      @SuppressWarnings("ForLoopReplaceableByForEach")
44      public void notifyBegin(List<Response.ResponseListener> listeners, Response response)
45      {
46          // Optimized to avoid allocations of iterator instances
47          for (int i = 0; i < listeners.size(); ++i)
48          {
49              Response.ResponseListener listener = listeners.get(i);
50              if (listener instanceof Response.BeginListener)
51                  notifyBegin((Response.BeginListener)listener, response);
52          }
53      }
54  
55      private void notifyBegin(Response.BeginListener listener, Response response)
56      {
57          try
58          {
59              listener.onBegin(response);
60          }
61          catch (Exception x)
62          {
63              LOG.info("Exception while notifying listener " + listener, x);
64          }
65      }
66  
67      @SuppressWarnings("ForLoopReplaceableByForEach")
68      public boolean notifyHeader(List<Response.ResponseListener> listeners, Response response, HttpField field)
69      {
70          boolean result = true;
71          // Optimized to avoid allocations of iterator instances
72          for (int i = 0; i < listeners.size(); ++i)
73          {
74              Response.ResponseListener listener = listeners.get(i);
75              if (listener instanceof Response.HeaderListener)
76                  result &= notifyHeader((Response.HeaderListener)listener, response, field);
77          }
78          return result;
79      }
80  
81      private boolean notifyHeader(Response.HeaderListener listener, Response response, HttpField field)
82      {
83          try
84          {
85              return listener.onHeader(response, field);
86          }
87          catch (Exception x)
88          {
89              LOG.info("Exception while notifying listener " + listener, x);
90              return false;
91          }
92      }
93  
94      @SuppressWarnings("ForLoopReplaceableByForEach")
95      public void notifyHeaders(List<Response.ResponseListener> listeners, Response response)
96      {
97          // Optimized to avoid allocations of iterator instances
98          for (int i = 0; i < listeners.size(); ++i)
99          {
100             Response.ResponseListener listener = listeners.get(i);
101             if (listener instanceof Response.HeadersListener)
102                 notifyHeaders((Response.HeadersListener)listener, response);
103         }
104     }
105 
106     private void notifyHeaders(Response.HeadersListener listener, Response response)
107     {
108         try
109         {
110             listener.onHeaders(response);
111         }
112         catch (Exception x)
113         {
114             LOG.info("Exception while notifying listener " + listener, x);
115         }
116     }
117 
118     @SuppressWarnings("ForLoopReplaceableByForEach")
119     public void notifyContent(List<Response.ResponseListener> listeners, Response response, ByteBuffer buffer)
120     {
121         // Slice the buffer to avoid that listeners peek into data they should not look at.
122         buffer = buffer.slice();
123         // Optimized to avoid allocations of iterator instances
124         for (int i = 0; i < listeners.size(); ++i)
125         {
126             Response.ResponseListener listener = listeners.get(i);
127             if (listener instanceof Response.ContentListener)
128             {
129                 // The buffer was sliced, so we always clear it (position=0, limit=capacity)
130                 // before passing it to the listener that may consume it.
131                 buffer.clear();
132                 notifyContent((Response.ContentListener)listener, response, buffer);
133             }
134         }
135     }
136 
137     private void notifyContent(Response.ContentListener listener, Response response, ByteBuffer buffer)
138     {
139         try
140         {
141             listener.onContent(response, buffer);
142         }
143         catch (Exception x)
144         {
145             LOG.info("Exception while notifying listener " + listener, x);
146         }
147     }
148 
149     @SuppressWarnings("ForLoopReplaceableByForEach")
150     public void notifySuccess(List<Response.ResponseListener> listeners, Response response)
151     {
152         // Optimized to avoid allocations of iterator instances
153         for (int i = 0; i < listeners.size(); ++i)
154         {
155             Response.ResponseListener listener = listeners.get(i);
156             if (listener instanceof Response.SuccessListener)
157                 notifySuccess((Response.SuccessListener)listener, response);
158         }
159     }
160 
161     private void notifySuccess(Response.SuccessListener listener, Response response)
162     {
163         try
164         {
165             listener.onSuccess(response);
166         }
167         catch (Exception x)
168         {
169             LOG.info("Exception while notifying listener " + listener, x);
170         }
171     }
172 
173     @SuppressWarnings("ForLoopReplaceableByForEach")
174     public void notifyFailure(List<Response.ResponseListener> listeners, Response response, Throwable failure)
175     {
176         // Optimized to avoid allocations of iterator instances
177         for (int i = 0; i < listeners.size(); ++i)
178         {
179             Response.ResponseListener listener = listeners.get(i);
180             if (listener instanceof Response.FailureListener)
181                 notifyFailure((Response.FailureListener)listener, response, failure);
182         }
183     }
184 
185     private void notifyFailure(Response.FailureListener listener, Response response, Throwable failure)
186     {
187         try
188         {
189             listener.onFailure(response, failure);
190         }
191         catch (Exception x)
192         {
193             LOG.info("Exception while notifying listener " + listener, x);
194         }
195     }
196 
197     @SuppressWarnings("ForLoopReplaceableByForEach")
198     public void notifyComplete(List<Response.ResponseListener> listeners, Result result)
199     {
200         // Optimized to avoid allocations of iterator instances
201         for (int i = 0; i < listeners.size(); ++i)
202         {
203             Response.ResponseListener listener = listeners.get(i);
204             if (listener instanceof Response.CompleteListener)
205                 notifyComplete((Response.CompleteListener)listener, result);
206         }
207     }
208 
209     private void notifyComplete(Response.CompleteListener listener, Result result)
210     {
211         try
212         {
213             listener.onComplete(result);
214         }
215         catch (Exception x)
216         {
217             LOG.info("Exception while notifying listener " + listener, x);
218         }
219     }
220 
221     public void forwardSuccess(List<Response.ResponseListener> listeners, Response response)
222     {
223         notifyBegin(listeners, response);
224         for (Iterator<HttpField> iterator = response.getHeaders().iterator(); iterator.hasNext();)
225         {
226             HttpField field = iterator.next();
227             if (!notifyHeader(listeners, response, field))
228                 iterator.remove();
229         }
230         notifyHeaders(listeners, response);
231         if (response instanceof ContentResponse)
232             notifyContent(listeners, response, ByteBuffer.wrap(((ContentResponse)response).getContent()));
233         notifySuccess(listeners, response);
234     }
235 
236     public void forwardSuccessComplete(List<Response.ResponseListener> listeners, Request request, Response response)
237     {
238         HttpConversation conversation = client.getConversation(request.getConversationID(), false);
239         forwardSuccess(listeners, response);
240         conversation.complete();
241         notifyComplete(listeners, new Result(request, response));
242     }
243 
244     public void forwardFailure(List<Response.ResponseListener> listeners, Response response, Throwable failure)
245     {
246         notifyBegin(listeners, response);
247         for (Iterator<HttpField> iterator = response.getHeaders().iterator(); iterator.hasNext();)
248         {
249             HttpField field = iterator.next();
250             if (!notifyHeader(listeners, response, field))
251                 iterator.remove();
252         }
253         notifyHeaders(listeners, response);
254         if (response instanceof ContentResponse)
255             notifyContent(listeners, response, ByteBuffer.wrap(((ContentResponse)response).getContent()));
256         notifyFailure(listeners, response, failure);
257     }
258 
259     public void forwardFailureComplete(List<Response.ResponseListener> listeners, Request request, Throwable requestFailure, Response response, Throwable responseFailure)
260     {
261         HttpConversation conversation = client.getConversation(request.getConversationID(), false);
262         forwardFailure(listeners, response, responseFailure);
263         conversation.complete();
264         notifyComplete(listeners, new Result(request, requestFailure, response, responseFailure));
265     }
266 }