00001
00002
00003 from __future__ import with_statement
00004
00005 import re
00006 import sys
00007 import os.path
00008 import win32com.client
00009 import StringIO
00010 import platform
00011 import runpy
00012 import subprocess
00013 import itertools
00014
00015 from GPyUnit.util import DispatchEx
00016
00017
00018 if platform.system() != 'Java':
00019
00020
00021 import win32com.client.gencache
00022 _savedGetClassForCLSID = win32com.client.gencache.GetClassForCLSID
00023 win32com.client.gencache.GetClassForCLSID = lambda x: None
00024
00025
00026 def execute_elevated(*args):
00027
00028 from win32com.shell.shell import ShellExecuteEx
00029 from win32com.shell import shellcon
00030 import win32process, win32event
00031 import winxpgui
00032 import win32api
00033 import win32con
00034 try:
00035 hwnd = winxpgui.GetConsoleWindow()
00036 except winxpgui.error:
00037 hwnd = 0
00038 parameters = ""
00039 if not hasattr(sys, "frozen"):
00040
00041 parameters += "\"" + sys.argv[0] + "\" "
00042 parameters += " ".join(map(lambda x: "\"" + str(x) + "\"", args))
00043 print "Executing elevated with parameters " + parameters
00044
00045 rc = ShellExecuteEx(hwnd=hwnd, fMask=shellcon.SEE_MASK_NOCLOSEPROCESS, lpVerb="runas", lpFile=sys.executable,
00046 lpParameters=parameters, nShow=win32con.SW_SHOW)
00047 hproc = rc['hProcess']
00048 win32event.WaitForSingleObject(hproc, win32event.INFINITE)
00049 exit_code = win32process.GetExitCodeProcess(hproc)
00050 if exit_code:
00051 raise Exception("Error: subprocess failed (exit code %s)." % exit_code)
00052
00053 def is_elevated():
00054 import win32security
00055 import win32api
00056 hToken = win32security.OpenProcessToken(win32api.GetCurrentProcess(), win32security.TOKEN_QUERY)
00057 return win32security.GetTokenInformation(hToken, win32security.TokenElevation) != 0
00058
00059
00060 def maybe_elevate():
00061 def decorator(func):
00062 if not hasattr(sys, "getwindowsversion") or sys.getwindowsversion()[0] < 6:
00063 wrap = func
00064 else:
00065 def wrap(*args, **kwargs):
00066 if not is_elevated():
00067 execute_elevated(func.__name__, *args, **kwargs)
00068 else:
00069 func(*args, **kwargs)
00070 setattr(sys.modules[__name__], func.__name__, wrap)
00071 return wrap
00072 return decorator
00073
00074 @maybe_elevate()
00075 def elevated_check_call(*args):
00076 return subprocess.check_call(args)
00077
00078
00079 def create_project(project, connection, paradigm):
00080 return project.Create(connection, paradigm)
00081
00082
00083 def xme2mga(xmefile, mgafile=None):
00084 if not mgafile:
00085 mgafile = os.path.splitext(xmefile)[0] + ".mga"
00086 with Project.open(xmefile, mgafile) as project:
00087 project.save(project.mgafile)
00088 return project.mgafile
00089
00090 def run_interpreter(interpreter, file, focusobj=None, selectedobj=None, param=None, mga_to_save=None, save=True):
00091 if param is None:
00092 param = 128
00093 with Project.open(file, mga_to_save=mga_to_save) as project:
00094 project.run_interpreter(interpreter, focusobj, selectedobj, param)
00095 if not save:
00096 project.project.Close(True)
00097
00098 def run_interpreter_with_focusobj(interpreter, file, focusobj=None, selectedobj=None, param=None, mga_to_save=None, save=True):
00099 if param is None:
00100 param = 128
00101 with Project.open(file, mga_to_save=mga_to_save) as project:
00102 if focusobj:
00103 focusobj = project.project.GetFCOByID(focusobj)
00104 project.run_interpreter(interpreter, focusobj, selectedobj, param)
00105 if not save:
00106 project.project.Close(True)
00107
00108
00109 def get_paradigm_file(paradigm, regaccess=3):
00110 "Returns the .mta file for a given registered paradigm"
00111 registrar = DispatchEx("Mga.MgaRegistrar")
00112 guid = registrar.GetParadigmGUIDStringDisp(regaccess, paradigm)
00113 import uuid
00114 if platform.system() != 'Java':
00115 buf = buffer(uuid.UUID(guid).bytes_le, 0, 16)
00116 else:
00117 buf = str(uuid.UUID(guid).bytes_le[0:16])
00118 (connstr, guid) = registrar.QueryParadigm(paradigm, None, buf, regaccess)
00119
00120
00121 return connstr[4:]
00122
00123
00124 def _associate(progid, paradigm, regaccess):
00125 registrar = DispatchEx("Mga.MgaRegistrar")
00126 registrar.Associate(progid, paradigm, regaccess)
00127
00128 @maybe_elevate()
00129 def _associate_elevated(*args):
00130 _associate(*args)
00131
00132 def associate(progid, paradigm, regaccess=1):
00133 "Associate a component with a paradigm"
00134 regaccess = int(regaccess)
00135 if regaccess != 1:
00136 _associate_elevated(progid, paradigm, regaccess)
00137 else:
00138 _associate(progid, paradigm, regaccess)
00139
00140
00141 def is_registered(paradigm):
00142 registrar = DispatchEx("Mga.MgaRegistrar")
00143 paradigms = []
00144
00145 paradigms.extend(registrar.GetParadigmsDisp(1))
00146
00147 paradigms.extend(registrar.GetParadigmsDisp(2))
00148 return filter(lambda p: p == paradigm, paradigms)
00149
00150 REGISTER = 128
00151 DONT_REGISTER = 0
00152 def register_if_not_registered(file):
00153 "Register an xme or mga if it has not already been registered"
00154 if os.path.splitext(file)[1] == ".xmp":
00155 if not is_registered(os.path.basename(os.path.splitext(file)[0])) or (platform.system() != 'Java' and not os.path.isfile(get_paradigm_file(os.path.splitext(os.path.basename(file))[0]))):
00156 regxmp(file)
00157 return
00158
00159
00160 with Project.open(os.path.abspath(file), mga_to_save=True) as project:
00161
00162
00163 paradigm = project.project.RootFolder.Name
00164 if not is_registered(paradigm):
00165 project.run_interpreter("MGA.Interpreter.MetaInterpreter", param=REGISTER)
00166 print "Paradigm '%s' is now registered" % paradigm
00167 elif not os.path.isfile(get_paradigm_file(paradigm)):
00168
00169 project.run_interpreter("MGA.Interpreter.MetaInterpreter", param=REGISTER)
00170 print "Paradigm '%s' had nonexistant .mta; it is now reregistered" % paradigm
00171
00172
00173 else:
00174 print "Paradigm '%s' is already registered" % paradigm
00175
00176 def mga2xmp(mgafile, register=REGISTER):
00177
00178 run_interpreter("MGA.Interpreter.MetaInterpreter", os.path.abspath(mgafile), param=register, mga_to_save=True, save=False)
00179
00180 def xme2xmp(xmefile, register=REGISTER):
00181 mgafile = xme2mga(xmefile)
00182 mga2xmp(mgafile, register)
00183 return mgafile
00184
00185 def regmta(mtafile, regaccess=1):
00186 regaccess = int(regaccess)
00187 if regaccess != 1:
00188 _regxmp_elevated(mtafile, regaccess)
00189 else:
00190 _regxmp(mtafile, regaccess)
00191
00192 def _regxmp(xmpfile, regaccess):
00193 REG_USER = 1
00194 REG_SYSTEM = 2
00195 REG_BOTH = 3
00196 registrar = DispatchEx("Mga.MgaRegistrar")
00197 if os.path.splitext(xmpfile)[1].lower() == ".xmp":
00198 registrar.RegisterParadigmFromData("XML=" + os.path.abspath(xmpfile), "", regaccess)
00199 else:
00200 registrar.RegisterParadigmFromData("MGA=" + os.path.abspath(xmpfile), "", regaccess)
00201
00202 @maybe_elevate()
00203 def _regxmp_elevated(xmpfile, regaccess):
00204 _regxmp(xmpfile, regaccess)
00205
00206 def regxmp(xmpfile, regaccess=1):
00207 regaccess = int(regaccess)
00208 if regaccess != 1:
00209 _regxmp_elevated(xmpfile, regaccess)
00210 else:
00211 _regxmp(xmpfile, regaccess)
00212
00213 def _reggmexmps(regaccess):
00214 regaccess = int(regaccess)
00215 for file in [ 'HFSM/HFSM.xmp', 'MetaGME/MetaGME.xmp', 'SF/SF.xmp', 'UML/UML.xmp' ]:
00216 regxmp(os.path.join(os.path.join(os.environ['GME_ROOT'], 'Paradigms'), file), regaccess)
00217
00218 @maybe_elevate()
00219 def _reggmexmps_elevated(regaccess):
00220 _reggmexmps(regaccess)
00221
00222 def reggmexmps(regaccess=1):
00223 regaccess = int(regaccess)
00224 if regaccess != 1:
00225 _reggmexmps_elevated(regaccess)
00226 else:
00227 _reggmexmps(regaccess)
00228
00229 def mga2xme(mgafile, xmefile=None):
00230 if not xmefile:
00231 xmefile = os.path.splitext(mgafile)[0] + ".xme"
00232
00233 with Project.open(mgafile) as project:
00234 project.save(xmefile)
00235 return xmefile
00236
00237 def register_component(file, warn_on_tlb_error=None):
00238 '''Register a GME component .dll'''
00239
00240 registrar = DispatchEx("Mga.MgaRegistrar")
00241
00242 registrar.RegisterComponentLibrary(file, 3)
00243
00244
00245
00246 def meta2uml(mgafile, umlfile=None):
00247 if not os.path.isfile(mgafile):
00248 raise Exception("'" + mgafile + "' not found")
00249
00250
00251 with Project.open(mgafile) as project:
00252 project.run_interpreter("MGA.Interpreter.MetaGME2Uml", None, None, 128)
00253 output_path = os.path.join(os.path.dirname(mgafile), project.project.RootFolder.Name + "_uml.mga")
00254
00255 project.project.Close(True)
00256 if umlfile and os.path.normcase(os.path.abspath(umlfile)) != os.path.normcase(os.path.abspath(output_path)):
00257 import shutil
00258 try:
00259 os.remove(umlfile)
00260 except OSError:
00261 pass
00262 shutil.move(output_path, umlfile)
00263
00264
00265
00266 def mga2udmxml(mgafile):
00267 run_interpreter("MGA.Interpreter.UML2XML", mgafile, param=128, save=False)
00268
00269
00270 def RunGreatMasterInt(file):
00271 file = os.path.abspath(file)
00272 mtime = os.stat(file).st_mtime
00273
00274 run_interpreter("MGA.Interpreter.GReAT Master Interpreter", file, param=128, save=True)
00275
00276 os.utime(file, (mtime, mtime))
00277
00278
00279 def context_menu_reg():
00280 """Register explorer context menu options"""
00281 import _winreg
00282 if hasattr(sys, "frozen"):
00283
00284 gmepydir = os.path.dirname(unicode(sys.executable, sys.getfilesystemencoding( )))
00285 else:
00286 gmepydir = os.path.dirname(__file__)
00287
00288 gmepy = gmepydir + "\\gmepy.exe"
00289
00290 mga = "mga"
00291 xme = "xme"
00292 xmp = "xmp"
00293 menus = [ (mga, "mga2xme"),
00294 (mga, "mga2xmp"),
00295 (mga, "mga2udmxml"),
00296 (xme, "xme2mga"),
00297 (xmp, "regxmp"),
00298 ]
00299 regname = gmepydir + "\\gmepy_context_menu.reg"
00300 with open(regname, "w") as reg:
00301 reg.write("Windows Registry Editor Version 5.00\n")
00302 for p in menus:
00303 try:
00304 key = _winreg.OpenKey(_winreg.ConnectRegistry(None, _winreg.HKEY_CLASSES_ROOT), "."+p[0])
00305 n,v,t = _winreg.EnumValue(key, 0)
00306 ext = v
00307 _winreg.CloseKey(key)
00308 except WindowsError:
00309 ext = "."+p[0]
00310 str = """[HKEY_CLASSES_ROOT\{ext}\shell]
00311
00312 [HKEY_CLASSES_ROOT\{ext}\shell\{name}]
00313
00314 [HKEY_CLASSES_ROOT\{ext}\shell\{name}\command]
00315 @="\\"{gmepy}\\" {name} \\\"%1\\\""
00316
00317 """.format(ext=ext, name=p[1], gmepy=gmepy.replace("\\", "\\\\"))
00318 reg.write(str)
00319 elevated_check_call("regedit", regname)
00320
00321 OBJTYPE_MODEL = 1
00322 OBJTYPE_ATOM = 2
00323 OBJTYPE_REFERENCE = 3
00324 OBJTYPE_CONNECTION = 4
00325 OBJTYPE_SET = 5
00326 OBJTYPE_FOLDER = 6
00327 def is_container(fco):
00328 return fco.ObjType == OBJTYPE_MODEL or fco.ObjType == OBJTYPE_FOLDER
00329
00330 import tempfile
00331 class Project():
00332 def __init__(self, com_project):
00333 self.project = com_project
00334
00335 def __enter__(self):
00336 self.begin_transaction()
00337 return self
00338
00339 def __exit__(self, exc_type, exc_value, traceback):
00340 if self.project.ProjectStatus == 3 or self.project.ProjectStatus == 4:
00341 if exc_type:
00342 self.project.AbortTransaction()
00343 else:
00344 self.project.CommitTransaction()
00345 if self.territory:
00346 self.territory.Destroy()
00347 self.territory = None
00348 if self.project.ProjectStatus != 0:
00349 self.project.Close()
00350
00351 def get_fco(self, path):
00352 path_a = path.split("/")
00353 current = self.project.RootFolder
00354 for name in path_a[0:-1]:
00355 containers = list(filter(is_container, current.ChildFCOs))
00356 if current.ObjType == OBJTYPE_FOLDER:
00357 containers += list(filter(is_container, current.ChildFolders))
00358 matches = filter(lambda x: x.Name == name, containers)
00359 if matches:
00360 current = matches[0]
00361 else:
00362 raise Exception("Cant find %s in path %s" % (name, path))
00363 matches = array(filter(lambda x: x.Name == path_a[-1], current.ChildFCOs))
00364 if current.ObjType == OBJTYPE_FOLDER:
00365 matches += array(filter(lambda x: x.Name == path_a[-1], current.ChildFolders))
00366 if matches:
00367 return matches[0]
00368 else:
00369 raise Exception("Cant find %s in path %s" % (path_a[-1], path))
00370
00371 def save(self, filename=None):
00372 if not filename:
00373 filename = self.file
00374 self.project.CommitTransaction()
00375 if self.territory:
00376 self.territory.Destroy()
00377 self.territory = None
00378
00379 extension = os.path.splitext(filename)[1]
00380 if extension == ".mga":
00381 self.project.Save("MGA=" + filename)
00382 elif extension == ".xme":
00383 dumper = DispatchEx("Mga.MgaDumper")
00384 dumper.DumpProject(self.project, filename)
00385 else:
00386 raise Exception("Don't know how to save '%s'" % filename)
00387 self.territory = self.project.BeginTransactionInNewTerr()
00388
00389 def begin_transaction(self):
00390 self.territory = self.project.BeginTransactionInNewTerr()
00391
00392 def commit_transaction(self):
00393 self.project.CommitTransaction()
00394 if self.territory:
00395 self.territory.Destroy()
00396 self.territory = None
00397
00398 def abort_transaction(self):
00399 self.project.AbortTransaction()
00400 if self.territory:
00401 self.territory.Destroy()
00402 self.territory = None
00403
00404 def run_interpreter(self, interpreter, focusobj=None, selectedobj=None, param=0):
00405 if not selectedobj:
00406 selectedobj=DispatchEx("Mga.MgaFCOs")
00407 self.commit_transaction()
00408 try:
00409 launcher = DispatchEx("Mga.MgaLauncher")
00410 launcher.RunComponent(interpreter, self.project, focusobj, selectedobj, param)
00411 finally:
00412 self.begin_transaction()
00413
00414 @staticmethod
00415 def create(mgafile, paradigm):
00416 project = DispatchEx("Mga.MgaProject")
00417 create_project(project, "MGA=" + mgafile, paradigm)
00418 p = Project(project)
00419 p.filename = mgafile
00420 p.mgafile = mgafile
00421 return p
00422
00423 @staticmethod
00424 def open(file, mga_to_save=None):
00425 if not os.path.isfile(file):
00426 raise Exception("'" + file + "' not found")
00427 extension = os.path.splitext(file)[1]
00428 mga = None
00429 if extension == ".mga":
00430 mga = DispatchEx("Mga.MgaProject")
00431 mga.Open("MGA=" + file)
00432 mga_to_save = file
00433 elif extension == ".xme":
00434 xme = DispatchEx("Mga.MgaParser")
00435 (paradigm, parversion, parguid, basename, ver) = xme.GetXMLInfo(file)
00436
00437 mga = DispatchEx("Mga.MgaProject")
00438 xme = DispatchEx("Mga.MgaParser")
00439 if mga_to_save == True:
00440 mga_to_save = os.path.splitext(file)[0] + ".mga"
00441 elif not mga_to_save:
00442 mga_to_save = tempfile.gettempdir() + "gmepy-%s.mga" % os.getpid()
00443 create_project(mga, "MGA=" + mga_to_save, paradigm)
00444 xme.ParseProject(mga, file)
00445 else:
00446 raise Exception("Don't know how to open '%s'" % file)
00447 p = Project(mga)
00448 p.filename = file
00449 p.mgafile = mga_to_save
00450 return p
00451
00452
00453 def print_paradigm(xmefile):
00454 "Print the input file and paradigm of a given xme"
00455 xme = DispatchEx("Mga.MgaParser")
00456 (paradigm, parversion, parguid, basename, ver) = xme.GetXMLInfo(xmefile)
00457 print xmefile
00458 print paradigm
00459
00460 def run_module(name):
00461 sys.path.append('.')
00462 runpy.run_module(name)
00463
00464 def usage():
00465 gme_dict = sys.modules[__name__].__dict__
00466 names = []
00467 names.extend(gme_dict.keys())
00468 for name in filter(lambda name: type(gme_dict[name]) == type(print_paradigm), names):
00469 if gme_dict[name].__doc__:
00470 print name
00471 print "\t" + gme_dict[name].__doc__
00472 sys.exit(2)
00473
00474 import traceback
00475 if __name__ == '__main__':
00476 try:
00477 if len(sys.argv) < 2 or sys.argv[1] not in dir():
00478 usage()
00479 else:
00480
00481
00482 eval("%s(*sys.argv[2:])" % sys.argv[1])
00483 except:
00484 traceback.print_exc(file=sys.stderr)
00485 sys.stdin.readline()
00486 sys.exit(1)