1a0428e9eSAndrew Rist#**************************************************************
2a0428e9eSAndrew Rist#
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
10a0428e9eSAndrew Rist#
11a0428e9eSAndrew Rist#    http://www.apache.org/licenses/LICENSE-2.0
12a0428e9eSAndrew Rist#
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.
19a0428e9eSAndrew Rist#
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 ):
37*d912c6c5SPedro Giffuni    nColon = url.find( ":" )
38*d912c6c5SPedro Giffuni    if -1 == nColon:
39*d912c6c5SPedro Giffuni        raise RuntimeException( "PythonLoader: No protocol in url " + url, None )
40*d912c6c5SPedro Giffuni    return url[0:nColon], url[nColon+1:len(url)]
41cdf0e10cSrcweir
42cdf0e10cSrcweirg_loadedComponents = {}
43cdf0e10cSrcweirdef checkForPythonPathBesideComponent( url ):
44*d912c6c5SPedro Giffuni    path = unohelper.fileUrlToSystemPath( url+"/pythonpath.zip" );
45*d912c6c5SPedro Giffuni    if DEBUG == 1:
46*d912c6c5SPedro Giffuni        print("checking for existence of " + encfile( path ))
47*d912c6c5SPedro Giffuni    if 1 == os.access( encfile( path ), os.F_OK) and not path in sys.path:
48*d912c6c5SPedro Giffuni        if DEBUG == 1:
49*d912c6c5SPedro Giffuni            print("adding " + encfile( path ) + " to sys.path")
50*d912c6c5SPedro Giffuni        sys.path.append( path )
51*d912c6c5SPedro Giffuni
52*d912c6c5SPedro Giffuni    path = unohelper.fileUrlToSystemPath( url+"/pythonpath" );
53*d912c6c5SPedro Giffuni    if 1 == os.access( encfile( path ), os.F_OK) and not path in sys.path:
54*d912c6c5SPedro Giffuni        if DEBUG == 1:
55*d912c6c5SPedro Giffuni            print("adding " + encfile( path ) + " to sys.path")
56*d912c6c5SPedro Giffuni        sys.path.append( path )
57cdf0e10cSrcweir
58cdf0e10cSrcweirdef encfile(uni):
59cdf0e10cSrcweir    return uni.encode( sys.getfilesystemencoding())
60cdf0e10cSrcweir
61cdf0e10cSrcweirclass Loader( XImplementationLoader, XServiceInfo, unohelper.Base ):
62*d912c6c5SPedro Giffuni    def __init__(self, ctx ):
63*d912c6c5SPedro Giffuni        if DEBUG:
64*d912c6c5SPedro Giffuni            print("pythonloader.Loader ctor")
65*d912c6c5SPedro Giffuni        self.ctx = ctx
66*d912c6c5SPedro Giffuni
67*d912c6c5SPedro Giffuni    def getModuleFromUrl( self, url ):
68*d912c6c5SPedro Giffuni        if DEBUG:
69*d912c6c5SPedro Giffuni            print("pythonloader: interpreting url " +url)
70*d912c6c5SPedro Giffuni        protocol, dependent = splitUrl( url )
71*d912c6c5SPedro Giffuni        if "vnd.sun.star.expand" == protocol:
72*d912c6c5SPedro Giffuni            exp = self.ctx.getValueByName( "/singletons/com.sun.star.util.theMacroExpander" )
73*d912c6c5SPedro Giffuni            url = exp.expandMacros(dependent)
74*d912c6c5SPedro Giffuni            protocol,dependent = splitUrl( url )
75*d912c6c5SPedro Giffuni
76*d912c6c5SPedro Giffuni        if DEBUG:
77*d912c6c5SPedro Giffuni            print("pythonloader: after expansion " +protocol +":" + dependent)
78*d912c6c5SPedro Giffuni
79*d912c6c5SPedro Giffuni        try:
80*d912c6c5SPedro Giffuni            if "file" == protocol:
81*d912c6c5SPedro Giffuni                # remove \..\ sequence, which may be useful e.g. in the build env
82*d912c6c5SPedro Giffuni                url = unohelper.absolutize( url, url )
83*d912c6c5SPedro Giffuni
84*d912c6c5SPedro Giffuni                # did we load the module already ?
85*d912c6c5SPedro Giffuni                mod = g_loadedComponents.get( url )
86*d912c6c5SPedro Giffuni                if not mod:
87*d912c6c5SPedro Giffuni                    mod = imp.new_module("uno_component")
88*d912c6c5SPedro Giffuni
89*d912c6c5SPedro Giffuni                    # check for pythonpath.zip beside .py files
90*d912c6c5SPedro Giffuni                    checkForPythonPathBesideComponent( url[0:url.rfind('/')] )
91*d912c6c5SPedro Giffuni
92*d912c6c5SPedro Giffuni                    # read the file
93*d912c6c5SPedro Giffuni                    filename = unohelper.fileUrlToSystemPath( url )
94*d912c6c5SPedro Giffuni                    fileHandle = file( filename )
95*d912c6c5SPedro Giffuni                    src = fileHandle.read().replace("\r","")
96*d912c6c5SPedro Giffuni                    if not src.endswith( "\n" ):
97*d912c6c5SPedro Giffuni                        src = src + "\n"
98*d912c6c5SPedro Giffuni
99*d912c6c5SPedro Giffuni                    # compile and execute the module
100*d912c6c5SPedro Giffuni                    codeobject = compile( src, encfile(filename), "exec" )
101*d912c6c5SPedro Giffuni                    exec(codeobject, mod.__dict__)
102*d912c6c5SPedro Giffuni                    mod.__file__ = encfile(filename)
103*d912c6c5SPedro Giffuni                    g_loadedComponents[url] = mod
104*d912c6c5SPedro Giffuni                return mod
105*d912c6c5SPedro Giffuni            elif "vnd.openoffice.pymodule" == protocol:
106*d912c6c5SPedro Giffuni                return  __import__( dependent )
107*d912c6c5SPedro Giffuni            else:
108*d912c6c5SPedro Giffuni                raise RuntimeException( "PythonLoader: Unknown protocol " +
109*d912c6c5SPedro Giffuni                                        protocol + " in url " +url, self )
110*d912c6c5SPedro Giffuni        except ImportError as e:
111*d912c6c5SPedro Giffuni            raise RuntimeException( "Couldn't load "+url+ " for reason "+str(e), None)
112*d912c6c5SPedro Giffuni        return None
113*d912c6c5SPedro Giffuni
114*d912c6c5SPedro Giffuni    def activate( self, implementationName, dummy, locationUrl, regKey ):
115*d912c6c5SPedro Giffuni        if DEBUG:
116*d912c6c5SPedro Giffuni            print("pythonloader.Loader.activate")
117*d912c6c5SPedro Giffuni
118*d912c6c5SPedro Giffuni        mod = self.getModuleFromUrl( locationUrl )
119*d912c6c5SPedro Giffuni        implHelper = mod.__dict__.get( "g_ImplementationHelper" , None )
120*d912c6c5SPedro Giffuni        if implHelper == None:
121*d912c6c5SPedro Giffuni            return mod.getComponentFactory( implementationName, self.ctx.ServiceManager, regKey )
122*d912c6c5SPedro Giffuni        else:
123*d912c6c5SPedro Giffuni            return implHelper.getComponentFactory( implementationName,regKey,self.ctx.ServiceManager)
124*d912c6c5SPedro Giffuni
125*d912c6c5SPedro Giffuni    def writeRegistryInfo( self, regKey, dummy, locationUrl ):
126*d912c6c5SPedro Giffuni        if DEBUG:
127*d912c6c5SPedro Giffuni            print("pythonloader.Loader.writeRegistryInfo")
128*d912c6c5SPedro Giffuni
129*d912c6c5SPedro Giffuni        mod = self.getModuleFromUrl( locationUrl )
130*d912c6c5SPedro Giffuni        implHelper = mod.__dict__.get( "g_ImplementationHelper" , None )
131*d912c6c5SPedro Giffuni        if implHelper == None:
132*d912c6c5SPedro Giffuni            return mod.writeRegistryInfo( self.ctx.ServiceManager, regKey )
133*d912c6c5SPedro Giffuni        else:
134*d912c6c5SPedro Giffuni            return implHelper.writeRegistryInfo( regKey, self.ctx.ServiceManager )
135*d912c6c5SPedro Giffuni
136*d912c6c5SPedro Giffuni    def getImplementationName( self ):
137*d912c6c5SPedro Giffuni        return g_implementationName
138*d912c6c5SPedro Giffuni
139*d912c6c5SPedro Giffuni    def supportsService( self, ServiceName ):
140*d912c6c5SPedro Giffuni        return ServiceName in self.serviceNames
141*d912c6c5SPedro Giffuni
142*d912c6c5SPedro Giffuni    def getSupportedServiceNames( self ):
143*d912c6c5SPedro Giffuni        return g_supportedServices
144