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.websocket.common.extensions;
20  
21  import java.io.IOException;
22  
23  import org.eclipse.jetty.io.ByteBufferPool;
24  import org.eclipse.jetty.util.annotation.ManagedAttribute;
25  import org.eclipse.jetty.util.annotation.ManagedObject;
26  import org.eclipse.jetty.util.component.ContainerLifeCycle;
27  import org.eclipse.jetty.util.log.Log;
28  import org.eclipse.jetty.util.log.Logger;
29  import org.eclipse.jetty.websocket.api.WebSocketException;
30  import org.eclipse.jetty.websocket.api.WebSocketPolicy;
31  import org.eclipse.jetty.websocket.api.WriteCallback;
32  import org.eclipse.jetty.websocket.api.extensions.Extension;
33  import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
34  import org.eclipse.jetty.websocket.api.extensions.Frame;
35  import org.eclipse.jetty.websocket.api.extensions.IncomingFrames;
36  import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
37  import org.eclipse.jetty.websocket.common.LogicalConnection;
38  
39  @ManagedObject("Abstract Extension")
40  public abstract class AbstractExtension extends ContainerLifeCycle implements Extension
41  {
42      private final Logger log;
43      private WebSocketPolicy policy;
44      private ByteBufferPool bufferPool;
45      private ExtensionConfig config;
46      private LogicalConnection connection;
47      private OutgoingFrames nextOutgoing;
48      private IncomingFrames nextIncoming;
49  
50      public AbstractExtension()
51      {
52          log = Log.getLogger(this.getClass());
53      }
54  
55      @Override
56      public void dump(Appendable out, String indent) throws IOException
57      {
58          super.dump(out, indent);
59          // incoming
60          dumpWithHeading(out, indent, "incoming", this.nextIncoming);
61          dumpWithHeading(out, indent, "outgoing", this.nextOutgoing);
62      }
63  
64      protected void dumpWithHeading(Appendable out, String indent, String heading, Object bean) throws IOException
65      {
66          out.append(indent).append(" +- ");
67          out.append(heading).append(" : ");
68          out.append(bean.toString());
69      }
70  
71      public ByteBufferPool getBufferPool()
72      {
73          return bufferPool;
74      }
75  
76      @Override
77      public ExtensionConfig getConfig()
78      {
79          return config;
80      }
81  
82      public LogicalConnection getConnection()
83      {
84          return connection;
85      }
86  
87      @Override
88      public String getName()
89      {
90          return config.getName();
91      }
92  
93      @ManagedAttribute(name = "Next Incoming Frame Handler", readonly = true)
94      public IncomingFrames getNextIncoming()
95      {
96          return nextIncoming;
97      }
98  
99      @ManagedAttribute(name = "Next Outgoing Frame Handler", readonly = true)
100     public OutgoingFrames getNextOutgoing()
101     {
102         return nextOutgoing;
103     }
104 
105     public WebSocketPolicy getPolicy()
106     {
107         return policy;
108     }
109 
110     @Override
111     public void incomingError(WebSocketException e)
112     {
113         nextIncomingError(e);
114     }
115 
116     /**
117      * Used to indicate that the extension makes use of the RSV1 bit of the base websocket framing.
118      * <p>
119      * This is used to adjust validation during parsing, as well as a checkpoint against 2 or more extensions all simultaneously claiming ownership of RSV1.
120      * 
121      * @return true if extension uses RSV1 for its own purposes.
122      */
123     @Override
124     public boolean isRsv1User()
125     {
126         return false;
127     }
128 
129     /**
130      * Used to indicate that the extension makes use of the RSV2 bit of the base websocket framing.
131      * <p>
132      * This is used to adjust validation during parsing, as well as a checkpoint against 2 or more extensions all simultaneously claiming ownership of RSV2.
133      * 
134      * @return true if extension uses RSV2 for its own purposes.
135      */
136     @Override
137     public boolean isRsv2User()
138     {
139         return false;
140     }
141 
142     /**
143      * Used to indicate that the extension makes use of the RSV3 bit of the base websocket framing.
144      * <p>
145      * This is used to adjust validation during parsing, as well as a checkpoint against 2 or more extensions all simultaneously claiming ownership of RSV3.
146      * 
147      * @return true if extension uses RSV3 for its own purposes.
148      */
149     @Override
150     public boolean isRsv3User()
151     {
152         return false;
153     }
154 
155     /**
156      * Used to indicate that the extension works as a decoder of TEXT Data Frames.
157      * <p>
158      * This is used to adjust validation during parsing/generating, as per spec TEXT Data Frames can only contain UTF8 encoded String data.
159      * <p>
160      * Example: a compression extension will process a compressed set of text data, the parser/generator should no longer be concerned about the validity of the
161      * TEXT Data Frames as this is now the responsibility of the extension.
162      * 
163      * @return true if extension will process TEXT Data Frames, false if extension makes no modifications of TEXT Data Frames. If false, the parser/generator is
164      *         now free to validate the conformance to spec of TEXT Data Frames.
165      */
166     @Override
167     public boolean isTextDataDecoder()
168     {
169         return false;
170     }
171 
172     protected void nextIncomingError(WebSocketException e)
173     {
174         this.nextIncoming.incomingError(e);
175     }
176 
177     protected void nextIncomingFrame(Frame frame)
178     {
179         log.debug("nextIncomingFrame({})",frame);
180         this.nextIncoming.incomingFrame(frame);
181     }
182 
183     protected void nextOutgoingFrame(Frame frame, WriteCallback callback)
184     {
185         log.debug("nextOutgoingFrame({})",frame);
186         this.nextOutgoing.outgoingFrame(frame,callback);
187     }
188 
189     public void setBufferPool(ByteBufferPool bufferPool)
190     {
191         this.bufferPool = bufferPool;
192     }
193 
194     public void setConfig(ExtensionConfig config)
195     {
196         this.config = config;
197     }
198 
199     public void setConnection(LogicalConnection connection)
200     {
201         this.connection = connection;
202     }
203 
204     @Override
205     public void setNextIncomingFrames(IncomingFrames nextIncoming)
206     {
207         this.nextIncoming = nextIncoming;
208     }
209 
210     @Override
211     public void setNextOutgoingFrames(OutgoingFrames nextOutgoing)
212     {
213         this.nextOutgoing = nextOutgoing;
214     }
215 
216     public void setPolicy(WebSocketPolicy policy)
217     {
218         this.policy = policy;
219     }
220 
221     @Override
222     public String toString()
223     {
224         return String.format("%s[%s]",this.getClass().getSimpleName(),config.getParameterizedName());
225     }
226 }