www.gusucode.com > external 工具箱matlab源码程序 > external/interfaces/webservices/restful/+matlab/+internal/+webservices/HTTPJavaConnectionAdapter.m

    %matlab.internal.webservices.HTTPJavaConnectionAdapter HTTP connector handle object
%
%   FOR INTERNAL USE ONLY -- This class is intentionally undocumented and
%   is intended for use only within the scope of functions and classes in
%   toolbox/matlab/external/interfaces/webservices/restful. Its behavior
%   may change, or the class itself may be removed in a future release.
%
%   matlab.internal.webservices.HTTPJavaConnectionAdapter properties (read-only):
%      URL - URL string
%      ContentType - Connection content type
%      ContentEncoding - Encoding of content
%      ResponseCode - HTTP response code
%      RedirectURL - Redirection URL
%
%   matlab.internal.webservices.HTTPJavaConnectionAdapter properties:
%      RequestMethod - Name of request method
%      TimeoutInMilliseconds - Connection timeout in milliseconds
%
%   matlab.internal.webservices.HTTPJavaConnectionAdapter methods:
%      HTTPJavaConnectionAdapter - Constructor
%      closeConnection - Close HTTP connection
%      copyContentToByteArray - Copy content to byte array
%      copyContentToFile - Copy content to file
%      delete - Delete object
%      openConnection - Open HTTP connection
%      setRequestProperty - Set HTTP request property

% Copyright 2014-2016 The MathWorks, Inc.

