Source code: jreceiver/client/rio/RioLauncher.java
1 /* $Header: /cvsroot/jreceiver/jreceiver/src/jreceiver/client/rio/RioLauncher.java,v 1.11 2002/12/29 00:44:09 reedesau Exp $ */
2
3 package jreceiver.client.rio;
4
5 import java.io.IOException;
6 import java.io.Writer;
7 import java.net.InetAddress;
8 import java.net.URL;
9 import java.net.UnknownHostException;
10 import java.util.Vector;
11 import javax.servlet.*;
12 import javax.servlet.http.*;
13
14 import org.apache.commons.lang.Strings;
15
16 import jreceiver.client.common.ClientLauncher;
17 import jreceiver.client.rio.hack.*;
18 import jreceiver.client.rio.status.*;
19 import jreceiver.common.LauncherException;
20 import jreceiver.common.rec.driver.*;
21 import jreceiver.common.rpc.Drivers;
22 import jreceiver.common.rpc.RpcException;
23 import jreceiver.common.rpc.RpcFactory;
24
25 /**
26 * launches background daemons to interact with the Rio Receiver
27 * <p>
28 * RioSSDP - listens for queries from Rio for server address and port
29 * <p>
30 * RioStatus - queries all known Rio Receivers for status every couple of
31 * seconds on their 18678 ports
32 * <p>
33 * All settings are loaded from database using the following
34 * keys and defaults:
35 * <p>
36 * hardware/rio/ssdp_port = 21075
37 * hardware/rio/mserve_port = 8080
38 * hardware/rio/mserve_host = "" blank to get host from Java
39 * hardware/rio/status_port = 18678
40 *
41 * @author Reed Esau
42 * @version $Revision: 1.11 $ $Date: 2002/12/29 00:44:09 $
43 */
44 public class RioLauncher extends ClientLauncher {
45
46 public static final String CALLBACK_URL_PARAM = "rio-rpc";
47
48 protected static Driver driver = null;
49
50 public static int getDriverId() {
51 return driver!=null ? driver.getId() : 0;
52 }
53
54 public static Driver getDriver() {
55 return driver;
56 }
57
58 /**
59 * Called by the servlet container to indicate to a servlet that the
60 * servlet is being placed into service.
61 *
62 * @param user - the user whose credentials were used to register the client
63 */
64 public void serverDetectedInit() throws LauncherException {
65
66 log.debug("RioLauncher: serverDetectedInit");
67
68 int ssdp_port;
69 int mserve_port;
70 int status_port;
71 boolean ds_hack;
72
73 // this initializes the settings cache for the creds used to register this driver
74 RioSettingCache settings = RioSettingCache.getInstance(getDefaultUser());
75
76 // register with the server (so that we can receive events
77 // and provide services through the XML-RPC interface)
78 try {
79 // initialize security to authenticate callbacks from server
80 String callback_user_id = "riocallback";
81 String callback_password = Strings.randomAlphanumeric(10);
82 RioSecurityBean security_bean = RioSecurityBean.getInstance();
83 security_bean.setCredentials(callback_user_id, callback_password);
84
85 RpcFactory.setDefaultCredentials(getDefaultUser());
86
87 log.info("RioLauncher: registering driver with server");
88 URL callback_url = getPropertyURL(CALLBACK_URL_PARAM);
89 Drivers drv_rpc = RpcFactory.newDrivers();
90
91 // build a list of natively supported mime-types
92 Vector mime_types = new Vector();
93 mime_types.add( "audio/x-mp3" );
94 if (settings.getNativeWMA())
95 mime_types.add( "audio/x-ms-wma" );
96 if (settings.getNativeOGG())
97 mime_types.add( "audio/x-ogg" );
98 if (settings.getNativeFLAC())
99 mime_types.add( "audio/x-flac" );
100
101 Vector slave_types = new Vector();
102 slave_types.add( "IR" );
103 driver = drv_rpc.register(callback_url,
104 callback_user_id,
105 callback_password,
106 mime_types,
107 null, //no master medium types
108 slave_types,
109 false); // settings restricted to driver registrar
110
111 int cmd_type = settings.getDsHack()
112 ? Command.TYPE_DIRECT
113 : Command.TYPE_IR;
114
115 Vector cmds = new Vector();
116 cmds.add( new CommandRec(0, Command.STD_PWRTGL , cmd_type) );
117 cmds.add( new CommandRec(0, Command.STD_PREV , cmd_type) );
118 cmds.add( new CommandRec(0, Command.STD_PLAYPAUSE, cmd_type) );
119 cmds.add( new CommandRec(0, Command.STD_STOP , cmd_type) );
120 cmds.add( new CommandRec(0, Command.STD_NEXT , cmd_type) );
121
122 drv_rpc.registerCommandSet(getDriverId(), cmds);
123
124 ssdp_port = settings.getSsdpPort();
125 mserve_port = settings.getMservePort();
126 status_port = settings.getStatusPort();
127 ds_hack = settings.getDsHack();
128 }
129 catch (RpcException e) {
130 throw new LauncherException("RioLauncher: rpc-problem registering the driver", e);
131 }
132
133 // initialize and launch the daemons
134 String host_ip = getHostIP();
135
136 log.debug("RioLauncher: creating and initializing the daemons");
137 ssdp_daemon = RioSSDP.getInstance(ssdp_port, host_ip, mserve_port);
138
139 // create the singleton and add it as a listener to the SSDP daemon
140 status_daemon = RioStatusDaemon.getInstance( new Integer(status_port) );
141 if (status_daemon != null) {
142 ssdp_daemon.addListener( status_daemon );
143
144 log.info("RioLauncher: starting status_daemon");
145 status_daemon.start(); // start listening
146 }
147 else {
148 log.warn("RioLauncher: unable to start the status daemon");
149 }
150
151 log.info("RioLauncher: starting ssdp_daemon");
152 ssdp_daemon.start(); // start listening
153
154 if (ds_hack) {
155 hack_daemon = RioHackDaemon.getInstance();
156 if (hack_daemon != null) {
157 log.info("RioLauncher: starting hack_daemon");
158 hack_daemon.start(); // start listening
159 }
160 else {
161 log.warn("RioLauncher: unable to start the hack daemon");
162 }
163 }
164 }
165
166 /**
167 * support method for serverDetectedInit to obtain a valid host ip address
168 */
169 private String getHostIP() throws LauncherException {
170
171 String host_ip = null;
172 String hostname;
173
174 try {
175 RioSettingCache settings = RioSettingCache.getInstance();
176
177 hostname = settings.getMserveHost();
178 }
179 catch (RpcException e) {
180 throw new LauncherException("unable to obtain the mserve host", e);
181 }
182
183 if (hostname != null && hostname.length() > 0) {
184 log.info("RioLauncher: getting music server IP for hostname " + hostname);
185 }
186 else {
187 log.debug("RioLauncher: attempting to determine music server hostname");
188 try {
189 hostname = InetAddress.getLocalHost().getHostName();
190 }
191 catch (UnknownHostException e) {
192 throw new LauncherException("unable to determine local hostname", e);
193 }
194 }
195
196 hostname = hostname.trim();
197
198 if (Character.isDigit(hostname.charAt(0))) { //TODO: need more sophistication
199 host_ip = hostname;
200 }
201 else { // attempt to resolve name into an IP
202 try {
203 InetAddress addr = InetAddress.getByName(hostname);
204 if (addr != null) {
205 host_ip = addr.getHostAddress();
206 }
207 else
208 throw new LauncherException("unable to resolve hostname");
209 }
210 catch (UnknownHostException e) {
211 throw new LauncherException("unable to resolve hostname", e);
212 }
213 }
214
215 return host_ip;
216 }
217
218 /**
219 * Called by the servlet container to indicate to a servlet that the
220 * servlet is being taken out of service. See {@link Servlet#destroy}.
221 */
222 public void destroy() {
223 if (ssdp_daemon != null)
224 ssdp_daemon.stop(); // stop listening
225 if (status_daemon != null)
226 status_daemon.stop(); // stop listening
227 }
228
229 /**
230 * test method
231 */
232 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
233 throws ServletException,IOException {
234 Writer writer = resp.getWriter();
235 writer.write("I'm the Rio Launcher Servlet.");
236 }
237
238 //
239 // internal data members
240 //
241
242 /**
243 * The RioSSDP daemon listens for Rio Receivers in search
244 * of a server, responds to them offering the services
245 * of the server that typically hosts the daemon.
246 * <p>
247 * IMPORTANT: keep this reference to the singleton,
248 * otherwise it might be garbage collected.
249 */
250 protected RioSSDP ssdp_daemon = null;
251
252 /**
253 * the RioStatus daemon queries all known Rios for status
254 * and produces events for (local) listeners
255 * <p>
256 * IMPORTANT: keep this reference to the singleton,
257 * otherwise it might be garbage collected.
258 */
259 protected RioStatusDaemon status_daemon = null;
260
261 protected RioHackDaemon hack_daemon = null;
262 }
263
264
265 /*
266 JRECEIVER MODIFIED BSD LICENSE
267
268 Copyright (c) 2001-2002, Reed Esau (reed.esau@pobox.com) All rights reserved.
269
270 Redistribution and use in source and binary forms, with or without
271 modification, are permitted provided that the following conditions are
272 met:
273
274 Redistributions of source code must retain the above copyright notice,
275 this list of conditions and the following disclaimer.
276
277 Redistributions in binary form must reproduce the above copyright notice,
278 this list of conditions and the following disclaimer in the documentation
279 and/or other materials provided with the distribution.
280
281 Neither the name of the JReceiver Project
282 (http://jreceiver.sourceforge.net) nor the names of its contributors may
283 be used to endorse or promote products derived from this software without
284 specific prior written permission.
285
286 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
287 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
288 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
289 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
290 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
291 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
292 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
293 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
294 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
295 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
296 POSSIBILITY OF SUCH DAMAGE.
297 */
298