Ejemplo n.º 1
0
  /**
   * Stores the <code>Dictionary</code> under the given <code>pid</code>.
   *
   * @param pid The identifier of the dictionary.
   * @param properties The <code>Dictionary</code> to store.
   * @throws IOException If an error occurrs storing the dictionary. If this exception is thrown, it
   *     is expected, that {@link #exists(String) exists(pid} returns <code>false</code>.
   */
  public void store(String pid, Dictionary properties) throws IOException {
    logger.debug("Store call for {} {}", pid, properties);

    // Store config handling settings in memory
    if (pid.startsWith("org.apache.felix.fileinstall")) {
      tempStore.put(pid, properties);
      return;
    }

    try {
      if (isReady(0) && requireRepository) {
        String id = pidToId(pid);

        Map<String, Object> obj = dictToMap(properties);
        JsonValue content = new JsonValue(obj);
        String configResourceId =
            ConfigBootstrapHelper.getId(
                content.get(ConfigBootstrapHelper.CONFIG_ALIAS).asString(),
                content.get(ConfigBootstrapHelper.SERVICE_PID).asString(),
                content.get(ConfigBootstrapHelper.SERVICE_FACTORY_PID).asString());
        String configString = (String) obj.get(JSONEnhancedConfig.JSON_CONFIG_PROPERTY);
        Map<Object, Object> configMap = deserializeConfig(configString);
        if (configMap != null) {
          configMap.put("_id", configResourceId);
        }
        obj.put(JSONEnhancedConfig.JSON_CONFIG_PROPERTY, configMap);

        Map<String, Object> existing = null;
        try {
          ReadRequest readRequest = Requests.newReadRequest(id);
          existing = repo.read(readRequest).getContent().asMap();
        } catch (NotFoundException ex) {
          // Just detect that it doesn't exist
        }
        if (existing != null) {
          String rev = (String) existing.get("_rev");

          existing.remove("_rev");
          existing.remove("_id");
          obj.remove("_rev"); // beware, this means _id and _rev should not be in config file
          obj.remove("_id"); // beware, this means _id and _rev should not be in config file
          obj.remove(RepoPersistenceManager.BUNDLE_LOCATION);
          obj.remove(RepoPersistenceManager.FELIX_FILEINSTALL_FILENAME);
          if (!existing.equals(obj)) {
            logger.trace("Not matching {} {}", existing, obj);
            boolean retry;
            do {
              retry = false;
              try {
                UpdateRequest r = Requests.newUpdateRequest(id, new JsonValue(obj));
                r.setRevision(rev);
                repo.update(r);
              } catch (PreconditionFailedException ex) {
                logger.debug("Concurrent change during update, retrying {} {}", pid, rev);
                ReadRequest readRequest = Requests.newReadRequest(id);
                existing = repo.read(readRequest).getContent().asMap();
                retry = true;
              }
            } while (retry);
            logger.debug("Updated existing config {} {} {}", new Object[] {pid, rev, obj});
          } else {
            logger.debug(
                "Existing config same as store request, ignoring {} {} {}",
                new Object[] {pid, rev, obj});
          }
        } else {
          logger.trace("Creating: {} {} ", id, obj);
          // This may create a new (empty) configuration, which felix marks with
          // _felix___cm__newConfiguration=true
          String newResourceId = id.substring(CONFIG_CONTEXT_PREFIX.length());
          CreateRequest createRequest =
              Requests.newCreateRequest(CONFIG_CONTEXT_PREFIX, new JsonValue(obj));
          createRequest.setNewResourceId(newResourceId);
          obj = repo.create(createRequest).getContent().asMap();
          logger.debug("Stored new config in repository {} {}", pid, obj);
        }
      } else {
        tempStore.put(pid, properties);
        logger.debug("Stored in memory {} {}", pid, properties);
      }
    } catch (ResourceException ex) {
      throw new IOException("Failed to store configuration in repository: " + ex.getMessage(), ex);
    }
  }