CONTENTS | PREV | NEXT | INDEX JMF 2.0 API Guide



D

Sample Data Source Implementation

This sample demonstrates how to implement a new DataSource to support an additional protocol, the FTP protocol. There are two classes:

Example D-1: FTP Data Source. (1 of 8)
 package COM.intel.media.protocol.ftp;
 
 import javax.media.protocol.PullDataSource;
 import javax.media.protocol.SourceStream;
 import javax.media.protocol.PullSourceStream;
 import javax.media.Time;
 import javax.media.Duration;
 import java.io.*;
 import java.net.*;
 import java.util.Vector;
 
 public class DataSource extends PullDataSource
 {
    public static final int FTP_PORT = 21;
    public static final int FTP_SUCCESS = 1;
    public static final int FTP_TRY_AGAIN = 2;
    public static final int FTP_ERROR = 3;
 
    // used to send commands to server
    protected Socket controlSocket;   
           
    // used to receive file
    protected Socket dataSocket;     
    // wraps controlSocket's output stream
    protected PrintStream controlOut;     
        
    // wraps controlSocket's input stream
    protected InputStream controlIn;   
        
    // hold (possibly multi-line) server response
    protected Vector response = new Vector(1);  
     
    // reply code from previous command
    protected int previousReplyCode;       
    
    // are we waiting for command reply?
    protected boolean replyPending;   
            
    // user login name
     protected String user = "anonymous"; 
         
    // user login password
    protected String password = "anonymous";  
    
    // FTP server name
    protected String hostString;         
      
    // file to retrieve
    protected String fileString;           
 
    public void connect() throws IOException
    {
       initCheck();  // make sure the locator is set
       if (controlSocket != null)
       {
          disconnect();
       }
       // extract FTP server name and target filename from locator
       parseLocator();   
       controlSocket = new Socket(hostString, FTP_PORT);
       controlOut = new PrintStream(new BufferedOutputStream(
          controlSocket.getOutputStream()), true);
       controlIn = new
          BufferedInputStream(controlSocket.getInputStream());
     
      if (readReply() == FTP_ERROR)
       {
           throw new IOException("connection failed");
       }
       
       if (issueCommand("USER " + user) == FTP_ERROR)
       {
          controlSocket.close();
          
          throw new IOException("USER command failed");
       }
 
       if (issueCommand("PASS " + password) == FTP_ERROR)
       {
          controlSocket.close();
          throw new IOException("PASS command failed");
       }
    }
 
    public void disconnect()
    {
       if (controlSocket == null)
       {
          return;
       }
 
       try
       {
          issueCommand("QUIT");
          controlSocket.close();
       }
 
       catch (IOException e) 
       {
          // do nothing, we just want to shutdown
       }
 
       controlSocket = null;
       controlIn = null;
       controlOut = null;
    }
 
     public void start() throws IOException
     {
          ServerSocket serverSocket;
          InetAddress myAddress = InetAddress.getLocalHost();
          byte[] address = myAddress.getAddress();
 
          String portCommand = "PORT ";
          serverSocket = new ServerSocket(0, 1);
 
          // append each byte of our address (comma-separated)
 
          for (int i = 0; i < address.length; i++)
          {
             portCommand = portCommand + (address[i] & 0xFF) + ",";
          }
 
       // append our server socket's port as two comma-separated
       // hex bytes
          portCommand = portCommand +
             ((serverSocket.getLocalPort() >>> 8) 
             & 0xFF) + "," + (serverSocket.getLocalPort() & 0xFF);
 
          // issue PORT command
          if (issueCommand(portCommand) == FTP_ERROR)
          {
             serverSocket.close();
             throw new IOException("PORT");
          }
 
          // issue RETRieve command
          if (issueCommand("RETR " + fileString) == FTP_ERROR)
          {
             serverSocket.close();
             throw new IOException("RETR");
          }
 
          dataSocket = serverSocket.accept();
          serverSocket.close();
    }
    public void stop()
    {
       try
       {
       // issue ABORt command
       issueCommand("ABOR");
       dataSocket.close();
       }
       catch(IOException e) {}
    }
 
    public String getContentType()
    {
     // We don't get MIME info from FTP server.  This
     // implementation makes an attempt guess the type using
     // the File name and returns "unknown" in the default case.
     // A more robust mechanisms should
     // be supported for real-world applications.
 
       String locatorString = getLocator().toExternalForm();
       int dotPos = locatorString.lastIndexOf(".");
       String extension = locatorString.substring(dotPos + 1);
       String typeString = "unknown";
 
       if (extension.equals("avi"))
          typeString = "video.x-msvideo";
       else if (extension.equals("mpg") ||     
          extension.equals("mpeg"))
          typeString = "video.mpeg";
       else if (extension.equals("mov"))
          typeString = "video.quicktime";
       else if (extension.equals("wav"))
          typeString = "audio.x-wav";
       else if (extension.equals("au"))
          typeString = "audio.basic";
       return typeString;
    }
 
    public PullSourceStream[] getStreams()
    {
       PullSourceStream[] streams = new PullSourceStream[1];
       try
       {
          streams[0] = new FTPSourceStream(dataSocket.getInputStream());
       }
 
       catch(IOException e)
       {
          System.out.println("error getting streams");
       }
       return streams;
    }
 
 
 
    public Time getDuration()
    {
       return Duration.DURATION_UNKNOWN;
    }
 
    public void setUser(String user)
 
    {
       this.user = user;
    }
 
    public String getUser()
    {
       return user;
    }
 
    public void setPassword(String password)
    {
       this.password = password;
    }
 
    public String getPassword()
    {
       return password;
    }
    private int readReply() throws IOException
    {
       previousReplyCode = readResponse();
       System.out.println(previousReplyCode);
       switch (previousReplyCode / 100)
       {
          case 1:
             replyPending = true;
             // fall through
          case 2:
          case 3:
             return FTP_SUCCESS;
          case 5:
             if (previousReplyCode == 530)
             {
                if (user == null)
                {
                   throw new IOException("Not logged in");
                }
                return FTP_ERROR;
             }
             if (previousReplyCode == 550)
             {
                throw new FileNotFoundException();
             }
       }
       return FTP_ERROR;
     }
 
    /**
     * Pulls the response from the server and returns the code as a
     * number. Returns -1 on failure.
     */
 
    private int readResponse() throws IOException
    {
       StringBuffer buff = new StringBuffer(32);
       String responseStr;
       int   c;
       int   continuingCode = -1;
       int   code = 0;
 
       response.setSize(0);
       
       while (true)
       {
          while ((c = controlIn.read()) != -1)
          {
             if (c == '\r')
             {
                if ((c = controlIn.read()) != '\n')
                {
                   buff.append('\r');
                }
             }
             buff.append((char)c);
 
 
             if (c == '\n')
             {
                 break;
             }
          }
          responseStr = buff.toString();
          buff.setLength(0);
          try
          {
             code = Integer.parseInt(responseStr.substring(0, 3));
          }
          catch (NumberFormatException e)
          {
             code = -1;
          }
          catch (StringIndexOutOfBoundsException e)
          {
             /* this line doesn't contain a response code, so
              * we just completely ignore it 
              */
              continue;
          }
          response.addElement(responseStr);
          if (continuingCode != -1)
          {
             /* we've seen a XXX- sequence */
             if (code != continuingCode ||
                (responseStr.length() >= 4 && 
                responseStr.charAt(3) == '-'))
             {
                 continue;
             }
             else
             {
                /* seen the end of code sequence */
                continuingCode = -1;
                break;
             }
          }
          else if (responseStr.length() >= 4 &&
             responseStr.charAt(3) == '-')
          {
             continuingCode = code;
             continue;
          }
          else
          {
             break;
          }
       }
 
       previousReplyCode = code;
       return code;
    }
 
    private int issueCommand(String cmd) throws IOException
    {
       int reply;
       if (replyPending)
       {
          if (readReply() == FTP_ERROR)
          {
             System.out.print("Error reading pending reply\n");
          }
       }
       replyPending = false;
       do
       {
          System.out.println(cmd);
          controlOut.print(cmd + "\r\n");
          reply = readReply();
       } while (reply == FTP_TRY_AGAIN);
       return reply;
    }
    /**
     * Parses the mediaLocator field into host and file strings
     */
 
    protected void parseLocator()
    {
       initCheck();
       String rest = getLocator().getRemainder();
       System.out.println("Begin parsing of: " + rest);
       int p1, p2 = 0;
       p1 = rest.indexOf("//");
       p2 = rest.indexOf("/", p1+2);
       hostString = rest.substring(p1 + 2, p2);
       fileString = rest.substring(p2);
       System.out.println("host: " + hostString + "   file: " 
          + fileString);
    }
 }

