public void testArgumentsService() throws Exception {
   assertNotNull(context);
   ServiceReference srv = context.getServiceReference(IApplicationContext.class.getName());
   assertNotNull(srv);
   IApplicationContext iac = (IApplicationContext) context.getService(srv);
   Map arguments = iac.getArguments();
   assertEquals("example.equinox.headless.application", arguments.get("eclipse.application"));
 }
Пример #2
0
  public Object start(IApplicationContext context) {

    // create and register a backend server
    // TODO: this info should be saved, not hard coded.
    try {
      context.applicationRunning(); // only run one
      //			MonitorServerManager.getInstance().getServers().get("");
      MonitorServer server = new MonitorServer("admin", "", "admin");
      MonitorServerManager.getInstance().registerServer(server);
      if (!login(server)) return IApplication.EXIT_OK;
      //			MonitorServerManager.getInstance().getCurServer().connectAndLogin();
      //			server.connectAndLogin();

    } catch (RemoteException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (NotBoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    Display display = PlatformUI.createDisplay();
    try {
      int returnCode = PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor());

      if (returnCode == PlatformUI.RETURN_RESTART) {
        return IApplication.EXIT_RESTART;
      }
      return IApplication.EXIT_OK;
    } finally {
      display.dispose();
    }
  }
  /**
   * @param appContext
   * @return
   */
  private URI determineApplicationModelURI(IApplicationContext appContext) {
    Optional<String> appModelPath = getArgValue(IWorkbench.XMI_URI_ARG, appContext, false);

    String appModelPathValue =
        appModelPath
            .filter(path -> !path.isEmpty())
            .orElseGet(
                () -> {
                  Bundle brandingBundle = appContext.getBrandingBundle();
                  if (brandingBundle != null) {
                    return brandingBundle.getSymbolicName()
                        + "/"
                        + E4Application.APPLICATION_MODEL_PATH_DEFAULT;
                  } else {
                    Logger logger = new WorkbenchLogger(PLUGIN_ID);
                    logger.error(
                        new Exception(),
                        "applicationXMI parameter not set and no branding plugin defined. "); //$NON-NLS-1$
                  }
                  return null;
                });

    URI applicationModelURI = null;

    // check if the appModelPath is already a platform-URI and if so use it
    if (URIHelper.isPlatformURI(appModelPathValue)) {
      applicationModelURI = URI.createURI(appModelPathValue, true);
    } else {
      applicationModelURI = URI.createPlatformPluginURI(appModelPathValue, true);
    }
    return applicationModelURI;
  }
  @Override
  public Object start(final IApplicationContext context) throws Exception {

    final String[] cmdArguments =
        (String[]) context.getArguments().get(IApplicationContext.APPLICATION_ARGS);
    Map<String, String> args = null;
    try {
      args = processArgs(cmdArguments);
    } catch (final ArgumentException e) {
      System.err.println(e.getMessage());
      System.err.println(usage());
      return -1;
    }

    JUnitCore junit = new JUnitCore();
    junit.addListener(new MyTextListener());

    if (args.containsKey(ARG_XML_OUT)) {
      final File xmlResultFile = new File(args.get(ARG_XML_OUT));
      JUnitXMLRunListener listener = new JUnitXMLRunListener(xmlResultFile);
      junit.addListener(listener);
    }

    logger.info("Starting regression test");
    logger.info("Platform default encoding: " + Charset.defaultCharset());
    logger.info("Common version: " + getBundleVersion(ProductConstants.PRODUCT_ID_COMMON));
    logger.info("Designer version: " + getBundleVersion(ProductConstants.PRODUCT_ID_DESIGNER));
    logger.info("Titan regression test version: " + getBundleVersion(REGRESSION_TEST_ID));

    Result result = junit.run(MainTestSuite.class);
    printResult(result);
    return IApplication.EXIT_OK;
  }
  protected Object startup(IApplicationContext context) throws Exception {
    // Get BundleContext
    bundleContext = Activator.getContext();
    // Process Arguments
    final String[] args =
        mungeArguments((String[]) context.getArguments().get("application.args")); // $NON-NLS-1$
    processArgs(args);

    createContainer();

    createChannel();

    connectContainer();

    return IApplication.EXIT_OK;
  }
Пример #6
0
 /*
  * (non-Javadoc)
  *
  * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext)
  */
 public Object start(IApplicationContext context) throws Exception {
   try {
     final String[] args =
         mungeArguments((String[]) context.getArguments().get("application.args")); // $NON-NLS-1$
     if (args.length == 1
         && (args[0].equals("-help") || args[0].equals("-h"))) { // $NON-NLS-1$ //$NON-NLS-2$
       usage();
       return IApplication.EXIT_OK;
     } else if (args.length == 2
         && (args[0].equals("-config") || args[0].equals("-c"))) { // $NON-NLS-1$ //$NON-NLS-2$
       // Setup from configuration file (expected after -c <file>
       FileInputStream fis = null;
       try {
         fis = new FileInputStream(args[1]);
         setupServerFromConfig(new ServerConfigParser().load(fis));
       } finally {
         if (fis != null) fis.close();
       }
     } else {
       String hostname = SSLServerSOContainer.DEFAULT_HOST;
       int port = SSLServerSOContainer.DEFAULT_PORT;
       String name = SSLServerSOContainer.DEFAULT_NAME;
       int keepAlive = SSLServerSOContainer.DEFAULT_KEEPALIVE;
       switch (args.length) {
         case 4:
           keepAlive = Integer.parseInt(args[3]);
         case 3:
           hostname = args[2];
         case 2:
           name = args[1];
           if (!name.startsWith("/")) // $NON-NLS-1$
           name = "/" + name; // $NON-NLS-1$
         case 1:
           port = Integer.parseInt(args[0]);
       }
       setupServerFromParameters(hostname, port, name, keepAlive);
     }
     synchronized (this) {
       this.wait();
     }
     return IApplication.EXIT_OK;
   } catch (final Exception e) {
     stop();
     throw e;
   }
 }
Пример #7
0
  @Override
  public Object start(IApplicationContext context) throws Exception {
    this.appContext = context;
    projectNames = new HashMap<String, IProject>();
    importedProjects = new LinkedList<IProject>();
    buildedProjects = new LinkedList<IProject>();
    args = (String[]) appContext.getArguments().get("application.args");

    // test only
    doDebugInitArgs();

    try {
      doTheJobWith();
      return STATUS_OK;
    } catch (Exception e) {
      System.out.println("net.sf.j2s.ui.cmdline Main Exception");
      e.printStackTrace();
      return STATUS_ERROR;
    }
  }
  /**
   * Finds an argument's value in the app's command line arguments, branding, and system properties
   *
   * @param argName the argument name
   * @param appContext the application context
   * @param singledCmdArgValue whether it's a single-valued argument
   * @return an {@link Optional} containing the value or an empty {@link Optional}, if no value
   *     could be found
   */
  private Optional<String> getArgValue(
      String argName, IApplicationContext appContext, boolean singledCmdArgValue) {
    // Is it in the arg list ?
    if (argName == null || argName.length() == 0) return Optional.empty();

    if (singledCmdArgValue) {
      for (int i = 0; i < args.length; i++) {
        if (("-" + argName).equals(args[i])) return Optional.of("true");
      }
    } else {
      for (int i = 0; i < args.length; i++) {
        if (("-" + argName).equals(args[i]) && i + 1 < args.length) return Optional.of(args[i + 1]);
      }
    }

    final String brandingProperty = appContext.getBrandingProperty(argName);

    return Optional.ofNullable(brandingProperty)
        .map(brandingPropertyValue -> Optional.of(brandingPropertyValue))
        .orElse(Optional.ofNullable(System.getProperty(argName)));
  }
Пример #9
0
  // @Override
  public Object startX(IApplicationContext context) throws Exception {

    final Display display = PlatformUI.createDisplay();
    final TakariWorkbenchAdvisor advisor = new TakariWorkbenchAdvisor();
    display.addListener(SWT.OpenDocument, advisor.getOpenDocumentHandler());

    // FIXME: Check unhandled arguments for a pom.xml file and treat like an
    // OpenDocument
    for (String arg : (String[]) context.getArguments().get(IApplicationContext.APPLICATION_ARGS)) {
      File f = new File(arg);
      if (f.exists()) {
        if ("pom.xml".equals(f.getName())) {
          Event e = new Event();
          e.text = arg;
          advisor.getOpenDocumentHandler().handleEvent(e);
        } else if (f.isDirectory() && (f = new File(f, "pom.xml")).exists()) {
          Event e = new Event();
          e.text = f.getPath();
          advisor.getOpenDocumentHandler().handleEvent(e);
        }
      }
    }

    try {
      int returnCode = PlatformUI.createAndRunWorkbench(display, advisor);
      if (returnCode == PlatformUI.RETURN_RESTART) {
        return IApplication.EXIT_RESTART;
      }
      return IApplication.EXIT_OK;
    } finally {
      Location loc = Platform.getInstanceLocation();
      if (loc != null) {
        loc.release();
      }
      display.dispose();
    }
  }
Пример #10
0
 public Object start(IApplicationContext context) throws Exception {
   String[] args = (String[]) context.getArguments().get(IApplicationContext.APPLICATION_ARGS);
   main(args);
   return null;
 }
 @Override
 public Object start(final IApplicationContext context) throws Exception {
   final String[] args =
       (String[]) context.getArguments().get(IApplicationContext.APPLICATION_ARGS);
   return start(args);
 }
Пример #12
0
 @Override
 public Object start(IApplicationContext context) throws Exception {
   String[] args = (String[]) context.getArguments().get(IApplicationContext.APPLICATION_ARGS);
   // Options options = new EclipseOptions();
   return PrimeMain.analyze(args, null);
 }
Пример #13
0
  /** {@inheritDoc} */
  @Override
  public Object start(final IApplicationContext context) throws Exception {
    // Display configuration info
    synchronized (Application.class) {
      final String version =
          (String) context.getBrandingBundle().getHeaders().get("Bundle-Version");
      bundle_version = context.getBrandingName() + " " + version;
    }

    // Create parser for arguments and run it.
    final String args[] = (String[]) context.getArguments().get("application.args");

    final ArgParser parser = new ArgParser();
    final BooleanOption help_opt = new BooleanOption(parser, "-help", "Display help");
    final BooleanOption version_opt = new BooleanOption(parser, "-version", "Display version info");
    parser.addEclipseParameters();
    try {
      parser.parse(args);
    } catch (final Exception ex) {
      System.out.println(ex.getMessage() + "\n" + parser.getHelp());
      return IApplication.EXIT_OK;
    }
    if (help_opt.get()) {
      System.out.println(bundle_version + "\n\n" + parser.getHelp());
      return IApplication.EXIT_OK;
    }
    if (version_opt.get()) {
      System.out.println(bundle_version);
      return IApplication.EXIT_OK;
    }

    final Logger log = Logger.getLogger(getClass().getName());
    try {
      // Display config info
      final Bundle bundle = context.getBrandingBundle();
      log.info(bundle_version);

      LogConfigurator.configureFromPreferences();

      log.config("Scan config       : " + ScanSystemPreferences.getScanConfigPath());
      log.config("Simulation config : " + ScanSystemPreferences.getSimulationConfigPath());
      log.config(
          "Server host:port  : "
              + ScanSystemPreferences.getServerHost()
              + ":"
              + ScanSystemPreferences.getServerPort());
      log.config("Pre-scan commands : " + Arrays.toString(ScanSystemPreferences.getPreScanPaths()));
      log.config(
          "Post-scan commands: " + Arrays.toString(ScanSystemPreferences.getPostScanPaths()));
      log.config("Script paths      : " + Arrays.toString(ScanSystemPreferences.getScriptPaths()));

      // Start server
      final int port = ScanSystemPreferences.getServerPort();
      server = new ScanServerImpl();
      server.start();
      log.config("Scan Server REST interface on http://localhost:" + port + "/index.html");
      final ScanWebServer httpd = new ScanWebServer(bundle.getBundleContext(), server, port);
      // TODO
      // final PVAccessServer pva = new PVAccessServer(server);
      // pva.initializeServerContext();

      // Register console commands
      ConsoleCommands commands = new ConsoleCommands(server);
      final BundleContext bundle_context = bundle.getBundleContext();
      bundle_context.registerService(CommandProvider.class.getName(), commands, null);

      // Keep running...
      run.await();
      server.stop();

      httpd.stop();
      // pva.destroyServerContext();
      // Release commands
      commands = null;
    } catch (Exception ex) {
      log.log(Level.SEVERE, "Exiting on error", ex);
      return Integer.valueOf(-1);
    }

    return EXIT_OK;
  }
Пример #14
0
  public E4Workbench createE4Workbench(
      IApplicationContext applicationContext, final Display display) {
    args = (String[]) applicationContext.getArguments().get(IApplicationContext.APPLICATION_ARGS);

    IEclipseContext appContext = createDefaultContext();
    appContext.set(Display.class, display);
    appContext.set(Realm.class, DisplayRealm.getRealm(display));
    appContext.set(
        UISynchronize.class,
        new UISynchronize() {

          @Override
          public void syncExec(Runnable runnable) {
            if (display != null && !display.isDisposed()) {
              display.syncExec(runnable);
            }
          }

          @Override
          public void asyncExec(Runnable runnable) {
            if (display != null && !display.isDisposed()) {
              display.asyncExec(runnable);
            }
          }
        });
    appContext.set(IApplicationContext.class, applicationContext);

    // This context will be used by the injector for its
    // extended data suppliers
    ContextInjectionFactory.setDefault(appContext);

    // Get the factory to create DI instances with
    IContributionFactory factory = appContext.get(IContributionFactory.class);

    // Install the life-cycle manager for this session if there's one
    // defined
    Optional<String> lifeCycleURI =
        getArgValue(IWorkbench.LIFE_CYCLE_URI_ARG, applicationContext, false);
    lifeCycleURI.ifPresent(
        lifeCycleURIValue -> {
          lcManager = factory.create(lifeCycleURIValue, appContext);
          if (lcManager != null) {
            // Let the manager manipulate the appContext if desired
            ContextInjectionFactory.invoke(lcManager, PostContextCreate.class, appContext, null);
          }
        });

    Optional<String> forcedPerspectiveId =
        getArgValue(PERSPECTIVE_ARG_NAME, applicationContext, false);
    forcedPerspectiveId.ifPresent(
        forcedPerspectiveIdValue ->
            appContext.set(E4Workbench.FORCED_PERSPECTIVE_ID, forcedPerspectiveIdValue));

    String showLocation = getLocationFromCommandLine();
    if (showLocation != null) {
      appContext.set(E4Workbench.FORCED_SHOW_LOCATION, showLocation);
    }

    // Create the app model and its context
    MApplication appModel = loadApplicationModel(applicationContext, appContext);
    appModel.setContext(appContext);

    boolean isRtl = ((Window.getDefaultOrientation() & SWT.RIGHT_TO_LEFT) != 0);
    appModel.getTransientData().put(E4Workbench.RTL_MODE, isRtl);

    // for compatibility layer: set the application in the OSGi service
    // context (see Workbench#getInstance())
    if (!E4Workbench.getServiceContext().containsKey(MApplication.class)) {
      // first one wins.
      E4Workbench.getServiceContext().set(MApplication.class, appModel);
    }

    // Set the app's context after adding itself
    appContext.set(MApplication.class, appModel);

    // adds basic services to the contexts
    initializeServices(appModel);

    // let the life cycle manager add to the model
    if (lcManager != null) {
      ContextInjectionFactory.invoke(lcManager, ProcessAdditions.class, appContext, null);
      ContextInjectionFactory.invoke(lcManager, ProcessRemovals.class, appContext, null);
    }

    // Create the addons
    IEclipseContext addonStaticContext = EclipseContextFactory.create();
    for (MAddon addon : appModel.getAddons()) {
      addonStaticContext.set(MAddon.class, addon);
      Object obj = factory.create(addon.getContributionURI(), appContext, addonStaticContext);
      addon.setObject(obj);
    }

    // Parse out parameters from both the command line and/or the product
    // definition (if any) and put them in the context
    Optional<String> xmiURI = getArgValue(IWorkbench.XMI_URI_ARG, applicationContext, false);
    xmiURI.ifPresent(
        xmiURIValue -> {
          appContext.set(IWorkbench.XMI_URI_ARG, xmiURIValue);
        });

    setCSSContextVariables(applicationContext, appContext);

    Optional<String> rendererFactoryURI =
        getArgValue(E4Workbench.RENDERER_FACTORY_URI, applicationContext, false);
    rendererFactoryURI.ifPresent(
        rendererFactoryURIValue -> {
          appContext.set(E4Workbench.RENDERER_FACTORY_URI, rendererFactoryURIValue);
        });

    // This is a default arg, if missing we use the default rendering engine
    Optional<String> presentationURI =
        getArgValue(IWorkbench.PRESENTATION_URI_ARG, applicationContext, false);
    appContext.set(
        IWorkbench.PRESENTATION_URI_ARG, presentationURI.orElse(PartRenderingEngine.engineURI));

    // Instantiate the Workbench (which is responsible for
    // 'running' the UI (if any)...
    return workbench = new E4Workbench(appModel, appContext);
  }
  /*
   * (non-Javadoc)
   * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext context)
   */
  public Object start(IApplicationContext context) throws Exception {
    System.out.println("S2MaterializerApplication.start");
    Display display = PlatformUI.createDisplay();

    try {
      // look and see if there's a splash shell we can parent off of
      Shell shell = WorkbenchPlugin.getSplashShell(display);
      if (shell != null) {
        // should should set the icon and message for this shell to be the
        // same as the chooser dialog - this will be the guy that lives in
        // the task bar and without these calls you'd have the default icon
        // with no message.
        shell.setText(ChooseWorkspaceDialog.getWindowTitle());
        shell.setImages(Dialog.getDefaultImages());
      }
      //
      // if ( !checkInstanceLocation( shell ) )
      // {
      // WorkbenchPlugin.unsetSplashShell( display );
      // Platform.endSplash();
      // return EXIT_OK;
      // }

      String[] args = (String[]) context.getArguments().get(IApplicationContext.APPLICATION_ARGS);
      String s2ProjectURL = null;
      String nexusBaseURL = null;
      for (int i = 0; i < args.length - 1; i++) {
        if (ARG_DESCRIPTOR_URL.equals(args[i])) {
          s2ProjectURL = args[i + 1];
        }

        if (ARG_NEXUS_BASE_URL.equals(args[i])) {
          nexusBaseURL = args[i + 1];
        }
      }

      if (s2ProjectURL == null || nexusBaseURL == null) {
        System.err.println(
            "Syntax: "
                + ARG_DESCRIPTOR_URL
                + " <descriptor url> "
                + ARG_NEXUS_BASE_URL
                + " <nexus server url>");
        return EXIT_OK;
      }

      NexusFacade.setMainNexusServerData(
          nexusBaseURL, null /* username */, null /* password */, new NullProgressMonitor());

      // Dump some useful debug info :)
      System.out.println(PROP_LAUNCHER + "=" + System.getProperty(PROP_LAUNCHER));
      System.out.println(PROP_VM + "=" + System.getProperty(PROP_VM));
      System.out.println(PROP_VMARGS + "=" + System.getProperty(PROP_VMARGS));
      System.out.println(PROP_COMMANDS + "=" + System.getProperty(PROP_COMMANDS));

      // Save the current workspace location in the eclipse preferences
      Location instanceLoc = Platform.getInstanceLocation();
      File workspaceFile = new File(instanceLoc.getURL().getFile());
      Preferences node = new ConfigurationScope().getNode(IDEWorkbenchPlugin.IDE_WORKBENCH);
      node.put(IDE.Preferences.RECENT_WORKSPACES, workspaceFile.getCanonicalPath());
      node.putInt(
          IDE.Preferences.RECENT_WORKSPACES_PROTOCOL, PERS_ENCODING_VERSION_CONFIG_PREFS_NO_COMMAS);
      node.flush();

      // create the workbench with this advisor and run it until it exits
      // N.B. createWorkbench remembers the advisor, and also registers
      // the workbench globally so that all UI plug-ins can find it using
      // PlatformUI.getWorkbench() or AbstractUIPlugin.getWorkbench()
      int returnCode =
          PlatformUI.createAndRunWorkbench(
              display, new S2MaterializerWorkbenchAdvisor(s2ProjectURL));

      // the workbench doesn't support relaunch yet (bug 61809) so
      // for now restart is used, and exit data properties are checked
      // here to substitute in the relaunch return code if needed
      if (returnCode != PlatformUI.RETURN_RESTART) {
        return EXIT_OK;
      }

      // if the exit code property has been set to the relaunch code, then
      // return that code now, otherwise this is a normal restart
      String command_line = buildCommandLine();
      System.out.println("New command line=" + command_line);
      System.setProperty(PROP_EXIT_DATA, command_line);
      System.out.println(PROP_EXIT_DATA + "=" + System.getProperty(PROP_EXIT_DATA));
      System.setProperty(PROP_EXIT_CODE, "" + Integer.toString(EXIT_RELAUNCH));
      System.out.println(PROP_EXIT_CODE + "=" + System.getProperty(PROP_EXIT_CODE));

      return EXIT_RELAUNCH;
    } finally {
      if (display != null) {
        display.dispose();
      }
      Location instanceLoc = Platform.getInstanceLocation();
      if (instanceLoc != null) instanceLoc.release();
    }
  }
Пример #16
0
  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.equinox.app.IApplication#start(org.eclipse.equinox.app.IApplicationContext context)
   */
  @Override
  public Object start(IApplicationContext appContext) throws Exception {

    // Display display = createDisplay();
    // processor must be created before we start event loop
    // DelayedEventsProcessor processor = new DelayedEventsProcessor(display);

    final Display display = PlatformUI.createDisplay();
    final TakariWorkbenchAdvisor advisor = new TakariWorkbenchAdvisor();
    display.addListener(SWT.OpenDocument, advisor.getOpenDocumentHandler());

    // FIXME: Check unhandled arguments for a pom.xml file and treat like an
    // OpenDocument
    for (String arg :
        (String[]) appContext.getArguments().get(IApplicationContext.APPLICATION_ARGS)) {
      File f = new File(arg);
      if (f.exists()) {
        if ("pom.xml".equals(f.getName())) {
          Event e = new Event();
          e.text = arg;
          advisor.getOpenDocumentHandler().handleEvent(e);
        } else if (f.isDirectory() && (f = new File(f, "pom.xml")).exists()) {
          Event e = new Event();
          e.text = f.getPath();
          advisor.getOpenDocumentHandler().handleEvent(e);
        }
      }
    }

    try {

      // look and see if there's a splash shell we can parent off of
      Shell shell = WorkbenchPlugin.getSplashShell(display);
      if (shell != null) {
        // should should set the icon and message for this shell to be the
        // same as the chooser dialog - this will be the guy that lives in
        // the task bar and without these calls you'd have the default icon
        // with no message.
        shell.setText(ChooseWorkspaceDialog.getWindowTitle());
        shell.setImages(Window.getDefaultImages());
      }

      Object instanceLocationCheck = checkInstanceLocation(shell, appContext.getArguments());
      if (instanceLocationCheck != null) {
        WorkbenchPlugin.unsetSplashShell(display);
        appContext.applicationRunning();
        return instanceLocationCheck;
      }

      // create the workbench with this advisor and run it until it exits
      // N.B. createWorkbench remembers the advisor, and also registers
      // the workbench globally so that all UI plug-ins can find it using
      // PlatformUI.getWorkbench() or AbstractUIPlugin.getWorkbench()
      // int returnCode = PlatformUI.createAndRunWorkbench(display, new
      // TakariWorkbenchAdvisor(processor));
      int returnCode = PlatformUI.createAndRunWorkbench(display, advisor);

      // the workbench doesn't support relaunch yet (bug 61809) so
      // for now restart is used, and exit data properties are checked
      // here to substitute in the relaunch return code if needed
      if (returnCode != PlatformUI.RETURN_RESTART) {
        return EXIT_OK;
      }

      // if the exit code property has been set to the relaunch code, then
      // return that code now, otherwise this is a normal restart
      return EXIT_RELAUNCH.equals(Integer.getInteger(PROP_EXIT_CODE))
          ? EXIT_RELAUNCH
          : EXIT_RESTART;
    } finally {
      if (display != null) {
        display.dispose();
      }
      Location instanceLoc = Platform.getInstanceLocation();
      if (instanceLoc != null) {
        instanceLoc.release();
      }
    }
  }