xref: /AOO41X/main/pyuno/source/loader/pythonloader.py (revision d912c6c57b46260843f1be9adddb49aacbbd5fb4)
1a0428e9eSAndrew Rist#**************************************************************
2cdf0e10cSrcweir#
3a0428e9eSAndrew Rist#  Licensed to the Apache Software Foundation (ASF) under one
4a0428e9eSAndrew Rist#  or more contributor license agreements.  See the NOTICE file
5a0428e9eSAndrew Rist#  distributed with this work for additional information
6a0428e9eSAndrew Rist#  regarding copyright ownership.  The ASF licenses this file
7a0428e9eSAndrew Rist#  to you under the Apache License, Version 2.0 (the
8a0428e9eSAndrew Rist#  "License"); you may not use this file except in compliance
9a0428e9eSAndrew Rist#  with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir#
11a0428e9eSAndrew Rist#    http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir#
13a0428e9eSAndrew Rist#  Unless required by applicable law or agreed to in writing,
14a0428e9eSAndrew Rist#  software distributed under the License is distributed on an
15a0428e9eSAndrew Rist#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16a0428e9eSAndrew Rist#  KIND, either express or implied.  See the License for the
17a0428e9eSAndrew Rist#  specific language governing permissions and limitations
18a0428e9eSAndrew Rist#  under the License.
19cdf0e10cSrcweir#
20a0428e9eSAndrew Rist#**************************************************************
21cdf0e10cSrcweirimport uno
22cdf0e10cSrcweirimport unohelper
23cdf0e10cSrcweirimport sys
24cdf0e10cSrcweirimport imp
25cdf0e10cSrcweirimport os
26cdf0e10cSrcweirfrom com.sun.star.uno import Exception,RuntimeException
27cdf0e10cSrcweirfrom com.sun.star.loader import XImplementationLoader
28cdf0e10cSrcweirfrom com.sun.star.lang import XServiceInfo
29cdf0e10cSrcweir
30cdf0e10cSrcweirMODULE_PROTOCOL = "vnd.openoffice.pymodule:"
31cdf0e10cSrcweirDEBUG = 0
32cdf0e10cSrcweir
33cdf0e10cSrcweirg_supportedServices  = "com.sun.star.loader.Python",      # referenced by the native C++ loader !
34cdf0e10cSrcweirg_implementationName = "org.openoffice.comp.pyuno.Loader" # referenced by the native C++ loader !
35cdf0e10cSrcweir
36cdf0e10cSrcweirdef splitUrl( url ):
37cdf0e10cSrcweir    nColon = url.find( ":" )
38cdf0e10cSrcweir    if -1 == nColon:
39cdf0e10cSrcweir        raise RuntimeException( "PythonLoader: No protocol in url " + url, None )
40cdf0e10cSrcweir    return url[0:nColon], url[nColon+1:len(url)]
41cdf0e10cSrcweir
42cdf0e10cSrcweirg_loadedComponents = {}
43cdf0e10cSrcweirdef checkForPythonPathBesideComponent( url ):
44cdf0e10cSrcweir    path = unohelper.fileUrlToSystemPath( url+"/pythonpath.zip" );
45cdf0e10cSrcweir    if DEBUG == 1:
46*d912c6c5SPedro Giffuni        print("checking for existence of " + encfile( path ))
47cdf0e10cSrcweir    if 1 == os.access( encfile( path ), os.F_OK) and not path in sys.path:
48cdf0e10cSrcweir        if DEBUG == 1:
49*d912c6c5SPedro Giffuni            print("adding " + encfile( path ) + " to sys.path")
50cdf0e10cSrcweir        sys.path.append( path )
51cdf0e10cSrcweir
52cdf0e10cSrcweir    path = unohelper.fileUrlToSystemPath( url+"/pythonpath" );
53cdf0e10cSrcweir    if 1 == os.access( encfile( path ), os.F_OK) and not path in sys.path:
54cdf0e10cSrcweir        if DEBUG == 1:
55*d912c6c5SPedro Giffuni            print("adding " + encfile( path ) + " to sys.path")
56cdf0e10cSrcweir        sys.path.append( path )
57cdf0e10cSrcweir
58cdf0e10cSrcweirdef encfile(uni):
59cdf0e10cSrcweir    return uni.encode( sys.getfilesystemencoding())
60cdf0e10cSrcweir
61cdf0e10cSrcweirclass Loader( XImplementationLoader, XServiceInfo, unohelper.Base ):
62cdf0e10cSrcweir    def __init__(self, ctx ):
63cdf0e10cSrcweir        if DEBUG:
64*d912c6c5SPedro Giffuni            print("pythonloader.Loader ctor")
65cdf0e10cSrcweir        self.ctx = ctx
66cdf0e10cSrcweir
67cdf0e10cSrcweir    def getModuleFromUrl( self, url ):
68cdf0e10cSrcweir        if DEBUG:
69*d912c6c5SPedro Giffuni            print("pythonloader: interpreting url " +url)
70cdf0e10cSrcweir        protocol, dependent = splitUrl( url )
71cdf0e10cSrcweir        if "vnd.sun.star.expand" == protocol:
72cdf0e10cSrcweir            exp = self.ctx.getValueByName( "/singletons/com.sun.star.util.theMacroExpander" )
73cdf0e10cSrcweir            url = exp.expandMacros(dependent)
74cdf0e10cSrcweir            protocol,dependent = splitUrl( url )
75cdf0e10cSrcweir
76cdf0e10cSrcweir        if DEBUG:
77*d912c6c5SPedro Giffuni            print("pythonloader: after expansion " +protocol +":" + dependent)
78cdf0e10cSrcweir
79cdf0e10cSrcweir        try:
80cdf0e10cSrcweir            if "file" == protocol:
81cdf0e10cSrcweir                # remove \..\ sequence, which may be useful e.g. in the build env
82cdf0e10cSrcweir                url = unohelper.absolutize( url, url )
83cdf0e10cSrcweir
84cdf0e10cSrcweir                # did we load the module already ?
85cdf0e10cSrcweir                mod = g_loadedComponents.get( url )
86cdf0e10cSrcweir                if not mod:
87cdf0e10cSrcweir                    mod = imp.new_module("uno_component")
88cdf0e10cSrcweir
89cdf0e10cSrcweir                    # check for pythonpath.zip beside .py files
90cdf0e10cSrcweir                    checkForPythonPathBesideComponent( url[0:url.rfind('/')] )
91cdf0e10cSrcweir
92cdf0e10cSrcweir                    # read the file
93cdf0e10cSrcweir                    filename = unohelper.fileUrlToSystemPath( url )
94cdf0e10cSrcweir                    fileHandle = file( filename )
95cdf0e10cSrcweir                    src = fileHandle.read().replace("\r","")
96cdf0e10cSrcweir                    if not src.endswith( "\n" ):
97cdf0e10cSrcweir                        src = src + "\n"
98cdf0e10cSrcweir
99cdf0e10cSrcweir                    # compile and execute the module
100cdf0e10cSrcweir                    codeobject = compile( src, encfile(filename), "exec" )
101*d912c6c5SPedro Giffuni                    exec(codeobject, mod.__dict__)
102cdf0e10cSrcweir                    mod.__file__ = encfile(filename)
103cdf0e10cSrcweir                    g_loadedComponents[url] = mod
104cdf0e10cSrcweir                return mod
105cdf0e10cSrcweir            elif "vnd.openoffice.pymodule" == protocol:
106cdf0e10cSrcweir                return  __import__( dependent )
107cdf0e10cSrcweir            else:
108cdf0e10cSrcweir                raise RuntimeException( "PythonLoader: Unknown protocol " +
109cdf0e10cSrcweir                                        protocol + " in url " +url, self )
110*d912c6c5SPedro Giffuni        except ImportError as e:
111cdf0e10cSrcweir            raise RuntimeException( "Couldn't load "+url+ " for reason "+str(e), None)
112cdf0e10cSrcweir        return None
113cdf0e10cSrcweir
114cdf0e10cSrcweir    def activate( self, implementationName, dummy, locationUrl, regKey ):
115cdf0e10cSrcweir        if DEBUG:
116*d912c6c5SPedro Giffuni            print("pythonloader.Loader.activate")
117cdf0e10cSrcweir
118cdf0e10cSrcweir        mod = self.getModuleFromUrl( locationUrl )
119cdf0e10cSrcweir        implHelper = mod.__dict__.get( "g_ImplementationHelper" , None )
120cdf0e10cSrcweir        if implHelper == None:
121cdf0e10cSrcweir            return mod.getComponentFactory( implementationName, self.ctx.ServiceManager, regKey )
122cdf0e10cSrcweir        else:
123cdf0e10cSrcweir            return implHelper.getComponentFactory( implementationName,regKey,self.ctx.ServiceManager)
124cdf0e10cSrcweir
125cdf0e10cSrcweir    def writeRegistryInfo( self, regKey, dummy, locationUrl ):
126cdf0e10cSrcweir        if DEBUG:
127*d912c6c5SPedro Giffuni            print("pythonloader.Loader.writeRegistryInfo")
128cdf0e10cSrcweir
129cdf0e10cSrcweir        mod = self.getModuleFromUrl( locationUrl )
130cdf0e10cSrcweir        implHelper = mod.__dict__.get( "g_ImplementationHelper" , None )
131cdf0e10cSrcweir        if implHelper == None:
132cdf0e10cSrcweir            return mod.writeRegistryInfo( self.ctx.ServiceManager, regKey )
133cdf0e10cSrcweir        else:
134cdf0e10cSrcweir            return implHelper.writeRegistryInfo( regKey, self.ctx.ServiceManager )
135cdf0e10cSrcweir
136cdf0e10cSrcweir    def getImplementationName( self ):
137cdf0e10cSrcweir        return g_implementationName
138cdf0e10cSrcweir
139cdf0e10cSrcweir    def supportsService( self, ServiceName ):
140cdf0e10cSrcweir        return ServiceName in self.serviceNames
141cdf0e10cSrcweir
142cdf0e10cSrcweir    def getSupportedServiceNames( self ):
143cdf0e10cSrcweir        return g_supportedServices
144