Source Stream

Example D-2:
  package intel.media.protocol.ftp;
 
  import java.io.*;
 import javax.media.protocol.ContentDescriptor;
 import javax.media.protocol.PullSourceStream;
 import javax.media.protocol.SourceStream;
 
 public class FTPSourceStream implements PullSourceStream
 {
    protected InputStream dataIn;
    protected boolean eofMarker;
    protected ContentDescriptor cd;
 
    public FTPSourceStream(InputStream in)
    {
       this.dataIn = in;
       eofMarker = false;
       cd = new ContentDescriptor("unknown");
    }
 
    // SourceSteam methods
 
    public ContentDescriptor getContentDescriptor()
    {
       return cd;
    }
 
    public void close() throws IOException
    {
       dataIn.close();
    }
 
    public boolean endOfStream()
    {
       return eofMarker;
    }
 
    // PullSourceStream methods
 
    public int available() throws IOException
    {
       return dataIn.available();
    }
    public int read(byte[] buffer, int offset, int length) throws 
IOException
    {
       int n = dataIn.read(buffer, offset, length);
       if (n == -1)
       {
          eofMarker = true;
       }
       return n;
    }
 
    public boolean willReadBlock() throws IOException
    {
       if(eofMarker) 
       {
          return true;
       } 
       else 
       {
          return 	 dataIn.available() == 0;
       }
    }
 
    public long getContentLength()
    {
       return SourceStream.LENGTH_UNKNOWN;
    }
 }



CONTENTS | PREV | NEXT | INDEX

Copyright © 1998-1999 Sun Microsystems, Inc. All Rights Reserved.