1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.fourthline.cling;
17
18 import org.fourthline.cling.binding.xml.DeviceDescriptorBinder;
19 import org.fourthline.cling.binding.xml.ServiceDescriptorBinder;
20 import org.fourthline.cling.binding.xml.UDA10DeviceDescriptorBinderImpl;
21 import org.fourthline.cling.binding.xml.UDA10ServiceDescriptorBinderImpl;
22 import org.fourthline.cling.model.ModelUtil;
23 import org.fourthline.cling.model.Namespace;
24 import org.fourthline.cling.model.message.UpnpHeaders;
25 import org.fourthline.cling.model.meta.RemoteDeviceIdentity;
26 import org.fourthline.cling.model.meta.RemoteService;
27 import org.fourthline.cling.model.types.ServiceType;
28 import org.fourthline.cling.transport.impl.DatagramIOConfigurationImpl;
29 import org.fourthline.cling.transport.impl.DatagramIOImpl;
30 import org.fourthline.cling.transport.impl.DatagramProcessorImpl;
31 import org.fourthline.cling.transport.impl.GENAEventProcessorImpl;
32 import org.fourthline.cling.transport.impl.MulticastReceiverConfigurationImpl;
33 import org.fourthline.cling.transport.impl.MulticastReceiverImpl;
34 import org.fourthline.cling.transport.impl.NetworkAddressFactoryImpl;
35 import org.fourthline.cling.transport.impl.SOAPActionProcessorImpl;
36 import org.fourthline.cling.transport.impl.StreamClientConfigurationImpl;
37 import org.fourthline.cling.transport.impl.StreamClientImpl;
38 import org.fourthline.cling.transport.impl.StreamServerConfigurationImpl;
39 import org.fourthline.cling.transport.impl.StreamServerImpl;
40 import org.fourthline.cling.transport.spi.DatagramIO;
41 import org.fourthline.cling.transport.spi.DatagramProcessor;
42 import org.fourthline.cling.transport.spi.GENAEventProcessor;
43 import org.fourthline.cling.transport.spi.MulticastReceiver;
44 import org.fourthline.cling.transport.spi.NetworkAddressFactory;
45 import org.fourthline.cling.transport.spi.SOAPActionProcessor;
46 import org.fourthline.cling.transport.spi.StreamClient;
47 import org.fourthline.cling.transport.spi.StreamServer;
48 import org.seamless.util.Exceptions;
49
50 import javax.enterprise.inject.Alternative;
51 import java.util.concurrent.Executor;
52 import java.util.concurrent.ExecutorService;
53 import java.util.concurrent.RejectedExecutionHandler;
54 import java.util.concurrent.SynchronousQueue;
55 import java.util.concurrent.ThreadFactory;
56 import java.util.concurrent.ThreadPoolExecutor;
57 import java.util.concurrent.TimeUnit;
58 import java.util.concurrent.atomic.AtomicInteger;
59 import java.util.logging.Logger;
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86 @Alternative
87 public class DefaultUpnpServiceConfiguration implements UpnpServiceConfiguration {
88
89 private static Logger log = Logger.getLogger(DefaultUpnpServiceConfiguration.class.getName());
90
91 final private int streamListenPort;
92
93 final private ExecutorService defaultExecutorService;
94
95 final private DatagramProcessor datagramProcessor;
96 final private SOAPActionProcessor soapActionProcessor;
97 final private GENAEventProcessor genaEventProcessor;
98
99 final private DeviceDescriptorBinder deviceDescriptorBinderUDA10;
100 final private ServiceDescriptorBinder serviceDescriptorBinderUDA10;
101
102 final private Namespace namespace;
103
104
105
106
107 public DefaultUpnpServiceConfiguration() {
108 this(NetworkAddressFactoryImpl.DEFAULT_TCP_HTTP_LISTEN_PORT);
109 }
110
111 public DefaultUpnpServiceConfiguration(int streamListenPort) {
112 this(streamListenPort, true);
113 }
114
115 protected DefaultUpnpServiceConfiguration(boolean checkRuntime) {
116 this(NetworkAddressFactoryImpl.DEFAULT_TCP_HTTP_LISTEN_PORT, checkRuntime);
117 }
118
119 protected DefaultUpnpServiceConfiguration(int streamListenPort, boolean checkRuntime) {
120 if (checkRuntime && ModelUtil.ANDROID_RUNTIME) {
121 throw new Error("Unsupported runtime environment, use org.fourthline.cling.android.AndroidUpnpServiceConfiguration");
122 }
123
124 this.streamListenPort = streamListenPort;
125
126 defaultExecutorService = createDefaultExecutorService();
127
128 datagramProcessor = createDatagramProcessor();
129 soapActionProcessor = createSOAPActionProcessor();
130 genaEventProcessor = createGENAEventProcessor();
131
132 deviceDescriptorBinderUDA10 = createDeviceDescriptorBinderUDA10();
133 serviceDescriptorBinderUDA10 = createServiceDescriptorBinderUDA10();
134
135 namespace = createNamespace();
136 }
137
138 public DatagramProcessor getDatagramProcessor() {
139 return datagramProcessor;
140 }
141
142 public SOAPActionProcessor getSoapActionProcessor() {
143 return soapActionProcessor;
144 }
145
146 public GENAEventProcessor getGenaEventProcessor() {
147 return genaEventProcessor;
148 }
149
150 public StreamClient createStreamClient() {
151 return new StreamClientImpl(
152 new StreamClientConfigurationImpl(
153 getSyncProtocolExecutorService()
154 )
155 );
156 }
157
158 public MulticastReceiver createMulticastReceiver(NetworkAddressFactory networkAddressFactory) {
159 return new MulticastReceiverImpl(
160 new MulticastReceiverConfigurationImpl(
161 networkAddressFactory.getMulticastGroup(),
162 networkAddressFactory.getMulticastPort()
163 )
164 );
165 }
166
167 public DatagramIO createDatagramIO(NetworkAddressFactory networkAddressFactory) {
168 return new DatagramIOImpl(new DatagramIOConfigurationImpl());
169 }
170
171 public StreamServer createStreamServer(NetworkAddressFactory networkAddressFactory) {
172 return new StreamServerImpl(
173 new StreamServerConfigurationImpl(
174 networkAddressFactory.getStreamListenPort()
175 )
176 );
177 }
178
179 public Executor getMulticastReceiverExecutor() {
180 return getDefaultExecutorService();
181 }
182
183 public Executor getDatagramIOExecutor() {
184 return getDefaultExecutorService();
185 }
186
187 public ExecutorService getStreamServerExecutorService() {
188 return getDefaultExecutorService();
189 }
190
191 public DeviceDescriptorBinder getDeviceDescriptorBinderUDA10() {
192 return deviceDescriptorBinderUDA10;
193 }
194
195 public ServiceDescriptorBinder getServiceDescriptorBinderUDA10() {
196 return serviceDescriptorBinderUDA10;
197 }
198
199 public ServiceType[] getExclusiveServiceTypes() {
200 return new ServiceType[0];
201 }
202
203
204
205
206 public boolean isReceivedSubscriptionTimeoutIgnored() {
207 return false;
208 }
209
210 public UpnpHeaders getDescriptorRetrievalHeaders(RemoteDeviceIdentity identity) {
211 return null;
212 }
213
214 public UpnpHeaders getEventSubscriptionHeaders(RemoteService service) {
215 return null;
216 }
217
218
219
220
221 public int getRegistryMaintenanceIntervalMillis() {
222 return 1000;
223 }
224
225
226
227
228 public int getAliveIntervalMillis() {
229 return 0;
230 }
231
232 public Integer getRemoteDeviceMaxAgeSeconds() {
233 return null;
234 }
235
236 public Executor getAsyncProtocolExecutor() {
237 return getDefaultExecutorService();
238 }
239
240 public ExecutorService getSyncProtocolExecutorService() {
241 return getDefaultExecutorService();
242 }
243
244 public Namespace getNamespace() {
245 return namespace;
246 }
247
248 public Executor getRegistryMaintainerExecutor() {
249 return getDefaultExecutorService();
250 }
251
252 public Executor getRegistryListenerExecutor() {
253 return getDefaultExecutorService();
254 }
255
256 public NetworkAddressFactory createNetworkAddressFactory() {
257 return createNetworkAddressFactory(streamListenPort);
258 }
259
260 public void shutdown() {
261 log.fine("Shutting down default executor service");
262 getDefaultExecutorService().shutdownNow();
263 }
264
265 protected NetworkAddressFactory createNetworkAddressFactory(int streamListenPort) {
266 return new NetworkAddressFactoryImpl(streamListenPort);
267 }
268
269 protected DatagramProcessor createDatagramProcessor() {
270 return new DatagramProcessorImpl();
271 }
272
273 protected SOAPActionProcessor createSOAPActionProcessor() {
274 return new SOAPActionProcessorImpl();
275 }
276
277 protected GENAEventProcessor createGENAEventProcessor() {
278 return new GENAEventProcessorImpl();
279 }
280
281 protected DeviceDescriptorBinder createDeviceDescriptorBinderUDA10() {
282 return new UDA10DeviceDescriptorBinderImpl();
283 }
284
285 protected ServiceDescriptorBinder createServiceDescriptorBinderUDA10() {
286 return new UDA10ServiceDescriptorBinderImpl();
287 }
288
289 protected Namespace createNamespace() {
290 return new Namespace();
291 }
292
293 protected ExecutorService getDefaultExecutorService() {
294 return defaultExecutorService;
295 }
296
297 protected ExecutorService createDefaultExecutorService() {
298 return new ClingExecutor();
299 }
300
301 public static class ClingExecutor extends ThreadPoolExecutor {
302
303 public ClingExecutor() {
304 this(new ClingThreadFactory(),
305 new ThreadPoolExecutor.DiscardPolicy() {
306
307 @Override
308 public void rejectedExecution(Runnable runnable, ThreadPoolExecutor threadPoolExecutor) {
309
310 log.info("Thread pool rejected execution of " + runnable.getClass());
311 super.rejectedExecution(runnable, threadPoolExecutor);
312 }
313 }
314 );
315 }
316
317 public ClingExecutor(ThreadFactory threadFactory, RejectedExecutionHandler rejectedHandler) {
318
319 super(0,
320 Integer.MAX_VALUE,
321 60L,
322 TimeUnit.SECONDS,
323 new SynchronousQueue<Runnable>(),
324 threadFactory,
325 rejectedHandler
326 );
327 }
328
329 @Override
330 protected void afterExecute(Runnable runnable, Throwable throwable) {
331 super.afterExecute(runnable, throwable);
332 if (throwable != null) {
333 Throwable cause = Exceptions.unwrap(throwable);
334 if (cause instanceof InterruptedException) {
335
336
337
338 return;
339 }
340
341 log.warning("Thread terminated " + runnable + " abruptly with exception: " + throwable);
342 log.warning("Root cause: " + cause);
343 }
344 }
345 }
346
347
348 public static class ClingThreadFactory implements ThreadFactory {
349
350 protected final ThreadGroup group;
351 protected final AtomicInteger threadNumber = new AtomicInteger(1);
352 protected final String namePrefix = "cling-";
353
354 public ClingThreadFactory() {
355 SecurityManager s = System.getSecurityManager();
356 group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
357 }
358
359 public Thread newThread(Runnable r) {
360 Thread t = new Thread(
361 group, r,
362 namePrefix + threadNumber.getAndIncrement(),
363 0
364 );
365 if (t.isDaemon())
366 t.setDaemon(false);
367 if (t.getPriority() != Thread.NORM_PRIORITY)
368 t.setPriority(Thread.NORM_PRIORITY);
369
370 return t;
371 }
372 }
373
374 }