📄 datasource.java
字号:
package net.sf.fmj.media.protocol.httpauth;import java.io.IOException;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.net.URLConnection;import java.util.logging.Level;import java.util.logging.Logger;import javax.media.MediaLocator;import javax.media.Time;import javax.media.protocol.ContentDescriptor;import javax.media.protocol.PullDataSource;import javax.media.protocol.PullSourceStream;import javax.media.protocol.SourceCloneable;import net.sf.fmj.utility.LoggerSingleton;import net.sf.fmj.utility.StringUtils;/** * This is a pseudo-protocol that allows the username and password for an http datasource to be specified in the URL. * Copied and modified from URLDataSource. * The syntax for an httpauth URL is derived from an http URL as follows: * http://myipcameraimage.com/cam * with username "user" and password "pass" would become * httpauth:user:pass@//myipcameraimage.com/cam * This is simply a convenience data source. It allows things like FMJ studio to play IP camera streams that are password protected, without having to prompt the user. * * @author Ken Larson * */public class DataSource extends PullDataSource implements SourceCloneable{ private static final Logger logger = LoggerSingleton.logger; private URLConnection conn; private boolean connected = false; private String contentTypeStr; private ContentDescriptor contentType; protected URLSourceStream[] sources; public DataSource() { super(); } public DataSource(URL url) { setLocator(new MediaLocator(url)); } public javax.media.protocol.DataSource createClone() { final DataSource d; try { d = new DataSource(getLocator().getURL()); } catch (MalformedURLException e) { logger.log(Level.WARNING, "" + e, e); return null; // according to the API, return null on failure. } if (connected) { try { d.connect(); } catch (IOException e) { logger.log(Level.WARNING, "" + e, e); return null; // according to the API, return null on failure. } } return d; } public PullSourceStream[] getStreams() { if (!connected) throw new Error("Unconnected source."); return sources; } /** Strips trailing ; and anything after it. Is generally only used for multipart content. */ private String stripTrailer(String contentType) { final int index = contentType.indexOf(";"); if (index < 0) return contentType; final String result = contentType.substring(0, index); return result; } public void connect() throws IOException { // we allow a re-connection even if we are connected, due to an oddity in the way Manager works. See comments there // in createPlayer(MediaLocator sourceLocator).//// if (connected)// return; // example: httpauth:guest:guest@// + real url without http: final String remainder = getLocator().getRemainder(); final int atIndex = remainder.indexOf('@'); if (atIndex < 0) throw new IOException("Invalid httpauth url: expected: @"); final int colonIndex = remainder.indexOf(':'); if (colonIndex < 0 || colonIndex > atIndex) throw new IOException("Invalid httpaut url: expected: :"); final String user = remainder.substring(0, colonIndex); final String pass = remainder.substring(colonIndex + 1, atIndex); final String realUrlStr = "http:" + getLocator().getRemainder().substring(atIndex + 1); conn = new URL(realUrlStr).openConnection(); if (conn instanceof HttpURLConnection) { // TODO: this is probably why JMF has explicit HTTP and FTP data sources - so we can check things explicitly. final HttpURLConnection huc = (HttpURLConnection) conn; if (user != null && !user.equals("")) { huc.setRequestProperty("Authorization", "Basic " + StringUtils.byteArrayToBase64String((user + ":" + pass).getBytes())); } huc.connect(); final int code = huc.getResponseCode(); if (!(code >= 200 && code < 300)) { huc.disconnect(); throw new IOException("HTTP response code: " + code); } // TODO: what is the right place to apply ContentDescriptor.mimeTypeToPackageName? contentTypeStr = ContentDescriptor.mimeTypeToPackageName(stripTrailer(conn.getContentType())); } else { conn.connect(); // TODO: what is the right place to apply ContentDescriptor.mimeTypeToPackageName? contentTypeStr = ContentDescriptor.mimeTypeToPackageName(conn.getContentType()); } contentType = new ContentDescriptor(contentTypeStr); sources = new URLSourceStream[1]; sources[0] = new URLSourceStream(); connected = true; } public String getContentType() { return contentTypeStr; } public void disconnect() { if (!connected) return; if (conn != null) { if (conn instanceof HttpURLConnection) { final HttpURLConnection huc = (HttpURLConnection) conn; huc.disconnect(); } // TODO: others } connected = false; } public void start() throws java.io.IOException { //throw new UnsupportedOperationException(); // TODO - what to do? } public void stop() throws java.io.IOException { //throw new UnsupportedOperationException(); // TODO - what to do? } public Time getDuration() { return Time.TIME_UNKNOWN; // TODO: any case where we know the duration? } public Object[] getControls() { return new Object[0]; } public Object getControl(String controlName) { return null; } class URLSourceStream implements PullSourceStream { private boolean endOfStream = false; public boolean endOfStream() { return endOfStream; } public ContentDescriptor getContentDescriptor() { return contentType; } public long getContentLength() { return conn.getContentLength(); // returns -1 if unknown, which is the same as LENGTH_UNKNOWN } public int read(byte[] buffer, int offset, int length) throws IOException { final int result = conn.getInputStream().read(buffer, offset, length); // TODO: does this handle the requirement of not returning 0 unless passed in 0? if (result == -1) // end of stream endOfStream = true; return result; } public boolean willReadBlock() { try { return conn.getInputStream().available() <= 0; } catch (IOException e) { return true; } } public Object getControl(String controlType) { return null; } public Object[] getControls() { return new Object[0]; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -