public static JSONObject getConfiguration(final View view) throws ViewException {
    final JSONObject configuration = new JSONObject();
    final List<Bundle> bundles = view.getBundles();
    for (Bundle s : bundles) {
      final String conf = s.getConfig();
      final String state = s.getState();
      final String name = s.getBundleinstance();
      try {
        // setup bundle node in config
        JSONObject bundle = new JSONObject();
        configuration.put(name, bundle);

        // setup conf for bundle
        if (conf != null) {
          bundle.put("conf", new JSONObject(conf));
        } else {
          log.warn("Could not get configuration fragment for bundle '", name, "'");
        }
        // setup state for bundle
        if (state != null) {
          bundle.put("state", new JSONObject(state));
        } else {
          log.warn("Could not get state fragment for bundle '", name, "'");
        }
      } catch (Exception ex) {
        log.error("Malformed JSON in configuration fragment for bundle", name, conf);
      }
    }
    return configuration;
  }
 public static JSONArray getStartupSequence(final View view) throws ViewException {
   final JSONArray startupSequence = new JSONArray();
   final List<Bundle> bundles = view.getBundles();
   log.debug("Got", bundles.size(), "states for view", view.getId());
   for (Bundle s : bundles) {
     final String startup = s.getStartup();
     final String name = s.getName();
     if (startup != null) {
       try {
         startupSequence.put(new JSONObject(startup));
       } catch (JSONException jsonex) {
         log.error(
             jsonex,
             "Malformed JSON in startup sequence fragment for bundle:",
             name,
             "- JSON:",
             startup);
       }
     } else {
       throw new ViewException(
           "Could not get startup sequence fragment for bundle '" + name + "'");
     }
   }
   return startupSequence;
 }
 /**
  * Merges user selections to bundles default config/state.
  *
  * @param bundle bundle to configure
  * @param userConfig overrides for default config
  * @param userState overrides for default state
  * @return root configuration object containing both config and state
  */
 private void mergeBundleConfiguration(
     final Bundle bundle, final JSONObject userConfig, final JSONObject userState) {
   final JSONObject defaultConfig = bundle.getConfigJSON();
   final JSONObject defaultState = bundle.getStateJSON();
   final JSONObject mergedConfig = JSONHelper.merge(defaultConfig, userConfig);
   final JSONObject mergedState = JSONHelper.merge(defaultState, userState);
   bundle.setConfig(mergedConfig.toString());
   bundle.setState(mergedState.toString());
 }
  private void setupMapState(
      final Bundle mapFullBundle, final JSONObject publisherData, final User user)
      throws ActionException {

    // setup map state
    final JSONObject publisherMapState = publisherData.optJSONObject(KEY_MAPSTATE);
    if (publisherMapState == null) {
      throw new ActionParamsException("Could not get state for mapfull from publisher data");
    }
    // complete overrride of template mapfull state with the data coming from publisher!
    mapFullBundle.setState(publisherMapState.toString());

    // setup layers based on user rights (double check for user rights)
    final JSONArray selectedLayers =
        getPublishableLayers(publisherMapState.optJSONArray(KEY_SELLAYERS), user);

    // Override template layer selections
    final boolean layersUpdated =
        JSONHelper.putValue(mapFullBundle.getConfigJSON(), KEY_LAYERS, selectedLayers);
    final boolean selectedLayersUpdated =
        JSONHelper.putValue(mapFullBundle.getStateJSON(), KEY_SELLAYERS, selectedLayers);
    if (!(layersUpdated && selectedLayersUpdated)) {
      // failed to put layers correctly
      throw new ActionParamsException("Could not override layers selections");
    }

    // Set layout
    final String layout = JSONHelper.getStringFromJSON(publisherData, KEY_LAYOUT, "lefthanded");
    JSONHelper.putValue(mapFullBundle.getConfigJSON(), KEY_LAYOUT, layout);

    // Set size
    final JSONObject size = publisherData.optJSONObject(KEY_SIZE);
    if (!JSONHelper.putValue(mapFullBundle.getConfigJSON(), KEY_SIZE, size)) {
      throw new ActionParamsException("Could not set size for map");
    }

    final JSONArray plugins = mapFullBundle.getConfigJSON().optJSONArray(KEY_PLUGINS);
    if (plugins == null) {
      throw new ActionParamsException("Could not get default plugins");
    }
    final JSONArray userConfiguredPlugins = publisherData.optJSONArray(KEY_PLUGINS);

    // merge user configs for template plugins
    for (int i = 0; i < plugins.length(); ++i) {
      JSONObject plugin = plugins.optJSONObject(i);
      // plugins
      JSONObject userPlugin = removePlugin(userConfiguredPlugins, plugin.optString(KEY_ID));
      if (userPlugin != null) {
        // same plugin from template AND user
        // merge config using users as base! and override it with template values
        // this way terms of use etc cannot be overridden by user
        JSONObject mergedConfig =
            JSONHelper.merge(
                userPlugin.optJSONObject(KEY_CONFIG), plugin.optJSONObject(KEY_CONFIG));
        JSONHelper.putValue(plugin, KEY_CONFIG, sanitizeConfigLocation(mergedConfig));
      }
    }
    // add remaining plugins user has selected on top of template plugins
    for (int i = userConfiguredPlugins.length(); --i >= 0; ) {
      JSONObject userPlugin = userConfiguredPlugins.optJSONObject(i);
      JSONHelper.putValue(
          userPlugin, KEY_CONFIG, sanitizeConfigLocation(userPlugin.optJSONObject(KEY_CONFIG)));
      plugins.put(userPlugin);
    }

    // replace current plugins
    JSONHelper.putValue(mapFullBundle.getConfigJSON(), KEY_PLUGINS, plugins);
  }
  public void handleAction(ActionParameters params) throws ActionException {

    final User user = params.getUser();

    // Parse stuff sent by JS
    final JSONObject publisherData = getPublisherInput(params.getRequiredParam(KEY_PUBDATA));
    final View currentView = getBaseView(publisherData, user);

    final Bundle mapFullBundle = currentView.getBundleByName(ViewModifier.BUNDLE_MAPFULL);
    if (mapFullBundle == null) {
      throw new ActionParamsException("Could find mapfull bundle from view:" + currentView.getId());
    }

    // Setup user
    try {
      JSONObject userJson = new JSONObject();
      userJson.put(KEY_FIRSTNAME, user.getFirstname());
      userJson.put(KEY_LASTNAME, user.getLastname());
      userJson.put(KEY_NICKNAME, user.getScreenname());
      userJson.put(KEY_LOGINNAME, user.getEmail());
      JSONHelper.putValue(mapFullBundle.getConfigJSON(), KEY_USER, userJson);
      // mapfullTemplateConfig.put(KEY_USER, userJson);
    } catch (JSONException jsonex) {
      log.error("Could not create user object:", user, "- Error:", jsonex.getMessage());
      throw new ActionParamsException("User data problem");
    }

    // setup basic info about view
    final String domain = JSONHelper.getStringFromJSON(publisherData, KEY_DOMAIN, null);
    if (domain == null) {
      throw new ActionParamsException("Domain missing");
    }
    final String name =
        JSONHelper.getStringFromJSON(
            publisherData, KEY_NAME, "Published map " + System.currentTimeMillis());
    final String language =
        JSONHelper.getStringFromJSON(
            publisherData, KEY_LANGUAGE, PropertyUtil.getDefaultLanguage());

    currentView.setPubDomain(domain);
    currentView.setName(name);
    currentView.setType(params.getHttpParam(ViewTypes.VIEW_TYPE, ViewTypes.PUBLISHED));
    currentView.setCreator(user.getId());
    currentView.setIsPublic(true);
    // application/page/developmentPath should be configured to publish template view
    currentView.setLang(language);

    // setup map state
    setupMapState(mapFullBundle, publisherData, user);

    // setup infobox
    final JSONObject tmpInfoboxState = publisherData.optJSONObject(ViewModifier.BUNDLE_INFOBOX);
    if (tmpInfoboxState != null) {
      final Bundle infoboxTemplateBundle = currentView.getBundleByName(ViewModifier.BUNDLE_INFOBOX);
      if (infoboxTemplateBundle != null) {
        infoboxTemplateBundle.setState(tmpInfoboxState.toString());
      } else {
        log.warn(
            "Publisher sent state for infobox, but infobox isn't available in template view! State:",
            tmpInfoboxState);
      }
    }

    // Setup publishedmyplaces2 bundle if user has configured it/has permission to do so
    if (user.hasAnyRoleIn(drawToolsEnabledRoles)) {
      setupBundle(currentView, publisherData, ViewModifier.BUNDLE_PUBLISHEDMYPLACES2);
    }

    // Setup toolbar bundle if user has configured it
    setupBundle(currentView, publisherData, ViewModifier.BUNDLE_TOOLBAR);

    // Setup thematic map/published grid bundle
    final JSONObject gridState = publisherData.optJSONObject(KEY_GRIDSTATE);
    log.debug("Grid state:", gridState);
    if (gridState != null) {
      final Bundle gridBundle = addBundle(currentView, ViewModifier.BUNDLE_PUBLISHEDGRID);
      log.debug("Grid bundle added:", gridBundle);
      mergeBundleConfiguration(gridBundle, null, gridState);
    }

    log.debug("Save view:", currentView);
    final View newView = saveView(currentView);
    log.debug("Published a map:", newView);

    try {
      JSONObject newViewJson = new JSONObject(newView.toString());
      ResponseHelper.writeResponse(params, newViewJson);
    } catch (JSONException je) {
      log.error(je, "Could not create JSON response.");
      ResponseHelper.writeResponse(params, false);
    }
  }