/**
  * @param id The globally unique site configuration id.
  * @return A site configuration with the given id. The site configuration may or may not yet exist
  *     in the backing store.
  */
 public static SiteConfiguration fromId(String id) {
   SiteConfiguration siteConfiguration =
       new SiteConfiguration(
           (IEclipsePreferences) scope.getNode(SITE_CONFIGURATIONS_NODE_NAME).node(id));
   siteConfiguration.setId(id);
   return siteConfiguration;
 }
 /**
  * Adds status field to a representation of a site configuration.
  *
  * @param siteConfigJson The JSONObject representing a single site configuration.
  * @param user The user making the request.
  * @param resource The original request passed to the decorator.
  */
 private void addStatus(
     HttpServletRequest req, JSONObject siteConfigJson, WebUser user, URI resource)
     throws JSONException {
   String id = siteConfigJson.getString(ProtocolConstants.KEY_ID);
   SiteConfiguration siteConfiguration = SiteConfiguration.fromId(id);
   IHostedSite site =
       HostingActivator.getDefault().getHostingService().get(siteConfiguration, user);
   JSONObject hostingStatus = new JSONObject();
   if (site != null) {
     hostingStatus.put(
         SiteConfigurationConstants.KEY_HOSTING_STATUS_STATUS, "started"); // $NON-NLS-1$
     String portSuffix = ":" + req.getLocalPort(); // $NON-NLS-1$
     // Whatever scheme was used to access the resource, assume it's used for the sites too
     // Hosted site also shares same contextPath
     String hostedUrl =
         resource.getScheme()
             + "://"
             + site.getHost()
             + portSuffix
             + req.getContextPath(); // $NON-NLS-1$
     hostingStatus.put(SiteConfigurationConstants.KEY_HOSTING_STATUS_URL, hostedUrl);
   } else {
     hostingStatus.put(
         SiteConfigurationConstants.KEY_HOSTING_STATUS_STATUS, "stopped"); // $NON-NLS-1$
   }
   siteConfigJson.put(SiteConfigurationConstants.KEY_HOSTING_STATUS, hostingStatus);
 }
 /*
  * (non-Javadoc)
  * @see org.eclipse.orion.internal.server.servlets.hosting.ISiteHostingService#get(org.eclipse.orion.internal.server.servlets.site.SiteConfiguration, org.eclipse.orion.internal.server.servlets.workspace.WebUser)
  */
 @Override
 public IHostedSite get(SiteConfiguration siteConfig, WebUser user) {
   // Note this may overlap with a concurrent start()/stop() call that modifies the map
   String id = siteConfig.getId();
   String userId = user.getId();
   for (IHostedSite site : sites.values()) {
     if (site.getSiteConfigurationId().equals(id) && site.getUserId().equals(userId)) {
       return site;
     }
   }
   return null;
 }
  /*
   * (non-Javadoc)
   * @see org.eclipse.orion.internal.server.servlets.hosting.ISiteHostingService#start(org.eclipse.orion.internal.server.servlets.site.SiteConfiguration, org.eclipse.orion.internal.server.servlets.workspace.WebUser, java.lang.String)
   */
  @Override
  public void start(SiteConfiguration siteConfig, WebUser user, String editServer)
      throws SiteHostingException {
    synchronized (sites) {
      if (get(siteConfig, user) != null) {
        return; // Already started; nothing to do
      }

      String host = getNextHost(siteConfig.getHostHint());

      try {
        IHostedSite result =
            sites.putIfAbsent(host, new HostedSite(siteConfig, user, host, editServer));
        if (result != null) {
          // Should never happen, since writes are done serially by start()/stop()
          throw new ConcurrentModificationException("Table was modified concurrently");
        }
      } catch (Exception e) {
        sites.remove(host);
        throw new SiteHostingException(e.getMessage(), e);
      }
    }
  }