1 # -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3 # This file is part of the LibreOffice project.
5 # This Source Code Form is subject to the terms of the Mozilla Public
6 # License, v. 2.0. If a copy of the MPL was not distributed with this
7 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 # This file incorporates work covered by the following license notice:
11 # Licensed to the Apache Software Foundation (ASF) under one or more
12 # contributor license agreements. See the NOTICE file distributed
13 # with this work for additional information regarding copyright
14 # ownership. The ASF licenses this file to you under the Apache
15 # License, Version 2.0 (the "License"); you may not use this file
16 # except in compliance with the License. You may obtain a copy of
17 # the License at http://www.apache.org/licenses/LICENSE-2.0 .
24 from com
.sun
.star
.uno
import Exception,RuntimeException
25 from com
.sun
.star
.loader
import XImplementationLoader
26 from com
.sun
.star
.lang
import XServiceInfo
28 MODULE_PROTOCOL
= "vnd.openoffice.pymodule:"
31 g_supportedServices
= "com.sun.star.loader.Python", # referenced by the native C++ loader !
32 g_implementationName
= "org.openoffice.comp.pyuno.Loader" # referenced by the native C++ loader !
35 nColon
= url
.find( ":" )
37 raise RuntimeException( "PythonLoader: No protocol in url " + url
, None )
38 return url
[0:nColon
], url
[nColon
+1:len(url
)]
40 g_loadedComponents
= {}
41 def checkForPythonPathBesideComponent( url
):
42 path
= unohelper
.fileUrlToSystemPath( url
+"/pythonpath.zip" );
44 print(b
"checking for existence of " + encfile( path
))
45 if 1 == os
.access( encfile( path
), os
.F_OK
) and not path
in sys
.path
:
47 print(b
"adding " + encfile( path
) + b
" to sys.path")
48 sys
.path
.append( path
)
50 path
= unohelper
.fileUrlToSystemPath( url
+"/pythonpath" );
51 if 1 == os
.access( encfile( path
), os
.F_OK
) and not path
in sys
.path
:
53 print(b
"adding " + encfile( path
) + b
" to sys.path")
54 sys
.path
.append( path
)
57 return uni
.encode( sys
.getfilesystemencoding())
59 class Loader( XImplementationLoader
, XServiceInfo
, unohelper
.Base
):
60 def __init__(self
, ctx
):
62 print("pythonloader.Loader ctor")
65 def getModuleFromUrl( self
, url
):
67 print("pythonloader: interpreting url " + url
)
68 protocol
, dependent
= splitUrl( url
)
69 if "vnd.sun.star.expand" == protocol
:
70 exp
= self
.ctx
.getValueByName( "/singletons/com.sun.star.util.theMacroExpander" )
71 url
= exp
.expandMacros(dependent
)
72 protocol
,dependent
= splitUrl( url
)
75 print("pythonloader: after expansion " + protocol
+ ":" + dependent
)
78 if "file" == protocol
:
79 # remove \..\ sequence, which may be useful e.g. in the build env
80 url
= unohelper
.absolutize( url
, url
)
82 # did we load the module already ?
83 mod
= g_loadedComponents
.get( url
)
85 mod
= imp
.new_module("uno_component")
87 # check for pythonpath.zip beside .py files
88 checkForPythonPathBesideComponent( url
[0:url
.rfind('/')] )
91 filename
= unohelper
.fileUrlToSystemPath( url
)
93 if sys
.version
>= '3':
94 fileHandle
= open( filename
, encoding
='utf_8' )
96 fileHandle
= open( filename
)
97 src
= fileHandle
.read().replace("\r","")
98 if not src
.endswith( "\n" ):
101 # compile and execute the module
102 codeobject
= compile( src
, encfile(filename
), "exec" )
103 exec(codeobject
, mod
.__dict
__)
104 mod
.__file
__ = encfile(filename
)
105 g_loadedComponents
[url
] = mod
107 elif "vnd.openoffice.pymodule" == protocol
:
108 nSlash
= dependent
.rfind('/')
110 path
= unohelper
.fileUrlToSystemPath( dependent
[0:nSlash
] )
111 dependent
= dependent
[nSlash
+1:len(dependent
)]
112 if not path
in sys
.path
:
113 sys
.path
.append( path
)
114 mod
= __import__( dependent
)
115 path_component
, dot
, rest
= dependent
.partition('.')
117 path_component
, dot
, rest
= rest
.partition('.')
118 mod
= getattr(mod
, path_component
)
122 print("Unknown protocol '" + protocol
+ "'");
123 raise RuntimeException( "PythonLoader: Unknown protocol " +
124 protocol
+ " in url " +url
, self
)
125 except Exception as e
:
127 print ("Python import exception " + str(type(e
)) +
128 " message " + str(e
) + " args " + str(e
.args
));
129 raise RuntimeException( "Couldn't load " + url
+ " for reason " + str(e
), None )
132 def activate( self
, implementationName
, dummy
, locationUrl
, regKey
):
134 print("pythonloader.Loader.activate")
136 mod
= self
.getModuleFromUrl( locationUrl
)
137 implHelper
= mod
.__dict
__.get( "g_ImplementationHelper" , None )
139 print ("Fetched ImplHelper as " + str(implHelper
))
140 if implHelper
is None:
141 return mod
.getComponentFactory( implementationName
, self
.ctx
.ServiceManager
, regKey
)
143 return implHelper
.getComponentFactory( implementationName
,regKey
,self
.ctx
.ServiceManager
)
145 def writeRegistryInfo( self
, regKey
, dummy
, locationUrl
):
147 print( "pythonloader.Loader.writeRegistryInfo" )
149 mod
= self
.getModuleFromUrl( locationUrl
)
150 implHelper
= mod
.__dict
__.get( "g_ImplementationHelper" , None )
151 if implHelper
is None:
152 return mod
.writeRegistryInfo( self
.ctx
.ServiceManager
, regKey
)
154 return implHelper
.writeRegistryInfo( regKey
, self
.ctx
.ServiceManager
)
156 def getImplementationName( self
):
157 return g_implementationName
159 def supportsService( self
, ServiceName
):
160 return ServiceName
in self
.serviceNames
162 def getSupportedServiceNames( self
):
163 return g_supportedServices
165 # vim:set shiftwidth=4 softtabstop=4 expandtab: