⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 contentdirectoryservice.java

📁 国外的j2me播放器软件
💻 JAVA
字号:
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 no.auc.one.portableplayer.communication.*;
import no.auc.one.portableplayer.communication.soap.*;
import no.auc.one.portableplayer.utils.*;
import no.auc.one.portableplayer.librarymanager.*;

import org.apache.log4j.*;

/**
 * Describes a UPnP Content Directory service of a Media Server device.
 */
public class ContentDirectoryService extends UPnPService implements Cloneable {

    private static Logger LOG;
    
    /**
     * To request all available content to be returned.
     */
    public static final int REQUEST_ALL = 0;
    
    private static final int BROWSEFLAG_DIRECT_CHILDREN = 0;
    private static final int BROWSEFLAG_METADATA = 1;
        
    // To support clone() method.
	private ContentDirectoryService(
        String type,
        String id,
        String scpd,
        String eventSub,
        String control)
    {
        super(type, id, scpd, eventSub, control);

        LOG = Logger.getLogger("CDS");    
	}
	
    /**
     * Construct a new class instance based on the UPnPService.
     *
     * @param service Service to base this class instance on.
     */
    public ContentDirectoryService(
        UPnPService service)
    {
        super(
            service.getServiceType(), 
            service.getServiceID(), 
            service.getScpdURL(), 
            service.getEventSubURL(), 
            service.getControlURL());
	}

    /**
     * Create a clone of this class instance.
     *
     * @return Clone of this class instance.
     */
    public Object clone() {
        return new ContentDirectoryService(
            getServiceType(),
            getServiceID(),
            getScpdURL(),
            getEventSubURL(),
            getControlURL());
    }

    /**
     * Browse and retrieve all available children of a container.
     * 
     * @param containerId ID for the requested container.
     */
    public ContentContainer browseDirectChildren(String containerId) 
        throws IOException
    {
        return browseDirectChildren(containerId, 0, REQUEST_ALL);
    }
    
	/**
	 * Initial browsing of a container of the media server's content directory 
     * service.
     *
	 * @param containerId ID for the container to retrieve content from.
     * @param startIndex Index for elements to be retrieved.
	 * @param requestedCount Requested count of elements to be retrieved. 
     *                       REQUEST_ALL(=0) means get all available elements.
     * 
	 * @return Returns a ContentContainer object which includes the children of 
     *         it in a MediaContent array. 
	 * 
     * @throws IOException
	 */
    public ContentContainer browseDirectChildren(
        String containerId, 
        int startIndex,
        int requestedCount) throws IOException
    {
        ContentContainer cc = null;
        
        try {
            ContentContainerHandler ccHandler = new ContentContainerHandler();
            invokeBrowse(
                containerId, 
                BROWSEFLAG_DIRECT_CHILDREN,
                startIndex,
                requestedCount,
                ccHandler);
            
            MediaContent[] mc = ccHandler.getMediaContent();
            
            System.out.println(
            	"browse result: total matches=" + ccHandler.getTotalMatches() + 
            	"\tnumber returned=" + ccHandler.getNumberReturned() + 
            	"\tmc length=" + mc.length);

            cc = new ContentContainer(
                    containerId, 
                    "0", 
                    "container",
                    mc);
        } catch (NoSuchElementException nse) {
            LOG.fatal(nse);
        }
	
        return cc;
    }

