1*a0428e9eSAndrew Rist#**************************************************************
2*a0428e9eSAndrew Rist#
3*a0428e9eSAndrew Rist#  Licensed to the Apache Software Foundation (ASF) under one
4*a0428e9eSAndrew Rist#  or more contributor license agreements.  See the NOTICE file
5*a0428e9eSAndrew Rist#  distributed with this work for additional information
6*a0428e9eSAndrew Rist#  regarding copyright ownership.  The ASF licenses this file
7*a0428e9eSAndrew Rist#  to you under the Apache License, Version 2.0 (the
8*a0428e9eSAndrew Rist#  "License"); you may not use this file except in compliance
9*a0428e9eSAndrew Rist#  with the License.  You may obtain a copy of the License at
10*a0428e9eSAndrew Rist#
11*a0428e9eSAndrew Rist#    http://www.apache.org/licenses/LICENSE-2.0
12*a0428e9eSAndrew Rist#
13*a0428e9eSAndrew Rist#  Unless required by applicable law or agreed to in writing,
14*a0428e9eSAndrew Rist#  software distributed under the License is distributed on an
15*a0428e9eSAndrew Rist#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*a0428e9eSAndrew Rist#  KIND, either express or implied.  See the License for the
17*a0428e9eSAndrew Rist#  specific language governing permissions and limitations
18*a0428e9eSAndrew Rist#  under the License.
19*a0428e9eSAndrew Rist#
20*a0428e9eSAndrew 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:
46cdf0e10cSrcweir            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:
49cdf0e10cSrcweir                  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:
55cdf0e10cSrcweir                  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:
64cdf0e10cSrcweir	     print "pythonloader.Loader ctor"
65cdf0e10cSrcweir	  self.ctx = ctx
66cdf0e10cSrcweir
67cdf0e10cSrcweir      def getModuleFromUrl( self, url ):
68cdf0e10cSrcweir          if DEBUG:
69cdf0e10cSrcweir                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:
77cdf0e10cSrcweir                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" )
101cdf0e10cSrcweir                            exec codeobject in 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 )
110cdf0e10cSrcweir          except ImportError, 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:
116cdf0e10cSrcweir	     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:
127cdf0e10cSrcweir	     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
144cdf0e10cSrcweir
145cdf0e10cSrcweir
146