public ServiceStatusWaiter(string taskDescription, IAutoResetEvent autoResetEvent, ITimerFactory timerFactory, ServiceStatusProvider serviceStatusProvider, string serviceName) : base(taskDescription, autoResetEvent, timerFactory) { _serviceStatusProvider = serviceStatusProvider; _serviceName = serviceName; }
public void Before_each_test() { //ServicesRepository servicesRepository = new ServicesRepository(new ScutexEntities()); //CommonRepository commonRepository = new CommonRepository(new ScutexServiceEntities()); AsymmetricEncryptionProvider asymmetricEncryptionProvider = new AsymmetricEncryptionProvider(); SymmetricEncryptionProvider symmetricEncryptionProvider = new SymmetricEncryptionProvider(); ObjectSerializationProvider objectSerializationProvider = new ObjectSerializationProvider(); NumberDataGenerator numberDataGenerator = new NumberDataGenerator(); PackingService packingService = new PackingService(numberDataGenerator); MasterService masterService = new MasterService(commonRepository); CommonService commonService = new CommonService(); KeyPairService keyPairService = new KeyPairService(commonService, commonRepository); ServiceStatusProvider serviceStatusProvider = new ServiceStatusProvider(symmetricEncryptionProvider, objectSerializationProvider, asymmetricEncryptionProvider); servicesService = new ServicesService(servicesRepository, serviceStatusProvider, packingService, null, null, null, null, null, null); controlService = new ControlService(symmetricEncryptionProvider, keyPairService, packingService, masterService, objectSerializationProvider, asymmetricEncryptionProvider); service = new Scutex.Model.Service(); service.OutboundKeyPair = asymmetricEncryptionProvider.GenerateKeyPair(BitStrengths.High); service.InboundKeyPair = asymmetricEncryptionProvider.GenerateKeyPair(BitStrengths.High); service.ManagementInboundKeyPair = asymmetricEncryptionProvider.GenerateKeyPair(BitStrengths.High); service.ManagementOutboundKeyPair = asymmetricEncryptionProvider.GenerateKeyPair(BitStrengths.High); }
public void Before_each_test() { //ServicesRepository servicesRepository = new ServicesRepository(new ScutexEntities()); //CommonRepository commonRepository = new CommonRepository(new ScutexServiceEntities()); AsymmetricEncryptionProvider asymmetricEncryptionProvider = new AsymmetricEncryptionProvider(); SymmetricEncryptionProvider symmetricEncryptionProvider = new SymmetricEncryptionProvider(); ObjectSerializationProvider objectSerializationProvider = new ObjectSerializationProvider(); NumberDataGenerator numberDataGenerator = new NumberDataGenerator(); PackingService packingService = new PackingService(numberDataGenerator); MasterService masterService = new MasterService(commonRepository); CommonService commonService = new CommonService(); KeyPairService keyPairService = new KeyPairService(commonService, commonRepository); ServiceStatusProvider serviceStatusProvider = new ServiceStatusProvider(symmetricEncryptionProvider, objectSerializationProvider, asymmetricEncryptionProvider); servicesService = new ServicesService(servicesRepository, serviceStatusProvider, packingService, null, null, null, null, null, null); controlService = new ControlService(symmetricEncryptionProvider, keyPairService, packingService, masterService, objectSerializationProvider, asymmetricEncryptionProvider); service = new Scutex.Model.Service(); service.OutboundKeyPair = asymmetricEncryptionProvider.GenerateKeyPair(BitStrengths.High); service.InboundKeyPair = asymmetricEncryptionProvider.GenerateKeyPair(BitStrengths.High); service.ManagementInboundKeyPair = asymmetricEncryptionProvider.GenerateKeyPair(BitStrengths.High); service.ManagementOutboundKeyPair = asymmetricEncryptionProvider.GenerateKeyPair(BitStrengths.High); }
public void Destroy() { lock (this) { if (_runtimeEnvironment != null) { Log.Info("Destroying runtime URI '" + URI + "'"); // first invoke listeners foreach (var listener in _serviceListeners) { try { listener.OnEPRuntimeDestroyRequested(this); } catch (Exception ex) { Log.Error("Runtime exception caught during an onEPRuntimeDestroyRequested callback:" + ex.Message, ex); } } if (_configLastProvided.Runtime.MetricsReporting.IsRuntimeMetrics) { DestroyEngineMetrics(_runtimeEnvironment.Services.RuntimeURI); } ServiceStatusProvider?.Set(false); _runtimeEnvironment.StageService.Destroy(); // assign null value var runtimeToDestroy = _runtimeEnvironment; runtimeToDestroy.Services.TimerService.StopInternalClock(false); // plugin-loaders - destroy in opposite order var pluginLoaders = runtimeToDestroy.Services.ConfigSnapshot.Runtime.PluginLoaders; if (!pluginLoaders.IsEmpty()) { var reversed = new List<ConfigurationRuntimePluginLoader>(pluginLoaders); reversed.Reverse(); foreach (var config in reversed) { PluginLoader plugin; try { plugin = (PluginLoader) runtimeToDestroy.Services.RuntimeEnvContext.Lookup("plugin-loader/" + config.LoaderName); plugin.Dispose(); } catch (Exception e) { Log.Error("Error destroying plug-in loader: " + config.LoaderName, e); } } } runtimeToDestroy.Services.ThreadingService.Dispose(); // assign null - making EPRuntime and EPAdministrator unobtainable _runtimeEnvironment = null; runtimeToDestroy.StageService.Clear(); runtimeToDestroy.Runtime.Destroy(); runtimeToDestroy.DeploymentService.Destroy(); runtimeToDestroy.Services.Destroy(); _runtimes.Remove(URI); runtimeToDestroy.Services.Initialize(); } } }
public WhenGettingServiceStatus() { _handler = new Codenizer.HttpClient.Testable.TestableMessageHandler(); var httpClient = new HttpClient(_handler); _provider = new ServiceStatusProvider(httpClient); }
public LicenseHelper() { asymmetricEncryptionProvider = new AsymmetricEncryptionProvider(); hashingProvider = new HashingProvider(); encodingService = new EncodingService(); objectSerializationProvider = new ObjectSerializationProvider(); symmetricEncryptionProvider = new SymmetricEncryptionProvider(); clientLicenseRepository = new ClientLicenseRepository(objectSerializationProvider, symmetricEncryptionProvider); clientLicenseService = new ClientLicenseService(clientLicenseRepository); serviceStatusProvider = new ServiceStatusProvider(symmetricEncryptionProvider, objectSerializationProvider, asymmetricEncryptionProvider); numberDataGenerator = new NumberDataGenerator(); packingService = new PackingService(numberDataGenerator); hardwareFingerprintService = new HardwareFingerprintService(new WmiDataProvider(), new HashingProvider()); keygen = new KeyGenerator(symmetricEncryptionProvider, asymmetricEncryptionProvider, hashingProvider); keyGeneratorLarge = new Scutex.Generators.StaticKeyGeneratorLarge.KeyGenerator(symmetricEncryptionProvider, asymmetricEncryptionProvider, hashingProvider, hardwareFingerprintService); licenseActiviationProvider = new LicenseActiviationProvider(asymmetricEncryptionProvider, symmetricEncryptionProvider, objectSerializationProvider); service = new LicenseKeyService(keygen, keyGeneratorLarge, packingService, clientLicenseService); productsProvider = new ProductsProvider(symmetricEncryptionProvider, objectSerializationProvider, asymmetricEncryptionProvider); zipCompressionProvider = new ZipCompressionProvider(); wcfPackagingService = new WcfPackagingService(zipCompressionProvider); //licenseSetsRepository = new LicenseSetsRepository(); //licenseSetService = new LicenseSetService(); //licenseService = new LicenseService(); License = new License(); License.Name = "UnitTest License"; License.UniqueId = Guid.NewGuid(); License.KeyPair = asymmetricEncryptionProvider.GenerateKeyPair(BitStrengths.High); //string path = System.Reflection.Assembly.GetAssembly(typeof(LicenseHelper)).Location; string path = Helper.AssemblyDirectory; DllHash = encodingService.Encode(hashingProvider.HashFile(path + "\\WaveTech.Scutex.Licensing.dll")); PublicKey = encodingService.Encode(License.KeyPair.PublicKey); }
protected override Result RunCore(Argument[] args) { var descriptions = ServiceStatusProvider.DescribeWindowsStatuses(); var waitForDescription = descriptions[_waitFor]; var fullPath = _fileSystem.FindInstallationDirectoryInPathContaining(ServiceStatusProvider .ServiceControllerExecutable, @"C:\windows\System32"); Presenter.ShowMessage($"Executing command to {_command} the service {_serviceName}", Logger); _processExecutor.ExecuteAndWaitForExit( Path.Combine(fullPath, ServiceStatusProvider.ServiceControllerExecutable), $"{_command} {_serviceName}", LogInformation, LogError); Presenter.ShowMessage($"Waiting for {_serviceName} to be {waitForDescription}", Logger); var status = _serviceStatusWaiter.WaitFor(_waitFor); var statusDescription = descriptions[status]; Presenter.ShowMessage($"Service {_serviceName} status is now {statusDescription}", Logger); return(status == _waitFor ? Result.Successful() : Result.Failure( $"Expecting {_command} command to put the service in '{waitForDescription}' status but instead it is in '{statusDescription}' status.")); }
public void Before_each_test() { clientLicenseRepoistory = new ClientLicenseRepository(objectSerializationProvider, symmetricEncryptionProvider); clientLicenseService = new ClientLicenseService(clientLicenseRepoistory); serviceProductsRepository = new ServiceProductsRepository(new ScutexServiceEntities()); symmetricEncryptionProvider = new SymmetricEncryptionProvider(); asymmetricEncryptionProvider = new AsymmetricEncryptionProvider(); hashingProvider = new HashingProvider(); objectSerializationProvider = new ObjectSerializationProvider(); numberDataGenerator = new NumberDataGenerator(); packingService = new PackingService(numberDataGenerator); commonRepository = new CommonRepository(new ScutexServiceEntities()); clientRepository = new ClientRepository(new ScutexServiceEntities()); keyGenerator = new KeyGenerator(symmetricEncryptionProvider, asymmetricEncryptionProvider, hashingProvider); masterService = new MasterService(commonRepository); hardwareFingerprintService = new HardwareFingerprintService(new WmiDataProvider(), new HashingProvider()); keyGeneratorLarge = new Scutex.Generators.StaticKeyGeneratorLarge.KeyGenerator(symmetricEncryptionProvider, asymmetricEncryptionProvider, hashingProvider, hardwareFingerprintService); var mockActivationLogRepository = new Mock <IActivationLogRepoistory>(); mockActivationLogRepository.Setup(log => log.SaveActivationLog(It.IsAny <Scutex.Model.ActivationLog>())); activationLogService = new ActivationLogService(mockActivationLogRepository.Object, hashingProvider); commonService = new CommonService(); string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase); path = path.Replace("file:\\", ""); var mockCommonService = new Mock <ICommonService>(); mockCommonService.Setup(common => common.GetPath()).Returns(path + "\\Data\\Client\\"); string masterServiceDataText; using (TextReader reader = new StreamReader(path + "\\Data\\MasterService.dat")) { masterServiceDataText = reader.ReadToEnd().Trim(); } masterServiceData = objectSerializationProvider.Deserialize <MasterServiceData>(masterServiceDataText); var mockCommonRepository = new Mock <ICommonRepository>(); mockCommonRepository.Setup(repo => repo.GetMasterServiceData()).Returns(masterServiceData); masterService = new MasterService(mockCommonRepository.Object); keyPairService = new KeyPairService(mockCommonService.Object, mockCommonRepository.Object); controlService = new ControlService(symmetricEncryptionProvider, keyPairService, packingService, masterService, objectSerializationProvider, asymmetricEncryptionProvider); servicesRepository = new ServicesRepository(new ScutexEntities()); serviceStatusProvider = new ServiceStatusProvider(symmetricEncryptionProvider, objectSerializationProvider, asymmetricEncryptionProvider); licenseActiviationProvider = new LicenseActiviationProvider(asymmetricEncryptionProvider, symmetricEncryptionProvider, objectSerializationProvider); servicesService = new ServicesService(servicesRepository, serviceStatusProvider, packingService, licenseActiviationProvider, null, null, null, null, null); licenseKeyService = new LicenseKeyService(keyGenerator, keyGeneratorLarge, packingService, clientLicenseService); keyService = new KeyManagementService(clientRepository, licenseKeyService, activationLogService, hashingProvider, serviceProductsRepository); activationService = new ActivationService(controlService, keyService, keyPairService, objectSerializationProvider, asymmetricEncryptionProvider, activationLogService, masterService, commonService, null); string serviceData; using (TextReader reader = new StreamReader(path + "\\Data\\Service.dat")) { serviceData = reader.ReadToEnd().Trim(); } service = objectSerializationProvider.Deserialize <Service>(serviceData); }
public void Before_each_test() { clientLicenseRepoistory = new ClientLicenseRepository(objectSerializationProvider, symmetricEncryptionProvider); clientLicenseService = new ClientLicenseService(clientLicenseRepoistory); serviceProductsRepository = new ServiceProductsRepository(new ScutexServiceEntities()); symmetricEncryptionProvider = new SymmetricEncryptionProvider(); asymmetricEncryptionProvider = new AsymmetricEncryptionProvider(); hashingProvider = new HashingProvider(); objectSerializationProvider = new ObjectSerializationProvider(); numberDataGenerator = new NumberDataGenerator(); packingService = new PackingService(numberDataGenerator); commonRepository = new CommonRepository(new ScutexServiceEntities()); clientRepository = new ClientRepository(new ScutexServiceEntities()); keyGenerator = new KeyGenerator(symmetricEncryptionProvider, asymmetricEncryptionProvider, hashingProvider); masterService = new MasterService(commonRepository); activationLogRepository = new ActivationLogRepoistory(new ScutexServiceEntities()); activationLogService = new ActivationLogService(activationLogRepository, hashingProvider); keyService = new KeyManagementService(clientRepository, licenseKeyService, activationLogService, hashingProvider, serviceProductsRepository); commonService = new CommonService(); string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase); path = path.Replace("file:\\", ""); var mockCommonService = new Mock<ICommonService>(); mockCommonService.Setup(common => common.GetPath()).Returns(path + "\\Data\\Client\\"); string masterServiceDataText; using (TextReader reader = new StreamReader(path + "\\Data\\MasterService.dat")) { masterServiceDataText = reader.ReadToEnd().Trim(); } masterServiceData = objectSerializationProvider.Deserialize<MasterServiceData>(masterServiceDataText); var mockCommonRepository = new Mock<ICommonRepository>(); mockCommonRepository.Setup(repo => repo.GetMasterServiceData()).Returns(masterServiceData); keyPairService = new KeyPairService(mockCommonService.Object, mockCommonRepository.Object); controlService = new ControlService(symmetricEncryptionProvider, keyPairService, packingService, masterService, objectSerializationProvider, asymmetricEncryptionProvider); servicesRepository = new ServicesRepository(new ScutexEntities()); serviceStatusProvider = new ServiceStatusProvider(symmetricEncryptionProvider, objectSerializationProvider, asymmetricEncryptionProvider); licenseActiviationProvider = new LicenseActiviationProvider(asymmetricEncryptionProvider, symmetricEncryptionProvider, objectSerializationProvider); servicesService = new ServicesService(servicesRepository, serviceStatusProvider, packingService, licenseActiviationProvider, null, null, null, null, null); licenseKeyService = new LicenseKeyService(keyGenerator, packingService, clientLicenseService); activationService = new ActivationService(controlService, keyService, keyPairService, objectSerializationProvider, asymmetricEncryptionProvider, null, null); string serviceData; using (TextReader reader = new StreamReader(path + "\\Data\\Service.dat")) { serviceData = reader.ReadToEnd().Trim(); } service = objectSerializationProvider.Deserialize<Service>(serviceData); }
private ServiceSession() { serviceStatusProvider = new ServiceStatusProvider(); data = new ServiceStatusData(); unsubscriber = serviceStatusProvider.Subscribe(this); }
/// <summary> /// Performs the initialization. /// </summary> /// <param name="startTime">optional start time</param> protected void DoInitialize(long? startTime) { Log.Info("Initializing runtime URI '" + URI + "' version " + RuntimeVersion.RUNTIME_VERSION); // Retain config-at-initialization since config-last-provided can be set to new values and "initialize" can be called _configAtInitialization = _configLastProvided; // Verify settings if (_configLastProvided.Runtime.Threading.IsInternalTimerEnabled && _configLastProvided.Common.TimeSource.TimeUnit != TimeUnit.MILLISECONDS) { throw new ConfigurationException("Internal timer requires millisecond time resolution"); } // This setting applies to all runtimes in a given VM ExecutionPathDebugLog.IsDebugEnabled = _configLastProvided.Runtime.Logging.IsEnableExecutionDebug; ExecutionPathDebugLog.IsTimerDebugEnabled = _configLastProvided.Runtime.Logging.IsEnableTimerDebug; // This setting applies to all runtimes in a given VM AuditPath.AuditPattern = _configLastProvided.Runtime.Logging.AuditPattern; if (_runtimeEnvironment != null) { if (ServiceStatusProvider != null) { ServiceStatusProvider.Set(false); } _runtimeEnvironment.Services.TimerService.StopInternalClock(false); if (_configLastProvided.Runtime.MetricsReporting.IsRuntimeMetrics) { DestroyEngineMetrics(_runtimeEnvironment.Services.RuntimeURI); } _runtimeEnvironment.Runtime.Initialize(); _runtimeEnvironment.Services.Destroy(); } ServiceStatusProvider = new AtomicBoolean(true); // Make EP services context factory var epServicesContextFactoryClassName = _configLastProvided.Runtime.EPServicesContextFactoryClassName; EPServicesContextFactory epServicesContextFactory; if (epServicesContextFactoryClassName == null) { // Check system properties epServicesContextFactoryClassName = Environment.GetEnvironmentVariable("ESPER_EPSERVICE_CONTEXT_FACTORY_CLASS"); } if (epServicesContextFactoryClassName == null) { epServicesContextFactory = new EPServicesContextFactoryDefault(Container); } else { Type clazz; try { clazz = TransientConfigurationResolver.ResolveClassForNameProvider(_configLastProvided.Common.TransientConfiguration) .ClassForName(epServicesContextFactoryClassName); } catch (TypeLoadException) { throw new ConfigurationException("Class '" + epServicesContextFactoryClassName + "' cannot be loaded"); } object obj; try { obj = TypeHelper.Instantiate(clazz); } catch (Exception) { throw new ConfigurationException("Class '" + clazz + "' cannot be instantiated"); } epServicesContextFactory = (EPServicesContextFactory) obj; } EPServicesContext services; try { services = epServicesContextFactory.CreateServicesContext(this, _configLastProvided); } catch (EPException ex) { throw new ConfigurationException("Failed runtime startup: " + ex.Message, ex); //throw; } catch (Exception ex) { throw new ConfigurationException("Failed runtime startup: " + ex.Message, ex); } // new runtime EPEventServiceImpl eventService = epServicesContextFactory.CreateEPRuntime(services, ServiceStatusProvider); eventService.InternalEventRouter = services.InternalEventRouter; services.InternalEventRouteDest = eventService; // set current time, if applicable if (startTime != null) { services.SchedulingService.Time = startTime.Value; } // Configure services to use the new runtime services.TimerService.Callback = eventService; // New services EPDeploymentServiceSPI deploymentService = new EPDeploymentServiceImpl(services, this); var eventTypeService = new EPEventTypeServiceImpl(services); EPContextPartitionService contextPartitionService = new EPContextPartitionServiceImpl(services); EPVariableService variableService = new EPVariableServiceImpl(services); EPMetricsService metricsService = new EPMetricsServiceImpl(services); EPFireAndForgetService fireAndForgetService = new EpFireAndForgetServiceImpl(services, ServiceStatusProvider); EPStageServiceSPI stageService = new EPStageServiceImpl(services, ServiceStatusProvider); // Build runtime environment _runtimeEnvironment = new EPRuntimeEnv( services, eventService, deploymentService, eventTypeService, contextPartitionService, variableService, metricsService, fireAndForgetService, stageService); // Stage Recovery var stageIterator = services.StageRecoveryService.StagesIterate(); while (stageIterator.MoveNext()) { var entry = stageIterator.Current; long currentTimeStage; if (services.EpServicesHA.CurrentTimeAsRecovered == null) { currentTimeStage = services.SchedulingService.Time; } else if (!services.EpServicesHA.CurrentTimeStageAsRecovered.TryGetValue(entry.Value, out currentTimeStage)) { currentTimeStage = services.SchedulingService.Time; } stageService.RecoverStage(entry.Key, entry.Value, currentTimeStage); } // Deployment Recovery var deploymentIterator = services.DeploymentRecoveryService.Deployments(); ISet<EventType> protectedVisibleTypes = new LinkedHashSet<EventType>(); while (deploymentIterator.MoveNext()) { var entry = deploymentIterator.Current; var deploymentId = entry.Key; StatementUserObjectRuntimeOption userObjectResolver = new ProxyStatementUserObjectRuntimeOption { ProcGetUserObject = env => entry.Value.UserObjectsRuntime.Get(env.StatementId) }; StatementNameRuntimeOption statementNameResolver = env => entry.Value.StatementNamesWhenProvidedByAPI.Get(env.StatementId); StatementSubstitutionParameterOption substitutionParameterResolver = env => { var param = entry.Value.SubstitutionParameters.Get(env.StatementId); if (param == null) { return; } if (env.SubstitutionParameterNames != null) { foreach (var name in env.SubstitutionParameterNames) { env.SetObject(name.Key, param.Get(name.Value)); } } else { for (var i = 0; i < env.SubstitutionParameterTypes.Length; i++) { env.SetObject(i + 1, param.Get(i + 1)); } } }; DeploymentInternal deployerResult; try { deployerResult = Deployer.DeployRecover( deploymentId, entry.Value.StatementIdFirstStatement, entry.Value.Compiled, statementNameResolver, userObjectResolver, substitutionParameterResolver, null, this); } catch (EPDeployException ex) { throw new EPException(ex.Message, ex); } foreach (var eventType in deployerResult.DeploymentTypes.Values) { if (eventType.Metadata.BusModifier == EventTypeBusModifier.BUS || eventType.Metadata.TypeClass == EventTypeTypeClass.NAMED_WINDOW || eventType.Metadata.TypeClass == EventTypeTypeClass.STREAM) { protectedVisibleTypes.Add(eventType); } } // handle staged deployments var stageUri = services.StageRecoveryService.DeploymentGetStage(deploymentId); if (stageUri != null) { stageService.RecoverDeployment(stageUri, deployerResult); } } // Event Handler Recovery var eventHandlers = services.ListenerRecoveryService.Listeners; while (eventHandlers.MoveNext()) { var deployment = eventHandlers.Current; var epStatement = services.StatementLifecycleService.GetStatementById(deployment.Key); epStatement.RecoveryUpdateEventHandlers(new EPStatementListenerSet(deployment.Value)); } // Filter service init ISet<EventType> filterServiceTypes = new LinkedHashSet<EventType>(services.EventTypeRepositoryBus.AllTypes); filterServiceTypes.AddAll(protectedVisibleTypes); Supplier<ICollection<EventType>> availableTypes = () => filterServiceTypes; services.FilterServiceSPI.Init(availableTypes); // Schedule service init services.SchedulingServiceSPI.Init(); // Stage services init stageService.RecoveredStageInitialize(availableTypes); // Start clocking if (_configLastProvided.Runtime.Threading.IsInternalTimerEnabled) { services.TimerService.StartInternalClock(); } // Load and initialize adapter loader classes LoadAdapters(services); // Initialize extension services if (services.RuntimeExtensionServices != null) { ((RuntimeExtensionServicesSPI) services.RuntimeExtensionServices).Init(services, eventService, deploymentService, stageService); } // Start metrics reporting, if any if (_configLastProvided.Runtime.MetricsReporting.IsEnableMetricsReporting) { services.MetricReportingService.SetContext(services.FilterService, services.SchedulingService, eventService); } // Start runtimes metrics report if (_configLastProvided.Runtime.MetricsReporting.IsRuntimeMetrics) { StartEngineMetrics(services, eventService); } // call initialize listeners foreach (var listener in _serviceListeners) { try { listener.OnEPRuntimeInitialized(this); } catch (Exception ex) { Log.Error("Runtime exception caught during an onEPRuntimeInitialized callback:" + ex.Message, ex); } } }
public CafeWindowsServiceStatusOption(ProcessExecutor processExecutor, IFileSystem fileSystem, string serviceName) : base("gets the status of the cafe windows service") { _serviceName = serviceName; _serviceStatusProvider = new ServiceStatusProvider(processExecutor, fileSystem); }