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