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