View Javadoc
1   /*
2    * Copyright (C) 2013 4th Line GmbH, Switzerland
3    *
4    * The contents of this file are subject to the terms of either the GNU
5    * Lesser General Public License Version 2 or later ("LGPL") or the
6    * Common Development and Distribution License Version 1 or later
7    * ("CDDL") (collectively, the "License"). You may not use this file
8    * except in compliance with the License. See LICENSE.txt for more
9    * information.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14   */
15  
16  package org.fourthline.cling;
17  
18  import org.fourthline.cling.controlpoint.ControlPoint;
19  import org.fourthline.cling.controlpoint.ControlPointImpl;
20  import org.fourthline.cling.protocol.ProtocolFactory;
21  import org.fourthline.cling.protocol.ProtocolFactoryImpl;
22  import org.fourthline.cling.registry.Registry;
23  import org.fourthline.cling.registry.RegistryImpl;
24  import org.fourthline.cling.registry.RegistryListener;
25  import org.fourthline.cling.transport.Router;
26  import org.fourthline.cling.transport.RouterException;
27  import org.fourthline.cling.transport.RouterImpl;
28  import org.seamless.util.Exceptions;
29  
30  import javax.enterprise.inject.Alternative;
31  import java.util.logging.Level;
32  import java.util.logging.Logger;
33  
34  /**
35   * Default implementation of {@link UpnpService}, starts immediately on construction.
36   * <p>
37   * If no {@link UpnpServiceConfiguration} is provided it will automatically
38   * instantiate {@link DefaultUpnpServiceConfiguration}. This configuration <strong>does not
39   * work</strong> on Android! Use the {@link org.fourthline.cling.android.AndroidUpnpService}
40   * application component instead.
41   * </p>
42   * <p>
43   * Override the various <tt>create...()</tt> methods to customize instantiation of protocol factory,
44   * router, etc.
45   * </p>
46   *
47   * @author Christian Bauer
48   */
49  @Alternative
50  public class UpnpServiceImpl implements UpnpService {
51  
52      private static Logger log = Logger.getLogger(UpnpServiceImpl.class.getName());
53  
54      protected final UpnpServiceConfiguration configuration;
55      protected final ControlPoint controlPoint;
56      protected final ProtocolFactory protocolFactory;
57      protected final Registry registry;
58      protected final Router router;
59  
60      public UpnpServiceImpl() {
61          this(new DefaultUpnpServiceConfiguration());
62      }
63  
64      public UpnpServiceImpl(RegistryListener... registryListeners) {
65          this(new DefaultUpnpServiceConfiguration(), registryListeners);
66      }
67  
68      public UpnpServiceImpl(UpnpServiceConfiguration configuration, RegistryListener... registryListeners) {
69          this.configuration = configuration;
70  
71          log.info(">>> Starting UPnP service...");
72  
73          log.info("Using configuration: " + getConfiguration().getClass().getName());
74  
75          // Instantiation order is important: Router needs to start its network services after registry is ready
76  
77          this.protocolFactory = createProtocolFactory();
78  
79          this.registry = createRegistry(protocolFactory);
80          for (RegistryListener registryListener : registryListeners) {
81              this.registry.addListener(registryListener);
82          }
83  
84          this.router = createRouter(protocolFactory, registry);
85  
86          try {
87              this.router.enable();
88          } catch (RouterException ex) {
89              throw new RuntimeException("Enabling network router failed: " + ex, ex);
90          }
91  
92          this.controlPoint = createControlPoint(protocolFactory, registry);
93  
94          log.info("<<< UPnP service started successfully");
95      }
96  
97      protected ProtocolFactory createProtocolFactory() {
98          return new ProtocolFactoryImpl(this);
99      }
100 
101     protected Registry createRegistry(ProtocolFactory protocolFactory) {
102         return new RegistryImpl(this);
103     }
104 
105     protected Router createRouter(ProtocolFactory protocolFactory, Registry registry) {
106         return new RouterImpl(getConfiguration(), protocolFactory);
107     }
108 
109     protected ControlPoint createControlPoint(ProtocolFactory protocolFactory, Registry registry) {
110         return new ControlPointImpl(getConfiguration(), protocolFactory, registry);
111     }
112 
113     public UpnpServiceConfiguration getConfiguration() {
114         return configuration;
115     }
116 
117     public ControlPoint getControlPoint() {
118         return controlPoint;
119     }
120 
121     public ProtocolFactory getProtocolFactory() {
122         return protocolFactory;
123     }
124 
125     public Registry getRegistry() {
126         return registry;
127     }
128 
129     public Router getRouter() {
130         return router;
131     }
132 
133     synchronized public void shutdown() {
134         shutdown(false);
135     }
136 
137     protected void shutdown(boolean separateThread) {
138         Runnable shutdown = new Runnable() {
139             @Override
140             public void run() {
141                 log.info(">>> Shutting down UPnP service...");
142                 shutdownRegistry();
143                 shutdownRouter();
144                 shutdownConfiguration();
145                 log.info("<<< UPnP service shutdown completed");
146             }
147         };
148         if (separateThread) {
149             // This is not a daemon thread, it has to complete!
150             new Thread(shutdown).start();
151         } else {
152             shutdown.run();
153         }
154     }
155 
156     protected void shutdownRegistry() {
157         getRegistry().shutdown();
158     }
159 
160     protected void shutdownRouter() {
161         try {
162             getRouter().shutdown();
163         } catch (RouterException ex) {
164             Throwable cause = Exceptions.unwrap(ex);
165             if (cause instanceof InterruptedException) {
166                 log.log(Level.INFO, "Router shutdown was interrupted: " + ex, cause);
167             } else {
168                 log.log(Level.SEVERE, "Router error on shutdown: " + ex, cause);
169             }
170         }
171     }
172 
173     protected void shutdownConfiguration() {
174         getConfiguration().shutdown();
175     }
176 
177 }