1*cdf0e10cSrcweir#*************************************************************************
2*cdf0e10cSrcweir#
3*cdf0e10cSrcweir# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir#
5*cdf0e10cSrcweir# Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir#
7*cdf0e10cSrcweir# OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir#
9*cdf0e10cSrcweir# This file is part of OpenOffice.org.
10*cdf0e10cSrcweir#
11*cdf0e10cSrcweir# OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir# it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir# only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir#
15*cdf0e10cSrcweir# OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir# but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir# GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir# (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir#
21*cdf0e10cSrcweir# You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir# version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir# <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir# for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir#
26*cdf0e10cSrcweir#*************************************************************************
27*cdf0e10cSrcweirimport uno
28*cdf0e10cSrcweirimport unohelper
29*cdf0e10cSrcweirimport sys
30*cdf0e10cSrcweirimport imp
31*cdf0e10cSrcweirimport os
32*cdf0e10cSrcweirfrom com.sun.star.uno import Exception,RuntimeException
33*cdf0e10cSrcweirfrom com.sun.star.loader import XImplementationLoader
34*cdf0e10cSrcweirfrom com.sun.star.lang import XServiceInfo
35*cdf0e10cSrcweir
36*cdf0e10cSrcweirMODULE_PROTOCOL = "vnd.openoffice.pymodule:"
37*cdf0e10cSrcweirDEBUG = 0
38*cdf0e10cSrcweir
39*cdf0e10cSrcweirg_supportedServices  = "com.sun.star.loader.Python",      # referenced by the native C++ loader !
40*cdf0e10cSrcweirg_implementationName = "org.openoffice.comp.pyuno.Loader" # referenced by the native C++ loader !
41*cdf0e10cSrcweir
42*cdf0e10cSrcweirdef splitUrl( url ):
43*cdf0e10cSrcweir      nColon = url.find( ":" )
44*cdf0e10cSrcweir      if -1 == nColon:
45*cdf0e10cSrcweir            raise RuntimeException( "PythonLoader: No protocol in url " + url, None )
46*cdf0e10cSrcweir      return url[0:nColon], url[nColon+1:len(url)]
47*cdf0e10cSrcweir
48*cdf0e10cSrcweirg_loadedComponents = {}
49*cdf0e10cSrcweirdef checkForPythonPathBesideComponent( url ):
50*cdf0e10cSrcweir      path = unohelper.fileUrlToSystemPath( url+"/pythonpath.zip" );
51*cdf0e10cSrcweir      if DEBUG == 1:
52*cdf0e10cSrcweir            print "checking for existence of " + encfile( path )
53*cdf0e10cSrcweir      if 1 == os.access( encfile( path ), os.F_OK) and not path in sys.path:
54*cdf0e10cSrcweir            if DEBUG == 1:
55*cdf0e10cSrcweir                  print "adding " + encfile( path ) + " to sys.path"
56*cdf0e10cSrcweir            sys.path.append( path )
57*cdf0e10cSrcweir
58*cdf0e10cSrcweir      path = unohelper.fileUrlToSystemPath( url+"/pythonpath" );
59*cdf0e10cSrcweir      if 1 == os.access( encfile( path ), os.F_OK) and not path in sys.path:
60*cdf0e10cSrcweir            if DEBUG == 1:
61*cdf0e10cSrcweir                  print "adding " + encfile( path ) + " to sys.path"
62*cdf0e10cSrcweir            sys.path.append( path )
63*cdf0e10cSrcweir
64*cdf0e10cSrcweirdef encfile(uni):
65*cdf0e10cSrcweir    return uni.encode( sys.getfilesystemencoding())
66*cdf0e10cSrcweir
67*cdf0e10cSrcweirclass Loader( XImplementationLoader, XServiceInfo, unohelper.Base ):
68*cdf0e10cSrcweir      def __init__(self, ctx ):
69*cdf0e10cSrcweir	  if DEBUG:
70*cdf0e10cSrcweir	     print "pythonloader.Loader ctor"
71*cdf0e10cSrcweir	  self.ctx = ctx
72*cdf0e10cSrcweir
73*cdf0e10cSrcweir      def getModuleFromUrl( self, url ):
74*cdf0e10cSrcweir          if DEBUG:
75*cdf0e10cSrcweir                print "pythonloader: interpreting url " +url
76*cdf0e10cSrcweir          protocol, dependent = splitUrl( url )
77*cdf0e10cSrcweir          if "vnd.sun.star.expand" == protocol:
78*cdf0e10cSrcweir                exp = self.ctx.getValueByName( "/singletons/com.sun.star.util.theMacroExpander" )
79*cdf0e10cSrcweir                url = exp.expandMacros(dependent)
80*cdf0e10cSrcweir                protocol,dependent = splitUrl( url )
81*cdf0e10cSrcweir
82*cdf0e10cSrcweir          if DEBUG:
83*cdf0e10cSrcweir                print "pythonloader: after expansion " +protocol +":" + dependent
84*cdf0e10cSrcweir
85*cdf0e10cSrcweir          try:
86*cdf0e10cSrcweir                if "file" == protocol:
87*cdf0e10cSrcweir                      # remove \..\ sequence, which may be useful e.g. in the build env
88*cdf0e10cSrcweir                      url = unohelper.absolutize( url, url )
89*cdf0e10cSrcweir
90*cdf0e10cSrcweir                      # did we load the module already ?
91*cdf0e10cSrcweir                      mod = g_loadedComponents.get( url )
92*cdf0e10cSrcweir                      if not mod:
93*cdf0e10cSrcweir                            mod = imp.new_module("uno_component")
94*cdf0e10cSrcweir
95*cdf0e10cSrcweir                            # check for pythonpath.zip beside .py files
96*cdf0e10cSrcweir                            checkForPythonPathBesideComponent( url[0:url.rfind('/')] )
97*cdf0e10cSrcweir
98*cdf0e10cSrcweir                            # read the file
99*cdf0e10cSrcweir                            filename = unohelper.fileUrlToSystemPath( url )
100*cdf0e10cSrcweir                            fileHandle = file( filename )
101*cdf0e10cSrcweir                            src = fileHandle.read().replace("\r","")
102*cdf0e10cSrcweir                            if not src.endswith( "\n" ):
103*cdf0e10cSrcweir                                  src = src + "\n"
104*cdf0e10cSrcweir
105*cdf0e10cSrcweir                            # compile and execute the module
106*cdf0e10cSrcweir                            codeobject = compile( src, encfile(filename), "exec" )
107*cdf0e10cSrcweir                            exec codeobject in mod.__dict__
108*cdf0e10cSrcweir                            mod.__file__ = encfile(filename)
109*cdf0e10cSrcweir                            g_loadedComponents[url] = mod
110*cdf0e10cSrcweir                      return mod
111*cdf0e10cSrcweir                elif "vnd.openoffice.pymodule" == protocol:
112*cdf0e10cSrcweir                      return  __import__( dependent )
113*cdf0e10cSrcweir                else:
114*cdf0e10cSrcweir                      raise RuntimeException( "PythonLoader: Unknown protocol " +
115*cdf0e10cSrcweir                                              protocol + " in url " +url, self )
116*cdf0e10cSrcweir          except ImportError, e:
117*cdf0e10cSrcweir                raise RuntimeException( "Couldn't load "+url+ " for reason "+str(e), None)
118*cdf0e10cSrcweir          return None
119*cdf0e10cSrcweir
120*cdf0e10cSrcweir      def activate( self, implementationName, dummy, locationUrl, regKey ):
121*cdf0e10cSrcweir	  if DEBUG:
122*cdf0e10cSrcweir	     print "pythonloader.Loader.activate"
123*cdf0e10cSrcweir
124*cdf0e10cSrcweir	  mod = self.getModuleFromUrl( locationUrl )
125*cdf0e10cSrcweir          implHelper = mod.__dict__.get( "g_ImplementationHelper" , None )
126*cdf0e10cSrcweir          if implHelper == None:
127*cdf0e10cSrcweir		return mod.getComponentFactory( implementationName, self.ctx.ServiceManager, regKey )
128*cdf0e10cSrcweir          else:
129*cdf0e10cSrcweir		return implHelper.getComponentFactory( implementationName,regKey,self.ctx.ServiceManager)
130*cdf0e10cSrcweir
131*cdf0e10cSrcweir      def writeRegistryInfo( self, regKey, dummy, locationUrl ):
132*cdf0e10cSrcweir	  if DEBUG:
133*cdf0e10cSrcweir	     print "pythonloader.Loader.writeRegistryInfo"
134*cdf0e10cSrcweir
135*cdf0e10cSrcweir	  mod = self.getModuleFromUrl( locationUrl )
136*cdf0e10cSrcweir          implHelper = mod.__dict__.get( "g_ImplementationHelper" , None )
137*cdf0e10cSrcweir          if implHelper == None:
138*cdf0e10cSrcweir	        return mod.writeRegistryInfo( self.ctx.ServiceManager, regKey )
139*cdf0e10cSrcweir          else:
140*cdf0e10cSrcweir	        return implHelper.writeRegistryInfo( regKey, self.ctx.ServiceManager )
141*cdf0e10cSrcweir
142*cdf0e10cSrcweir      def getImplementationName( self ):
143*cdf0e10cSrcweir	  return g_implementationName
144*cdf0e10cSrcweir
145*cdf0e10cSrcweir      def supportsService( self, ServiceName ):
146*cdf0e10cSrcweir	  return ServiceName in self.serviceNames
147*cdf0e10cSrcweir
148*cdf0e10cSrcweir      def getSupportedServiceNames( self ):
149*cdf0e10cSrcweir	  return g_supportedServices
150*cdf0e10cSrcweir
151*cdf0e10cSrcweir
152