View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 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.jsr356;
20  
21  import java.util.Map;
22  import java.util.Objects;
23  import java.util.concurrent.ConcurrentHashMap;
24  
25  import javax.websocket.Decoder;
26  import javax.websocket.EndpointConfig;
27  
28  import org.eclipse.jetty.util.log.Log;
29  import org.eclipse.jetty.util.log.Logger;
30  import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
31  import org.eclipse.jetty.websocket.common.scopes.WebSocketSessionScope;
32  import org.eclipse.jetty.websocket.jsr356.metadata.DecoderMetadata;
33  import org.eclipse.jetty.websocket.jsr356.metadata.DecoderMetadataSet;
34  
35  /**
36   * Factory for {@link DecoderMetadata}
37   * <p>
38   * Relies on search order of parent {@link DecoderFactory} instances as such.
39   * <ul>
40   * <li>From Static DecoderMetadataSet (based on data in annotations and static EndpointConfig)</li>
41   * <li>From Composite DecoderMetadataSet (based static and instance specific EndpointConfig)</li>
42   * <li>Container declared DecoderMetadataSet (primitives)</li>
43   * </ul>
44   */
45  public class DecoderFactory implements Configurable
46  {
47      public static class Wrapper implements Configurable
48      {
49          private final Decoder decoder;
50          private final DecoderMetadata metadata;
51  
52          private Wrapper(Decoder decoder, DecoderMetadata metadata)
53          {
54              this.decoder = decoder;
55              this.metadata = metadata;
56          }
57  
58          public Decoder getDecoder()
59          {
60              return decoder;
61          }
62  
63          public DecoderMetadata getMetadata()
64          {
65              return metadata;
66          }
67  
68          @Override
69          public void init(EndpointConfig config)
70          {
71              this.decoder.init(config);
72          }
73      }
74  
75      private static final Logger LOG = Log.getLogger(DecoderFactory.class);
76  
77      private final DecoderMetadataSet metadatas;
78      private final WebSocketContainerScope containerScope;
79      private DecoderFactory parentFactory;
80      private Map<Class<?>, Wrapper> activeWrappers;
81  
82      public DecoderFactory(WebSocketContainerScope containerScope, DecoderMetadataSet metadatas)
83      {
84          this(containerScope,metadatas,null);
85      }
86      
87      public DecoderFactory(WebSocketSessionScope sessionScope, DecoderMetadataSet metadatas, DecoderFactory parentFactory)
88      {
89          this(sessionScope.getContainerScope(),metadatas,parentFactory);
90      }
91  
92      protected DecoderFactory(WebSocketContainerScope containerScope, DecoderMetadataSet metadatas, DecoderFactory parentFactory)
93      {
94          Objects.requireNonNull(containerScope,"Container Scope cannot be null");
95          this.containerScope = containerScope;
96          this.metadatas = metadatas;
97          this.activeWrappers = new ConcurrentHashMap<>();
98          this.parentFactory = parentFactory;
99      }
100 
101     public Decoder getDecoderFor(Class<?> type)
102     {
103         Wrapper wrapper = getWrapperFor(type);
104         if (wrapper == null)
105         {
106             return null;
107         }
108         return wrapper.decoder;
109     }
110 
111     public DecoderMetadata getMetadataFor(Class<?> type)
112     {
113         if (LOG.isDebugEnabled())
114         {
115             LOG.debug("getMetadataFor({})",type);
116         }
117         
118         DecoderMetadata metadata = metadatas.getMetadataByType(type);
119 
120         if (metadata != null)
121         {
122             return metadata;
123         }
124 
125         if (parentFactory != null)
126         {
127             return parentFactory.getMetadataFor(type);
128         }
129 
130         return null;
131     }
132 
133     public Wrapper getWrapperFor(Class<?> type)
134     {
135         synchronized (activeWrappers)
136         {
137             Wrapper wrapper = activeWrappers.get(type);
138 
139             // Try parent (if needed)
140             if ((wrapper == null) && (parentFactory != null))
141             {
142                 wrapper = parentFactory.getWrapperFor(type);
143             }
144 
145             if (wrapper == null)
146             {
147                 // Attempt to create Wrapper on demand
148                 DecoderMetadata metadata = metadatas.getMetadataByType(type);
149                 if (metadata == null)
150                 {
151                     return null;
152                 }
153                 wrapper = newWrapper(metadata);
154                 // track wrapper
155                 activeWrappers.put(type,wrapper);
156             }
157 
158             return wrapper;
159         }
160     }
161 
162     @Override
163     public void init(EndpointConfig config)
164     {
165         if (LOG.isDebugEnabled())
166         {
167             LOG.debug("init({})",config);
168         }
169         // Instantiate all declared decoders
170         for (DecoderMetadata metadata : metadatas)
171         {
172             Wrapper wrapper = newWrapper(metadata);
173             activeWrappers.put(metadata.getObjectType(),wrapper);
174         }
175 
176         // Initialize all decoders
177         for (Wrapper wrapper : activeWrappers.values())
178         {
179             wrapper.decoder.init(config);
180         }
181     }
182 
183     public Wrapper newWrapper(DecoderMetadata metadata)
184     {
185         Class<? extends Decoder> decoderClass = metadata.getCoderClass();
186         try
187         {
188             Decoder decoder = containerScope.getObjectFactory().createInstance(decoderClass);
189             return new Wrapper(decoder,metadata);
190         }
191         catch (InstantiationException | IllegalAccessException e)
192         {
193             throw new IllegalStateException("Unable to instantiate Decoder: " + decoderClass.getName());
194         }
195     }
196 }