adskHttpSchemeResolver.py

"""
Custom file resolver derived from MPxFileResolver that handles
the URI 'htpp' scheme.
When this resolver is active, URI file paths using the 'http://<domain>/'
scheme will be processed using methods on this class.
Refer to MPxFileResolver for more information about custom file resolvers.

To use, make sure that adskHttpSchemeResolver.py is in
your MAYA_PLUG_IN_PATH then do the following:

# Load the plug-in
import maya.cmds
maya.cmds.loadPlugin("adskHttpSchemeResolver.py")
# Once loaded, Maya will call the resolver methods in this plug-in when
# a URI file path is encountered during file resolution processing
# (file open, setAttr, etc.)
# Unload the plug-in
maya.cmds.unloadPlugin("adskHttpSchemeResolver")
# Maya will no longer have access to this file
# resolver to handle URI file paths using the 'http:///' scheme  

"""

import sys
import maya.OpenMaya as OpenMaya
import maya.OpenMayaMPx as OpenMayaMPx
import maya.cmds as cmds
import urllib 
import os.path


#Specify the location for downloaded file
kTempDir = cmds.internalVar(userTmpDir=True)

# Set status messages on or off 
kWantStatusOutput = True; 

def downloadProgress(data, dataSize, fileSize):
    """ Display download progress - callback invoked by urllib.urlretrieve """
    percent = 100.0*data*dataSize/fileSize
    if percent > 100:
        percent = 100
    printStatus('Download progress: %.2f%%' % (percent))

def printStatus(msg):
    """ Print status output for diagnostic purposes (when enabled) """
    if (kWantStatusOutput):
        sys.stderr.write('%s: %s\n' % (adskHttpSchemeResolver.className(), msg) )

def printWarning(msg):
    """ Print warning messages """
    sys.stderr.write('Warning %s: %s\n' % (adskHttpSchemeResolver.className(), msg) )



# 'http' scheme resolver 
class adskHttpSchemeResolver(OpenMayaMPx.MPxFileResolver):
    """
    This custom plug-in resolver handles the 'http' uri scheme.
    This resolver will copy the file from its 'http' location 
    using standard url library to a temporary location. This temporary location
    of the file is the fully qualified resolved path.
    It also implements a crude caching system.
    """

    kPluginURIScheme = "http"
    kPluginResolverName = "adskHttpSchemeResolver"

    def __init__(self):
        OpenMayaMPx.MPxFileResolver.__init__(self)

    def uriScheme(self):
        return(self.kPluginURIScheme)

    def resolveURI(self,URI,mode):
        # Determine temporary location that will be used for this file
        uri = URI.asString()
        tempFile = kTempDir + URI.getFileName()
        result = u''

        # Check resolver mode, since not all modes require the file
        # to be downloaded.

        # When mode is kNone, simply return the resolved path
        if mode & OpenMayaMPx.MPxFileResolver.kNone:
            result = tempFile;
        
        # When mode is kInput, Maya is expecting to use this
        # file for input. Download the file to the temporary storage
        # area if it hasn't already been done. 
        elif mode & OpenMayaMPx.MPxFileResolver.kInput: 
            if not os.path.exists(tempFile):
                # If the file does not exist in the cache then go and
                # download it. At this point we assume we have a well
                # formed URI and that it exists on the web somewhere
                # Any error here and the resolved file is simply not
                # found. Would need to code for all the errors that
                # could go wrong here in a production case (lost
                # connections, server down, etc.)
                printStatus('Downloading URI: %s to location: %s' % (uri, tempFile))

                data = urllib.urlretrieve(uri, tempFile, downloadProgress)
                if os.path.exists(tempFile):
                    printStatus('Download complete')
                else:
                    printWarning('Download failed for URI: %s to location: %s'
                             % (uri, tempFile))
                result = tempFile
            else:
                printStatus('Download skipped, using cached version of URI: %s at location: %s'
                        % (uri, tempFile))
                result = tempFile

        # Unexpected mode - simply return the resolved path 
        else:
            printWarning('Unexpected resolve mode encountered: %s' % str(mode))
            result = tempFile

        # Return the resolved path  
        return result

    def performAfterSaveURI(self,URI,resolvedFullPath):
        uri = URI.asString()
        printStatus('Uploading local file %s to URI location %s'
                        % (resolvedFullPath, uri))

    @staticmethod
    # Creator for the proxy instance 
    def theCreator():
        return OpenMayaMPx.asMPxPtr( adskHttpSchemeResolver() )

    @staticmethod
    def className():
        return 'adskHttpSchemeResolver'

    

# Initialize the script plug-in
def initializePlugin(plugin):
    pluginFn = OpenMayaMPx.MFnPlugin(plugin)
    try:
        pluginFn.registerURIFileResolver( adskHttpSchemeResolver.kPluginResolverName,
                          adskHttpSchemeResolver.kPluginURIScheme,
                          adskHttpSchemeResolver.theCreator )
    except:
        sys.stderr.write( "Failed to register custom resolver: %s for scheme: %s\n" %
                  (adskHttpSchemeResolver.kPluginResolverName,
                   adskHttpSchemeResolver.kPluginURIScheme ))
        raise

# Uninitialize the script plug-in
def uninitializePlugin(plugin):
    pluginFn = OpenMayaMPx.MFnPlugin(plugin)
    try:
        pluginFn.deregisterURIFileResolver(adskHttpSchemeResolver.kPluginResolverName)
    except:
        sys.stderr.write(
            "Failed to deregister custom file resolver: %s\n" %
            adskHttpSchemeResolver.kPluginResolverName)
        raise

#-
# ==========================================================================
# Copyright (C) 2012 Autodesk, Inc. and/or its licensors.  All
# rights reserved.
#
# The coded instructions, statements, computer programs, and/or related
# material (collectively the "Data") in these files contain unpublished
# information proprietary to Autodesk, Inc. ("Autodesk") and/or its
# licensors, which is protected by U.S. and Canadian federal copyright
# law and by international treaties.
#
# The Data is provided for use exclusively by You. You have the right
# to use, modify, and incorporate this Data into other products for
# purposes authorized by the Autodesk software license agreement,
# without fee.
#
# The copyright notices in the Software and this entire statement,
# including the above license grant, this restriction and the
# following disclaimer, must be included in all copies of the
# Software, in whole or in part, and all derivative works of
# the Software, unless such copies or derivative works are solely
# in the form of machine-executable object code generated by a
# source language processor.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
# AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED
# WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF
# NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
# PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR
# TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS
# BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL,
# DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK
# AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY
# OR PROBABILITY OF SUCH DAMAGES.
#
# ==========================================================================
#+