private static CyPhyMetaLink.CyPhyMetaLinkAddon GetMetaLinkAddon(MgaProject project)
        {
            CyPhyMetaLink.CyPhyMetaLinkAddon cyPhyMLSyncComponent = null;
            MgaComponents mgaComponents = project.AddOnComponents;

            foreach (IMgaComponent iMgaComponent in mgaComponents)
            {
                if (iMgaComponent.ComponentName == "CyPhyMetaLinkAddon")
                {
                    cyPhyMLSyncComponent = (CyPhyMetaLink.CyPhyMetaLinkAddon)iMgaComponent;
                    break;
                }
            }
            return(cyPhyMLSyncComponent);
        }
Esempio n. 2
0
        protected void RunCyPhyMLSync(System.Action <MgaProject, CyPhyMetaLink.CyPhyMetaLinkAddon, CyPhyMetaLink.CyPhyMetalinkInterpreter> testAction)
        {
            try
            {
                if (debugMetalinkStartup)
                {
                    metalink.WaitForExit();
                    string stderr = metalink.StandardError.ReadToEnd();
                    string stdout = metalink.StandardOutput.ReadToEnd();
                }
                Exception      exception = null;
                AutoResetEvent workEvent = new AutoResetEvent(false);
                Thread         work      = new Thread(new ThreadStart(delegate
                {
                    try
                    {
                        // Import XME file to create an MGA
                        String xmeFullPath = Path.Combine(TestModelDir, testXMEFilename);
                        String mgaFullPath = TestModelDir + testInputFilename;
                        MgaUtils.ImportXME(xmeFullPath, mgaFullPath);
                        Assert.True(File.Exists(mgaFullPath), "MGA file not found. XME import may have failed.");

                        MgaProject project = new MgaProject();
                        project.EnableAutoAddOns(true);
                        project.OpenEx("MGA=" + mgaFullPath, "", true);
                        CyPhyMetaLink.CyPhyMetaLinkAddon propagate = null;
                        try
                        {
                            Assert.Contains("MGA.Addon.CyPhyMLPropagate", project.AddOnComponents.Cast <IMgaComponentEx>().Select(x => x.ComponentProgID));
                            propagate = (CyPhyMetaLink.CyPhyMetaLinkAddon)project.AddOnComponents.Cast <IMgaComponent>().Where(comp => comp is CyPhyMetaLink.CyPhyMetaLinkAddon).FirstOrDefault();
                            CyPhyMetaLink.CyPhyMetalinkInterpreter interpreter = new CyPhyMetaLink.CyPhyMetalinkInterpreter();
                            propagate.TestMode = true;
                            propagate.TestMode_NoAutomaticCreoStart = true;
                            propagate.TestMode_CreoJobObject        = JobObjectPinvoke.CreateKillOnCloseJob();
                            interpreter.GMEConsole = GME.CSharp.GMEConsole.CreateFromProject(project);
                            interpreter.MgaGateway = new MgaGateway(project);

                            var task = Task.Run(async() => await interpreter.ConnectToMetaLinkBridge(project, 128));
                            task.Wait();
                            propagate.bridgeClient.SocketQueue.EditMessageReceived += msg => addonMessagesQueue.Add(msg);
                            testAction(project, propagate, interpreter);
                        }
                        finally
                        {
                            if (propagate != null)
                            {
                                JobObjectPinvoke.CloseHandle(propagate.TestMode_CreoJobObject);
                                propagate.TestMode_CreoJobObject = IntPtr.Zero;
                            }
                            project.Save(project.ProjectConnStr + "_posttest.mga", true);
                            project.Close(true);
                        }
                    }
                    catch (Exception e)
                    {
                        exception = e;
                        KillMetaLink();
                    }
                    finally
                    {
                        workEvent.Set();
                    }
                }));
                work.SetApartmentState(ApartmentState.STA);
                work.Start();

                ManualResetEvent metalinkEvent = new ManualResetEvent(true);
                metalinkEvent.SafeWaitHandle = new SafeWaitHandle(metalink.Handle, false);

                int handle = WaitHandle.WaitAny(new WaitHandle[] { metalinkEvent, workEvent });
                if (exception != null)
                {
                    throw new Exception("Test failed", exception);
                }
                if (handle == 0)
                {
                    work.Abort();
                    throw new Exception("metalink exited");
                }
            }
            finally
            {
                KillMetaLink();
                lock (metalinkLogStream)
                    metalinkLogStream.Dispose();
            }
        }
        public bool ConnectToMetaLinkBridge(MgaProject project, int param)
        {
            bool connected = false;

            if (propagateAddon == null)
            {
                propagateAddon = GetPropagateAddon(project);
            }
            if (propagateAddon.EstablishConnection())
            {
                connected = true;
            }
            else
            {
                //GMEConsole.Error.WriteLine("Failed to establish connection to MetaLink Bridge.");
                if (param != 128)
                {
                    string metaLinkPath = Path.Combine(META.VersionInfo.MetaPath, @"src\MetaLink\meta-bridge\java-server\target\metalink-java-server-1.0.0.jar"); // dev machine
                    if (!File.Exists(metaLinkPath))
                    {
                        metaLinkPath = Path.Combine(META.VersionInfo.MetaPath, @"bin\metalink-java-server-1.0.0.jar"); // installed machine
                    }
                    if (File.Exists(metaLinkPath))
                    {
                        string java_path = GetJavaInstallationPath();
                        if (java_path == null)
                        {
                            throw new ApplicationException("Could not find java.exe. Is Java installed?");
                        }
                        string java_exe = Path.Combine(java_path, "bin\\java.exe");

                        //DialogResult res = MessageBox.Show("Could not connect to MetaLink.\n\nDo you want to start MetaLink?", "MetaLink", MessageBoxButtons.YesNo);
                        //if (res == DialogResult.Yes)
                        {
                            ProcessStartInfo startInfo = new ProcessStartInfo()
                            {
                                FileName = java_exe,
                                // Arguments = String.Format("-jar \"{0}\" -r \"{1}\"", metaLinkPath, Path.GetTempFileName()),
                                Arguments = String.Format("-jar \"{0}\"", metaLinkPath),
                                WindowStyle = ProcessWindowStyle.Minimized,
                                UseShellExecute = false,
                            };
#if DEBUG
                            // startInfo.Arguments += String.Format(" -r \"{0}\"", Path.Combine(Path.GetTempPath, "metalink_recordedmessages.mlp");
#endif
                            Process metalink = new Process();
                            metalink.StartInfo = startInfo;
                            metalink.Start();
#if DEBUG
                            metalink.BeginErrorReadLine();
                            metalink.BeginOutputReadLine();
#endif

                            for (int i = 0; i < 100; i++)
                            {
                                if (propagateAddon.EstablishConnection())
                                {
                                    connected = true;
                                    break;
                                }
                                Thread.Sleep(100);
                            }
                            int WM_SETICON = 0x80;
                            int ICON_SMALL = 0;
                            int ICON_BIG = 1;
                            Icon icon = Properties.Resources.CyPhyMLSync;
                            IntPtr result = SendMessage(metalink.MainWindowHandle, WM_SETICON, (IntPtr)ICON_SMALL, icon.Handle);
                            result = SendMessage(metalink.MainWindowHandle, WM_SETICON, (IntPtr)ICON_BIG, icon.Handle);
                            int WM_SYSCOMMAND = 0x0112;
                            var SC_MINIMIZE = (IntPtr)0xF020;
                            SendMessage(metalink.MainWindowHandle, WM_SYSCOMMAND, SC_MINIMIZE, IntPtr.Zero);
                            if (!connected)
                            {
                                GMEConsole.Error.WriteLine("Failed to start MetaLink Bridge.");
                                metalink.Dispose();
                            }
                            else
                            {
                                propagateAddon.metalinkBridge = metalink;
                            }
                        }
                    }
                    else
                    {
                        GMEConsole.Error.WriteLine("Meta-Link Bridge executable is missing. Please check that Meta-Link Bridge is installed.");
                    }
                }
            }
            if (connected)
            {
                GMEConsole.Info.WriteLine("Established connection to MetaLink Bridge.");
            }
            return connected;
        }
        public void InvokeEx(MgaProject project, MgaFCO currentobj, MgaFCOs selectedobjs, int param)
        {
            if (!enabled)
            {
                return;
            }

            try
            {
                GMEConsole = GMEConsole.CreateFromProject(project);
                MgaGateway = new MgaGateway(project);


                propagateAddon = GetPropagateAddon(project);
                if (propagateAddon == null)
                {
                    GMEConsole.Error.WriteLine("CyPhyMLSync: Unable to contact CyPhyMLPropagate.");
                    return;
                }
                if (propagateAddon.bridgeClient.IsConnectedToBridge() == false)
                {
                    ConnectToMetaLinkBridge(project, param);
                }

                string currentobjKind = null;
                MgaFCO selectedCADModel = null;
                string componentVersion = null;
                MgaGateway.PerformInTransaction(delegate
                {
                    if (currentobj != null)
                    {
                        currentobjKind = currentobj.Meta.Name;
                        if (currentobjKind == "CADModel")
                        {
                            selectedCADModel = currentobj;
                            currentobj = (MgaFCO)currentobj.ParentModel;
                            currentobjKind = currentobj.Meta.Name;
                        }
                        else
                        {
                            Func<MgaFCO, bool> isCADCreoModel = fco => fco.Meta.Name == "CADModel"
                                && CyPhyMLClasses.CADModel.Cast(fco).Attributes.FileFormat == CyPhyMLClasses.CADModel.AttributesClass.FileFormat_enum.Creo;
                            selectedCADModel = (selectedobjs ?? (System.Collections.IEnumerable)(new List<MgaFCO>())).Cast<MgaFCO>()
                                .FirstOrDefault(isCADCreoModel);
                            if (selectedCADModel == null && currentobj.ObjType == GME.MGA.Meta.objtype_enum.OBJTYPE_MODEL)
                            {
                                // TODO: show dialog instead of picking one at random
                                selectedCADModel = ((MgaModel)currentobj).ChildFCOs.Cast<MgaFCO>().FirstOrDefault(isCADCreoModel);
                            }
                        }
                        if (currentobj != null && currentobj.Meta.Name == typeof(CyPhyMLClasses.Component).Name)
                        {
                            componentVersion = CyPhyMLClasses.Component.Cast(currentobj).Attributes.Version;
                        }
                    }
                }, transactiontype_enum.TRANSACTION_GENERAL, abort: false);
                if (currentobjKind != null && currentobjKind != "Component" && currentobjKind != "CADModel" && currentobjKind != "ComponentAssembly")
                {
                    System.Windows.Forms.MessageBox.Show("Please open a Component or a Component Assembly");
                    return;
                }
                if (currentobjKind == "Component")
                {
                    CyPhyML.Component component = CyPhyMLClasses.Component.Cast(currentobj);
                    if (selectedCADModel == null)
                    {
                        GMEConsole.Error.WriteLine("This component has no CADModels to edit.");
                        return;
                    }
                    bool connected = true;
                    if (propagateAddon.bridgeClient.IsConnectedToBridge() == false)
                    {
                        connected = ConnectToMetaLinkBridge(project, param);
                    }
                    if (connected)
                    {
                        LinkComponent(component, selectedCADModel);
                    }
                    return;
                }

                if (currentobjKind == null)
                {
                    propagateAddon.StartCreoEmpyMode();
                    return;
                }

                //GMEConsole.Out.WriteLine("Running CyPhySync interpreter...");

                if (propagateAddon.AssemblyID != null)
                {
                    GMEConsole.Warning.WriteLine("A ComponentAssembly is already synced");
                }
                else
                {
                    bool connected = propagateAddon.bridgeClient.IsConnectedToBridge();
                    if (connected == false)
                    {
                        GMEConsole.Info.WriteLine("Connecting to MetaLink Bridge ...");

                        connected = ConnectToMetaLinkBridge(project, param);
                    }

                    if (connected)
                    {
                        StartAssemblySync(project, currentobj, param);
                    }
                }

                //GMEConsole.Out.WriteLine("End of CyPhySync interpreter...");
            }
            finally
            {
                MgaGateway = null;
                project = null;
                currentobj = null;
                selectedobjs = null;
                GMEConsole = null;
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
        }
        private async Task <bool> _ConnectToMetaLinkBridge(MgaProject project, int param)
        {
            bool connected = false;

            if (metalinkAddon == null)
            {
                metalinkAddon = GetMetaLinkAddon(project);
            }
            bool firstTimeConnect = metalinkAddon.bridgeClient.ConnectionWasRequested == false;

            if (await metalinkAddon.EstablishConnection())
            {
                connected = true;
            }
            else
            {
                //GMEConsole.Error.WriteLine("Failed to establish connection to MetaLink Bridge.");
                if (param != 128)
                {
                    string metaLinkPath = Path.Combine(META.VersionInfo.MetaPath, @"src\MetaLink\meta-bridge\java-server\target\metalink-java-server-1.1.0.jar"); // dev machine
                    if (!File.Exists(metaLinkPath))
                    {
                        metaLinkPath = Path.Combine(META.VersionInfo.MetaPath, @"bin\metalink-java-server-1.1.0.jar"); // installed machine
                    }
                    if (File.Exists(metaLinkPath))
                    {
                        string java_path = GetJavaInstallationPath();
                        if (java_path == null)
                        {
                            throw new ApplicationException("Could not find java.exe. Is Java installed?");
                        }
                        string java_exe = Path.Combine(java_path, "bin\\java.exe");

                        //DialogResult res = MessageBox.Show("Could not connect to MetaLink.\n\nDo you want to start MetaLink?", "MetaLink", MessageBoxButtons.YesNo);
                        //if (res == DialogResult.Yes)
                        {
                            ProcessStartInfo startInfo = new ProcessStartInfo()
                            {
                                FileName = java_exe,
                                // Arguments = String.Format("-jar \"{0}\" -r \"{1}\"", metaLinkPath, Path.GetTempFileName()),
                                Arguments              = String.Format("-jar \"{0}\"", metaLinkPath),
                                WindowStyle            = ProcessWindowStyle.Hidden,
                                CreateNoWindow         = true,
                                UseShellExecute        = false,
                                RedirectStandardError  = true,
                                RedirectStandardOutput = true,
                            };
#if DEBUG
                            // startInfo.Arguments += String.Format(" -r \"{0}\"", Path.Combine(Path.GetTempPath, "metalink_recordedmessages.mlp");
#endif
                            Process metalink = new Process();
                            metalink.StartInfo = startInfo;


                            string logPath = Path.Combine(ProjectDirectory, "log", "MetaLinkBridge_" + Process.GetCurrentProcess().Id.ToString() + ".log");
                            Directory.CreateDirectory(Path.GetDirectoryName(logPath));
                            var log           = new StreamWriter(logPath);
                            int streamsClosed = 0;
                            TaskCompletionSource <bool> bridgeListening = new TaskCompletionSource <bool>();

                            DataReceivedEventHandler handler = (sender, e) =>
                            {
                                lock (log)
                                {
                                    if (e.Data == null)
                                    {
                                        streamsClosed += 1;
                                        if (streamsClosed == 2)
                                        {
                                            log.Close();
                                            log.Dispose();
                                        }
                                        return;
                                    }
                                    if (bridgeListening.Task.IsCompleted == false && e.Data.Contains("AssemblyDesignBridgeServer started and listening"))
                                    {
                                        bridgeListening.SetResult(true);
                                    }
                                    log.WriteLine(e.Data);
                                    // log.Flush();
                                }
                            };
                            metalink.OutputDataReceived += handler;
                            metalink.ErrorDataReceived  += handler;

                            metalink.Start();
                            metalink.BeginErrorReadLine();
                            metalink.BeginOutputReadLine();

                            if (Task.WaitAny(new Task[] { bridgeListening.Task }, 20 * 1000) == -1)
                            {
                                // throw new TimeoutException();
                            }
                            // n.b. ensure that even if GME is killed or crashes, MetaLinkBridge will exit
                            // this is important because we are reading its output, and it may block when we are not around to read it
                            IntPtr job = JobObjectPinvoke.AssignProcessToKillOnCloseJob(metalink);

                            for (int i = 0; i < 100; i++)
                            {
                                if (await metalinkAddon.EstablishConnection())
                                {
                                    connected = true;
                                    break;
                                }
                                await Task.Delay(100);
                            }
                            if (!connected)
                            {
                                if (GMEConsole != null)
                                {
                                    GMEConsole.Error.WriteLine("Failed to start MetaLink Bridge.");
                                }
                                if (metalink.HasExited)
                                {
                                    metalink.Kill();
                                }
                                metalink.Dispose();
                                JobObjectPinvoke.CloseHandle(job);
                            }
                            else
                            {
                                metalinkAddon._metalinkBridge    = metalink;
                                metalinkAddon._metalinkBridgeJob = job;
                            }
                        }
                    }
                    else
                    {
                        if (GMEConsole != null)
                        {
                            GMEConsole.Error.WriteLine("Meta-Link Bridge executable is missing. Please check that Meta-Link Bridge is installed.");
                        }
                    }
                }
            }
            if (connected && firstTimeConnect)
            {
                if (GMEConsole != null)
                {
                    GMEConsole.Info.WriteLine("Established connection to MetaLink Bridge.");
                }
            }
            return(connected);
        }
        public void InvokeEx(MgaProject project, MgaFCO currentobj, MgaFCOs selectedobjs, int param)
        {
            if (!enabled)
            {
                return;
            }

            try
            {
                GMEConsole       = GMEConsole.CreateFromProject(project);
                MgaGateway       = new MgaGateway(project);
                ProjectDirectory = Path.GetDirectoryName(project.ProjectConnStr.Substring("MGA=".Length));


                metalinkAddon = GetMetaLinkAddon(project);
                if (metalinkAddon == null)
                {
                    GMEConsole.Error.WriteLine("MetaLink: Unable to find CyPhyMetaLinkAddon. Was it disabled under Tools>Register Components?");
                    return;
                }
                ConnectToMetaLinkBridge(project, param);

                string currentobjKind   = null;
                string currentobjName   = null;
                MgaFCO selectedCADModel = null;
                string componentVersion = null;
                Guid   currentobjGuid   = Guid.Empty;
                if (currentobj != null)
                {
                    MgaGateway.PerformInTransaction(delegate
                    {
                        currentobjKind = currentobj.Meta.Name;
                        currentobjName = currentobj.Name;
                        currentobjGuid = CyPhyMLClasses.DesignElement.Cast(currentobj).Guid;
                        if (currentobjKind == "CADModel")
                        {
                            selectedCADModel = currentobj;
                            currentobj       = (MgaFCO)currentobj.ParentModel;
                            currentobjKind   = currentobj.Meta.Name;
                            currentobjName   = currentobj.Name;
                            currentobjGuid   = CyPhyMLClasses.DesignElement.Cast(currentobj).Guid;
                        }
                        else
                        {
                            Func <MgaFCO, bool> isCADCreoModel = fco => fco.Meta.Name == "CADModel" &&
                                                                 CyPhyMLClasses.CADModel.Cast(fco).Attributes.FileFormat == CyPhyMLClasses.CADModel.AttributesClass.FileFormat_enum.Creo;
                            selectedCADModel = (selectedobjs ?? (System.Collections.IEnumerable)(new List <MgaFCO>())).Cast <MgaFCO>()
                                               .FirstOrDefault(isCADCreoModel);
                            if (selectedCADModel == null && currentobj.ObjType == GME.MGA.Meta.objtype_enum.OBJTYPE_MODEL)
                            {
                                // TODO: show dialog instead of picking one at random
                                selectedCADModel = ((MgaModel)currentobj).ChildFCOs.Cast <MgaFCO>().FirstOrDefault(isCADCreoModel);
                            }
                        }
                        if (currentobj != null && currentobj.Meta.Name == typeof(CyPhyMLClasses.Component).Name)
                        {
                            componentVersion = CyPhyMLClasses.Component.Cast(currentobj).Attributes.Version;
                        }
                    }, transactiontype_enum.TRANSACTION_NON_NESTED, abort: false);
                }
                if (currentobjKind != null && currentobjKind != "Component" && currentobjKind != "CADModel" && currentobjKind != "ComponentAssembly")
                {
                    System.Windows.Forms.MessageBox.Show("Please open a Component or a Component Assembly");
                    return;
                }
                if (currentobjKind == "Component")
                {
                    CyPhyML.Component component = CyPhyMLClasses.Component.Cast(currentobj);
                    if (selectedCADModel == null)
                    {
                        GMEConsole.Error.WriteLine("This component has no CADModels to edit.");
                        return;
                    }
                    bool connected = true;
                    ConnectToMetaLinkBridgeTask.Wait();
                    connected = ConnectToMetaLinkBridgeTask.Result;
                    if (connected)
                    {
                        LinkComponent(component, selectedCADModel);
                    }
                    return;
                }

                if (currentobjKind == null)
                {
                    bool connected = true;
                    ConnectToMetaLinkBridgeTask.Wait();
                    connected = ConnectToMetaLinkBridgeTask.Result;
                    if (connected)
                    {
                        metalinkAddon.StartCreoEmpyMode();
                    }
                    return;
                }

                //GMEConsole.Out.WriteLine("Running CyPhySync interpreter...");

                if (metalinkAddon.AssemblyID != null)
                {
                    if (currentobjGuid == Guid.Parse(metalinkAddon.AssemblyID))
                    {
                        metalinkAddon.assemblySyncPaused = !metalinkAddon.assemblySyncPaused;
                        if (metalinkAddon.assemblySyncPaused)
                        {
                            GMEConsole.Info.WriteLine(String.Format("Pausing MetaLink for {0}", SecurityElement.Escape(currentobjName)));
                        }
                        else
                        {
                            GMEConsole.Info.WriteLine(String.Format("Resuming MetaLink for {0}", SecurityElement.Escape(currentobjName)));
                            if (metalinkAddon.assembliesToRestart.Count > 0)
                            {
                                MgaGateway.PerformInTransaction(delegate
                                {
                                    // n.b. end of current transaction will trigger MetaLinkAddon RestartAssemblySync
                                });
                            }
                        }
                    }
                    else
                    {
                        GMEConsole.Warning.WriteLine("A different ComponentAssembly is already synced");
                    }
                }
                else
                {
                    StartAssemblySync(project, currentobj, param);
                }

                //GMEConsole.Out.WriteLine("End of CyPhySync interpreter...");
            }
            catch (AggregateException e)
            {
                foreach (var exception in e.InnerExceptions)
                {
                    GMEConsole.Error.WriteLine(exception.Message);
                }
                throw new ApplicationException(e.InnerException.Message, e.InnerException);
            }
            finally
            {
                MgaGateway   = null;
                project      = null;
                currentobj   = null;
                selectedobjs = null;
                GMEConsole   = null;
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
        }