classdef HTTPJavaConnectionAdapter < handle
  
    properties (Dependent)
        URL
        ContentType
        ContentEncoding
        ResponseCode
        RedirectURL
    end
        
    properties
        Username
        Password
        RequestMethod = 'GET'
        TimeoutInMilliseconds = 0
        Encoding = 0
        CertificateFilename = ''
    end
    
    properties (Hidden, Access = 'protected')
        ConnectionIsOpen = false
        Proxy = []
        Protocol = ''
        JavaURL = ''
        HttpURLConnection = []
    end
    
    properties (Access = 'private')
        pURL
    end
        
    methods
        
        function adapter = HTTPJavaConnectionAdapter(varargin)
        % Constructor for HTTPJavaConnectionAdapter class
        
            if isscalar(varargin)
                adapter.URL = varargin{1};
            end
        end
        
        %------------------------------------------------------------------
        
        function openConnection(adapter, varargin)
        % Open URL connection
            
            if ~adapter.ConnectionIsOpen
                url = adapter.JavaURL;
                if isscalar(varargin) && ~isempty(varargin{1})
                    proxy = varargin{1};
                    adapter.HttpURLConnection = url.openConnection(proxy);
                else
                   adapter.HttpURLConnection = url.openConnection;
                end
                
                if any(strcmpi(adapter.Protocol, {'http', 'https'}))
                   adapter.HttpURLConnection.setFollowRedirects(true);
                end
                setConnectionTimeout(adapter);
                
                if ~isempty(adapter.Username)
                    authorization = getBasicAuthorizationString( ...
                        adapter.Username, adapter.Password);
                    setRequestProperty(adapter, 'Authorization', authorization);
                end
                    
                adapter.ConnectionIsOpen = true;
            end
        end
        
        %------------------------------------------------------------------
        
        function openProxyConnection(adapter, ~)
        % Open proxy URL connection
            
            proxy = adapter.Proxy;
            openConnection(adapter, proxy);
        end
        
        %------------------------------------------------------------------
        
        function closeConnection(adapter)
        % Close connection
            
            if ~isempty(adapter.HttpURLConnection) ...
                    && isjava(adapter.HttpURLConnection)
                try
                    adapter.HttpURLConnection.disconnect;
                catch
                end               
                adapter.HttpURLConnection = [];
                adapter.ConnectionIsOpen = false;
            end
        end
        
        %------------------------------------------------------------------
        
        function delete(adapter)
        % Delete object
        
            % Ensure connection is closed.
            closeConnection(adapter)
        end
                         
        %------------------------------------------------------------------
        
        function byteArray = copyContentToByteArray(adapter)
        % Copy content from Web service to byte (uint8) array
            
            try
                % Get the input stream.
                inputStream = getConnectionInputStream(adapter);
                
                % Construct an output stream.
                outputStream = java.io.ByteArrayOutputStream;
                
                % Copy the data from the connection to the output stream.
                copyStream(adapter, inputStream, outputStream);
                
                % Convert the stream to a uint8 array.
                % Use typecast rather than casting to uint8 otherwise
                % certain values are truncated.
                byteArray = typecast(outputStream.toByteArray,'uint8');
            catch e
                throwAsCaller(e);
            end
        end
    
        %------------------------------------------------------------------
        
        function copyContentToFile(adapter, filename)
        % Copy content from Web service to file
            
            try
                % Get the input stream.
                inputStream = getConnectionInputStream(adapter);
                
                % Get an output stream for the file.
                outputStream = getFileOutputStream(filename);
                
                % Copy the data from the connection to the file.
                copyStream(adapter, inputStream, outputStream);
            catch e
                throwAsCaller(e);
            end
        end
                
        %------------------------------------------------------------------
        
        function setRequestProperty(adapter, name, value)
        % Set connection request property if name is not empty
        
            urlConnection = adapter.HttpURLConnection;
            if ~isempty(name) && ~isempty(urlConnection)
                try
                    % The setRequestProperty Java method can issue an error
                    % and should be invoked from within a try/catch to
                    % prevent a Java error from propagating to the user.
                    urlConnection.setRequestProperty(name, value);
                catch e
                    throwAsCaller(e);
                end
            end
        end
        
        %------------------------- set/get methods ------------------------
        
        function set.URL(adapter, url)
        % Set URL property value and update JavaURL, Protocol, and Proxy 
        % property values.
        
            % Store the URL property value in the private copy.
            adapter.pURL = url;
            
            % Construct and set JavaURL and Protocol.
            [adapter.JavaURL, adapter.Protocol] = constructURL(url); 
            
            % Get the proxy information using the MATLAB proxy API
            % and set the property.
            adapter.Proxy = getProxySettings(adapter.JavaURL);             
        end
           
        %------------------------------------------------------------------
        
        function url = get.URL(adapter)
            url = adapter.pURL;
        end
        
        %------------------------------------------------------------------
        
        function contentType = get.ContentType(adapter)
            if adapter.ConnectionIsOpen
                contentType = char(adapter.HttpURLConnection.getContentType());
            else
                contentType = '';
            end
        end
        
        %------------------------------------------------------------------
        
        function contentEncoding = get.ContentEncoding(adapter)
            if adapter.ConnectionIsOpen
                contentEncoding = char(adapter.HttpURLConnection.getContentEncoding());
            else
                contentEncoding = '';
            end
        end
        
        %------------------------------------------------------------------
        
        function code = get.ResponseCode(adapter)
            if adapter.ConnectionIsOpen
                try
                    code = adapter.HttpURLConnection.getResponseCode();
                catch
                    code = 400;
                end
            else
                code = 400;
            end
        end
        
        %------------------------------------------------------------------
        
        function url = get.RedirectURL(adapter)
            url = '';
            if adapter.ConnectionIsOpen
                try
                    url = adapter.HttpURLConnection.getHeaderField('Location');
                    url = char(url.toString);
                catch
                    url = '';
                end
            end
        end
    end
    
    methods (Access = 'protected')
        
        function setConnectionTimeout(adapter)            
            milliseconds = int32(adapter.TimeoutInMilliseconds);
            urlConnection = adapter.HttpURLConnection;
            urlConnection.setConnectTimeout(milliseconds);
            urlConnection.setReadTimeout(milliseconds);
        end
        
        %------------------------------------------------------------------
        
        function inputStream = getConnectionInputStream(adapter)
        % Obtain input stream from connection
            
            % Ensure the connection is open.
            openConnection(adapter, adapter.Proxy);
            
            % Get the input stream from the connection.
            try
                inputStream = adapter.HttpURLConnection.getInputStream;
            catch e
                % Construct an MException and include the HTTP response
                % code and message.
                e = constructResponseException(adapter, e);
                throwAsCaller(e);
            end
            
            switch adapter.Encoding
                case 1
                    inputStream = getGzipInputStream(inputStream);
                case 2
                    inputStream = getDeflaterInputStream(inputStream);
            end
        end
             
        %------------------------------------------------------------------
        
        function copyStream(adapter, inputStream, outputStream)
        % Copy data from inputStream to outputStream
            
            % Read the data from the connection and copy it to outputStream.
            % Use the InterruptibleStreamCopier to add ability to cntrl-c
            % the copy operation.
            copier = com.mathworks.mlwidgets.io.InterruptibleStreamCopier.getInterruptibleStreamCopier;
            closeObj = onCleanup(@()closeStreams(inputStream, outputStream));
            try
                copier.copyStream(inputStream, outputStream);
                closeConnection(adapter);
            catch e
                e = MException('MATLAB:webservices:CopyContentToDataStreamError', e.getMessage(), adapter.URL);
                throwAsCaller(e);
            end
        end
        
        %------------------------------------------------------------------
        
        function e = constructResponseException(adapter, e)
        % Construct an MException consisting of the URL, response code and
        % message
            
            url = adapter.URL;
            if strcmp(adapter.Protocol, 'file')
                % file protocol.
                % Parse the error message provided.
                timeout = connectionTimeoutInSeconds(adapter);
                [msg, id] = parseErrorMessage(e, url, timeout, adapter.ResponseCode);
            else
                % http, https protocol
                % Parse the response message.
                [msg, id] = parseResponseMessage(adapter, e, url);
            end
            
            % Construct an MException from the message string.
            % Avoid sprintf issues by using '%s'.
            msg = msg.getString();
            e = MException(id, '%s', msg);
        end
        
        %------------------------------------------------------------------
        
        function [msg, id] = parseResponseMessage(adapter, e, url)
        % Construct a message and message id consisting of the URL,
        % response code and message
            
            connection = adapter.HttpURLConnection;
            try
                % Get the server response to be included in the error message.
                response = char(connection.getResponseMessage);
                if strcmp(response, 'OK')
                    % The response message in this case does not contain
                    % any error information. Use the message in the
                    % ExceptionObject instead.
                    response = getLocalizedMessage(e);
                end
                
                % Get the numeric response code and convert to char to
                % include in the message body and use the response code as
                % part of the message ID. If the code is less than 0
                % (typically -1) (the response is not valid HTTP), then set
                % to 'Unknown'. Use the getResponseCode() method of the
                % Java connection object (rather than adapter.ResponseCode)
                % to ensure that the code is valid. If not, an error is
                % issued, and caught below. 
                responseCode = connection.getResponseCode();
                if responseCode >= 0
                    responseCodeString = responseCode;
                else
                    responseCodeString = adapter.ResponseCode;
                end
                
                % Construct a message with the response code and response.
                % Use CopyContentToDataStreamError ID to obtain the correct
                % message catalog entry.
                id = 'MATLAB:webservices:StatusError';
                msg = message(id, responseCodeString, response, url);
                
                % Reset ID to include HTTP status code.
                id = ['MATLAB:webservices:HTTP' num2str(responseCodeString) 'StatusCodeError'];
            catch e2
                if ~isa(e2,'matlab.exception.JavaException')
                    % The new exception does not contain a Java exception
                    % object. Use the original MException object.
                    e2 = e;
                end
                % Parse the exception to obtain a meaningful message.
                timeout = connectionTimeoutInSeconds(adapter);
                [msg, id] = parseErrorMessage(e2, url, timeout, adapter.ResponseCode);
            end
        end
        
        %------------------------------------------------------------------
        
        function seconds = connectionTimeoutInSeconds(adapter)
        % Return connection value in seconds, empty if unknown
        
            connection = adapter.HttpURLConnection;
            if ~isempty(connection) && isjava(connection)
                milliseconds = adapter.HttpURLConnection.getConnectTimeout;
                seconds = milliseconds / 1000;
            else
                seconds = [];
            end
        end
    end
