📄 .#mediaserver.java.1.4
字号:
package no.auc.one.portableplayer.communication.mediaserver;
import java.io.*;
import java.util.*;
import javax.microedition.io.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.log4j.*;
import no.auc.one.portableplayer.communication.*;
import no.auc.one.portableplayer.utils.*;
/**
* Describes a Universal Plug & Play Media Server device.
*/
public class MediaServer extends UPnPDevice implements Cloneable, CancelAction {
private static Logger LOG = Logger.getLogger("MS");
private static MediaServer[] mediaServers = null;
private ContentDirectoryService cds;
private UPnPDiscovery discoServers = new UPnPDiscovery();
private boolean isUpdatingList = false;
public MediaServer() {
super();
cds = null;
}
public MediaServer(
String name,
String url,
UPnPService service)
{
super(name, url);
cds = (ContentDirectoryService)service;
}
private MediaServer(UPnPDevice device, ContentDirectoryService cds) {
super(device.getFriendlyName(), device.getURLBase());
this.cds = cds;
}
public Object clone() {
MediaServer ms = new MediaServer(
(UPnPDevice)this,
(ContentDirectoryService)cds.clone());
return ms;
}
public void cancel() throws IOException {
discoServers.cancel();
}
// TODO Should probably add some auto-update stuff, since it now will only
// find servers once. Perhaps use a Timer for this... for example
// update once each hour. The schedule-element should be static, so
// we won't get e.g. 5 instances trying to update at the same time.
public Enumeration getMediaServers() throws NoSuchElementException,
IOException
{
if (mediaServers == null) {
throw new IllegalStateException(
"Media Servers have not been discovered yet. Do updateMediaServerList first");
}
// XXX: Doc issue...:
// Since Cloneable interface is not supported on CLDC will do a
// copy of the mediaServers list here. Needs to do a copy since the
// MediaServer list is static. (Add rationale for why it is static
// at documentation for mediaServers... to reduce memory footprint,
// since this implies that it will only be copied when needed, and
// probably thrown away (by the GC) after an enumeration has been
// used. This compared to a non-static variable which would occupy
// memory for the entire life of the class)
MediaServer[] serverListClone = null;
if (mediaServers != null) {
serverListClone = new MediaServer[mediaServers.length];
for(int i = 0; i < mediaServers.length; i++) {
serverListClone[i] = (MediaServer)mediaServers[i].clone();
}
}
return new MediaServerEnumeration(serverListClone);
}
public MediaServer getMediaServer(int index) throws NoSuchElementException, IOException {
MediaServer ms = null;
if (mediaServers == null) {
throw new IllegalStateException(
"Media Servers have not been discovered yet. Do updateMediaServerList first.");
}
if (mediaServers != null) {
ms = (MediaServer)mediaServers[index].clone();
}
return ms;
}
/**
* This method send the UDP Datagram request to discover AVServer
* UDP request is as below:<br>
* M-SEARCH * HTTP/1.1
* HOST: 239.255.255.250:1900
* MAN: "ssdp:discover"
* MX: 10
* ST: urn:schemas-upnp-org:device:MediaServer:1
* Finally, filter the serverLocationUrls[]
* @return Returns serverLocationUrls
* @throws IOException
*/
public void updateMediaServerList() throws IOException
{
if (isUpdatingList) {
return;
} else {
isUpdatingList = true;
}
try {
String[] serverLocationUrls = discoServers.start(
"urn:schemas-upnp-org:device:MediaServer:1",
5); // max duration set to 5 seconds
if (serverLocationUrls == null || serverLocationUrls.length <= 0) {
LOG.debug("No media servers discovered.");
mediaServers = null;
return;
}
mediaServers = new MediaServer[serverLocationUrls.length];
for(int index = 0; index < serverLocationUrls.length; index++)
{
LOG.debug(
"MS" + index + ": " + serverLocationUrls[index]);
HttpConnection conn = null;
try{
conn = (HttpConnection)Connector.open(
serverLocationUrls[index]);
conn.setRequestMethod(HttpConnection.GET);
conn.setRequestProperty("Content-Length","0");
mediaServers[index] = new MediaServer();
SAXParserFactory pfactory = SAXParserFactory.newInstance();
SAXParser parser = pfactory.newSAXParser();
MediaServerDeviceDescriptionHandler msddHandler = new
MediaServerDeviceDescriptionHandler(
mediaServers[index],
serverLocationUrls[index]);
parser.parse(conn.openInputStream(), msddHandler);
conn.close();
// Output the elements of this device :)
LOG.debug(
"MediaServer found (" + index + ")" +
" Name:" + mediaServers[index].friendlyName +
" URLBase:" + mediaServers[index].urlBase +
" CDS:" + mediaServers[index].cds.toString());
} catch (ParserConfigurationException pce) {
LOG.debug("PCE exception in updateMediaServerList" + pce.toString());
pce.printStackTrace();
} catch (SAXException se) {
LOG.debug("SAXExceptio in updateMediaServerList" + se.toString());
se.printStackTrace();
} catch (ConnectionNotFoundException cnfe) {
LOG.debug("Connection not found. " + cnfe.toString());
cnfe.printStackTrace();
} catch (IOException ioe) {
LOG.debug("Error while getting device description. " + ioe.toString());
ioe.printStackTrace();
}
}
} finally {
isUpdatingList = false;
}
}
public ContentDirectoryService getContentDirectoryService() {
return cds;
}
private class MediaServerDeviceDescriptionHandler extends DefaultHandler{
private MediaServer ms;
private Vector services = new Vector();
private Stack tagStack = new Stack();
private String locationURL;
public MediaServerDeviceDescriptionHandler(MediaServer ms, String url) {
this.ms = ms;
locationURL = url;
}
public void startElement(
String uri,
String localName,
String qName,
Attributes attributes) throws SAXException
{
if(qName.equals("service")) {
// Should know if the device description contains an URLBase
// element or not at this point
if(ms.urlBase == null || ms.urlBase == "") {
// Use locationURL as URLBase
ms.urlBase = getHostAndPort(locationURL);
}
services.addElement(new UPnPService());
}
tagStack.push(qName);
}
public void characters(char[] ch, int start, int length) throws SAXException {
String chars = new String(ch, start, length).trim();
if(chars.length() > 0) {
String qName = (String)tagStack.peek();
if (qName.equals("friendlyName")) {
ms.friendlyName = chars;
} else if (qName.equals("URLBase")) {
ms.urlBase = chars;
} else if (qName.equals("serviceType")) {
UPnPService currentService = (UPnPService)services.lastElement();
currentService.setServiceType(chars);
} else if (qName.equals("serviceId")) {
UPnPService currentService = (UPnPService)services.lastElement();
currentService.setServiceId(chars);
} else if (qName.equals("controlURL")) {
UPnPService currentService = (UPnPService)services.lastElement();
currentService.setControlURL(ms.urlBase + chars);
} else if (qName.equals("SCPDURL")) {
UPnPService currentService = (UPnPService)services.lastElement();
currentService.setSCPDURL(ms.urlBase + chars);
} else if (qName.equals("eventSubURL")) {
UPnPService currentService = (UPnPService)services.lastElement();
currentService.setEventSubURL(ms.urlBase + chars);
}
}
}
public void endElement(String uri, String localName, String qName) throws SAXException {
tagStack.pop();
}
public void endDocument() throws SAXException {
if (services == null) {
return;
}
for (int i=0; i < services.size(); i++){
UPnPService currentService = (UPnPService)services.elementAt(i);
if (currentService == null) {
continue;
}
if (currentService.getServiceType().equals("urn:schemas-upnp-org:service:ContentDirectory:1")){
ms.cds = new ContentDirectoryService(currentService);
break; // FYI: If more services are needed to be
// initialized in the future then this break
// statement must be removed!
}
}
}
/**
* Analyze the serverLocationUrls to get only the address and port
* @param url URL to find host and port of.
* @return Returns host and port of an URL
*/
private String getHostAndPort(String url) {
int ss = 0;
for (int i = 8; i < url.length(); i++) {
ss=url.substring(8).indexOf('/');
}
return url.substring(0, ss + 9);
}
}
private class MediaServerEnumeration implements Enumeration {
private MediaServer[] serverList;
private int currentIndex;
public MediaServerEnumeration (
MediaServer[] servers)
{
serverList = servers;
currentIndex = 0;
}
public boolean hasMoreElements() {
if (serverList == null || currentIndex > (serverList.length - 1)) {
return false;
} else {
return true;
}
}
public Object nextElement() {
if (hasMoreElements()) {
return serverList[currentIndex++];
} else {
throw new NoSuchElementException("No more Media Serverers available");
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -