View Javadoc

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