end

%--------------------------------------------------------------------------

function [jurl, protocol] = constructURL(url)
% Construct a java.net.URL given a URL string and its protocol

% Get the protocol (before the ":") from the URL.
protocol = getProtocolFromURL(url);

% Get the handler.
handler = getProtocolHandler(protocol);

try
    jurl = java.net.URL([], url, handler);
catch
    try
        jurl = java.net.URL(url);
    catch
        error(message('MATLAB:webservices:MalformedURL', url))
    end
end
end

%--------------------------------------------------------------------------

function handler = getProtocolHandler(protocol)
% Get handler based on protocol

if strcmp('https', protocol)
    handler = sun.net.www.protocol.https.Handler;
elseif strcmp('http', protocol)
    handler = sun.net.www.protocol.http.Handler;
else
    handler = [];
end
end

%--------------------------------------------------------------------------

function proxy = getProxySettings(jurl)
% Get proxy information for a Java URL

% Set the default authenticator to null to fix g999501
java.net.Authenticator.setDefault([]);
            
% Get the proxy information using the MATLAB proxy API.
% Be sure the proxy settings are set.
com.mathworks.mlwidgets.html.HTMLPrefs.setProxySettings

% Get the proxy settings.
proxy = com.mathworks.webproxy.WebproxyFactory.findProxyForURL(jurl);