    /**
     * Continued browsing of a container. This method should be used to 
     * continue browsing a container already retrieved from the 'initial' 
     * browseDirectChildren method overload.
     */
    public void browseDirectChildren(
        ContentContainer container,
        int startIndex,
        int requestedCount) throws IOException
    {
        try {
            ContentContainerHandler ccHandler = new ContentContainerHandler();
            System.out.println(
                "Invoking browse for container ID=" + container.getObjectID() + 
               ", startindex=" + startIndex + ", reqcount=" + requestedCount);
            invokeBrowse(
                container.getObjectID(), 
                BROWSEFLAG_DIRECT_CHILDREN,
                startIndex,
                requestedCount,
                ccHandler);

            System.out.println(
                "Total matches: " + ccHandler.getTotalMatches() + 
                ", Elemements fetched: " + ccHandler.getNumberReturned());

            if(container.totalLength() == -1) { // container is currently empty
                System.out.println("Container is currently empty.");
                /*
                container = new ContentContainer(
                    container.getObjectID(),
                    container.getParentID(),
                    container.getName(),
                    ccHandler.getTotalMatches());
                */
                container.setTotalLength(ccHandler.getTotalMatches());
                container.insertMediaContentAt(
                    0,
                    ccHandler.getMediaContent());
/*   

            if (container.totalLength() != ccHandler.getTotalMatches()) {
                System.out.println(
                    "container.totalLength(" + container.totalLength() + 
                    " != totalMatches(" + ccHandler.getTotalMatches());

                retContainer = new ContentContainer(
                    container.getObjectID(),
                    container.getParentID(),
                    container.getName());
                retContainer.insertMediaContentAt(
                    ccHandler.getMediaContent());
*/                
            } else {
                System.out.println(
                    "container.totalLength(" + container.totalLength() + 
                    ") == ccHHandler.totalMatches(" + 
                    ccHandler.getTotalMatches() + ")");
                
                MediaContent[] mc = ccHandler.getMediaContent();

                // XXX Is this test redundant?
                if (mc.length > (container.totalLength() - startIndex)) {
                    System.out.println(
                        "Ouch, mc.length(" + mc.length + 
                        ") > container.length(" + container.totalLength() + 
                        ") - startIndex(" + startIndex + 
                        ") Nope test is not redundant!");
                }

                /*
                container = new ContentContainer(
                    container.getObjectID(),
                    container.getParentID(),
                    container.getName(),
                    ccHandler.getTotalMatches());
                container.insertMediaContentAt(
                    0,
                    container.getMediaContent());
                */
                container.insertMediaContentAt(
                    startIndex, 
                    mc);
            }
        } catch (NoSuchElementException nse) {
            LOG.fatal(nse);
        }  
    }

    /**
     * Retrieve metadata for an object.
     *
     * For example Windows Media Connect (WMC) does not include metadata in 
     * the response to a Browse request with the BrowseDirectChildren flag.
     *
     * @param objectId Requested object
     * 
     * @return MediaContent for the specific object. Notice that the callee 
     *         should use the instanceof operator to test what kind of 
     *         object was returned (one of the classes derived from 
     *         MediaContent). 
     * 
     * @throws IOException
     */
    public MediaContent browseMetadata(String objectId) throws IOException {
        MediaContent mc = null;
        
        try {
            // XXX MetadataResultHandler mrh = new MetadataResultHandler();
            
            // XXX invokeBrowse(objectID, BROWSEFLAG_METADATA, 0, 1, resultParser);

            // Do something with mrh?
        } catch (NoSuchElementException nse) {
            LOG.fatal(nse);
        }

        return mc;
    }
    