end

%--------------------------------------------------------------------------

function protocol = getProtocolFromURL(url)
% Get protocol (http or https) from URL

protocol = url(1:find(url == ':', 1) -1);
end

%--------------------------------------------------------------------------

function inputStream = getGzipInputStream(inputStream)
% Obtain GZIPInputStream, if available

try
    inputStream = java.util.zip.GZIPInputStream(inputStream);
catch
    % Use default inputStream
end
end

%--------------------------------------------------------------------------

function inputStream = getDeflaterInputStream(inputStream)
% Obtain DeflaterInputStream, if available

try
    inputStream = java.util.zip.InflaterInputStream(inputStream);
catch
    % Use default inputStream
end
end

%--------------------------------------------------------------------------

function [msg, id] = parseErrorMessage(e, url, timeout, code)
% Construct a meaningful string from the error message

id = 'MATLAB:webservices:';
if ~isa(e,'matlab.exception.JavaException')
    exceptionClass = 'unknown';
else
    exceptionClass = class(e.ExceptionObject);
end

switch exceptionClass
    case 'java.net.SocketTimeoutException'
        id = [id 'Timeout'];
        value = num2str(timeout);
        msg = message(id, url, value, 'options.Timeout');
        
    case 'java.net.UnknownHostException'
        host = getLocalizedMessage(e);
        id = [id 'UnknownHost'];
        msg = message(id, host);
        
    case 'java.io.FileNotFoundException'
        id = [id 'FileNotFound'];
        msg = message(id, url);
        
    case 'unknown'
        id = [id 'ConnectionFailed'];
        msg = message(id, url);
        
    otherwise
        if strfind(e.message,'java.net.Authenticator.requestPasswordAuthentication')
            id = [id 'BasicAuthenticationFailed'];
            msg = message(id, url, 'Basic', 'options.Username', 'options.Password');
        else
            response = getLocalizedMessage(e);
            id = 'MATLAB:webservices:StatusError';
            msg = message(id, code, response, url);
        end
end
end

%--------------------------------------------------------------------------

function msg = getLocalizedMessage(e)
% Obtain localized message from exception object

if isa(e,'matlab.exception.JavaException')
    msg = char(e.ExceptionObject.getLocalizedMessage);
else
    msg = e.message;
end
end

%--------------------------------------------------------------------------

function fileOutputStream = getFileOutputStream(filename)
% Construct fileOutputStream for filename

% Create a Java File object.
file = java.io.File(filename);

% Ensure it is an absolute path.
if ~file.isAbsolute
    % Specify the full path to the file.
    location = fullfile(pwd, filename);
    file = java.io.File(location);
end

try
    % Make sure the path isn't nonsense.
    file = file.getCanonicalFile;
    
    % Open the output file.
    fileOutputStream = java.io.FileOutputStream(file);
catch e
    e = MException(message('MATLAB:webservices:InvalidFilename', ...
        char(file.getAbsolutePath)));
    throwAsCaller(e);
end
end

%--------------------------------------------------------------------------

function closeStreams(inputStream, outputStream)
% Close streams

if exist('outputStream','var') && ~isempty(outputStream)
    org.apache.commons.io.IOUtils.closeQuietly(outputStream)
end
if  exist('inputStream','var') && ~isempty(inputStream)
    org.apache.commons.io.IOUtils.closeQuietly(inputStream)
end
end

%--------------------------------------------------------------------------

function authorization = getBasicAuthorizationString(username, password)
% Create a string suitable for basic authorization.

usernamePassword = [username ':' password];
usernamePasswordBytes = int8(usernamePassword)';
usernamePasswordBase64 = base64Encode(usernamePasswordBytes);
authorization = ['Basic ' usernamePasswordBase64];
end

%--------------------------------------------------------------------------

function encoded = base64Encode(value)
% Use base64 encoding to encode value.

encoded = char(org.apache.commons.codec.binary.Base64.encodeBase64(value)');
end