    /**
     * Invokes the browse action at the server side.
     *
     * Used by the public methods browseDirectChildren and browseMetadata.
     */
    private void invokeBrowse(
            String objectID, 
            int browseFlag,
            int startIndex,
            int requestedCount,
            DefaultHandler resultParser) throws IOException
    {
        SoapInvoke si = new SoapInvoke(
            "\"urn:schemas-upnp-org:service:ContentDirectory:1#Browse\"",
            getControlURL());

        StringBuffer buffer = new StringBuffer();
        // XXX: Not all devices like to get the <?xml..?> part. Should perhaps
        //      try first to send a request with the <?xml..?> and if an error 
        //      is returned then try to send a new request without.
        //      
        buffer.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n");
        buffer.append(
            "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"");
        buffer.append(
            "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n");
        buffer.append("<s:Body>\r\n");
        buffer.append
            ("<u:Browse xmlns:u=\"urn:schemas-upnp-org:service:");
        buffer.append("ContentDirectory:1\">\r\n");
        buffer.append("<ObjectID>" + objectID + "</ObjectID>\r\n");
        buffer.append("<BrowseFlag>");
        buffer.append(
            (browseFlag == BROWSEFLAG_DIRECT_CHILDREN) ? 
            "BrowseDirectChildren" : "BrowseMetadata");
        buffer.append("</BrowseFlag>\r\n");
        buffer.append("<Filter>*</Filter>\r\n");
        buffer.append(
            "<StartingIndex>" + startIndex + "</StartingIndex>\r\n");
        buffer.append(
            "<RequestedCount>" + requestedCount + "</RequestedCount>\r\n");
        buffer.append("<SortCriteria></SortCriteria>\r\n");
        buffer.append("</u:Browse>\r\n");
        buffer.append("</s:Body>\r\n");
        buffer.append("</s:Envelope>\r\n");

        si.setBody(buffer.toString());

        String resp = si.invoke(
            "\"urn:schemas-upnp-org:service:ContentDirectory:1#Browse\"");
        
        GenericSoapResultParser gparser = new GenericSoapResultParser(
            new ByteArrayInputStream(resp.getBytes()),
            resultParser);
    
        gparser.parseSoapResult();

        if (resultParser instanceof ContentContainerHandler) {
            BrowseResultParser brp = (BrowseResultParser)resultParser;
            brp.setNumberReturned(gparser.getNumberReturned());
            brp.setTotalMatches(gparser.getTotalMatches());
        } else {
            System.out.println(
                "Nope, result parser does not implement BrowseResultParser.");
        }
    }

    private class GenericSoapResultParser {
        private InputStream is;
        private DefaultHandler resultParserHandler;
        private SAXParser parser;
        private GenericSoapResultHandler gh;
    
        public GenericSoapResultParser(InputStream is, DefaultHandler dh) {
            try {
                SAXParserFactory pfactory = SAXParserFactory.newInstance();
                parser = pfactory.newSAXParser();
                
                this.is = is;
                resultParserHandler = dh;
            } catch (SAXException se) {
                LOG.debug("SAXException caught in GSRP::ctor");
                LOG.debug(se);
            } catch (ParserConfigurationException pce) {
                LOG.debug("PCE in GSRP::ctor");
                LOG.debug(pce);
            }
        }
    
        public void parseSoapResult() {
            try {
                gh = new GenericSoapResultHandler();
                parser.parse(is, gh);

                parser.parse(
                    new ByteArrayInputStream(
                        gh.resultElement.getBytes()), 
                    resultParserHandler);
            } catch (SAXException se) {
                LOG.debug("Error in generic soap result parser");
                LOG.debug(se);
            } catch (IOException ioe) {
                LOG.debug("IOException in GSRP");
                LOG.debug(ioe);
            }
        }

        public int getNumberReturned() {
            return gh.numberReturned;
        }
    
        public int getTotalMatches() {
            return gh.totalMatches;
        }
        
        private class GenericSoapResultHandler extends DefaultHandler {
            public String resultElement;
            public int totalMatches = 0;
            public int numberReturned = 0;
            private int currentElement;
            
            private final int ELEMENT_IS_UNKNOWN = -1;
            private final int ELEMENT_IS_RESULT = 0;
            private final int ELEMENT_IS_NUMBER_RETURNED = 1;
            private final int ELEMENT_IS_TOTAL_MATCHES = 2;
    
            public GenericSoapResultHandler() {
                currentElement = ELEMENT_IS_UNKNOWN;
            }
    
            public void characters(
                char[] ch, 
                int start, 
                int length) throws SAXException
            {
                String txt = new String(ch, start, length);
                
                switch(currentElement) {
                    case ELEMENT_IS_RESULT:
                        resultElement = txt;
                        break;
                    case ELEMENT_IS_NUMBER_RETURNED:
                        numberReturned = Integer.parseInt(txt);
                        break;
                    case ELEMENT_IS_TOTAL_MATCHES:
                        totalMatches = Integer.parseInt(txt);
                        break;
                }
    
                currentElement = ELEMENT_IS_UNKNOWN;
            }
    
            public void startElement(
                String uri,
                String localName,
                String qName,
                Attributes attr) throws SAXException
            {
                if (qName.equals("Result")) {
                    currentElement = ELEMENT_IS_RESULT;
                } else if (qName.equals("NumberReturned")) {
                    currentElement = ELEMENT_IS_NUMBER_RETURNED;
                } else if (qName.equals("TotalMatches")) {
                    currentElement = ELEMENT_IS_TOTAL_MATCHES;
                } else {
                    currentElement = ELEMENT_IS_UNKNOWN;
                }
            }
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -