Class SecretsContexts

java.lang.Object
com.iizix.prop.SecretsContexts

public final class SecretsContexts extends Object
The secrets of the four context roots (SECRETS-STORE-DESIGN.md sections 3 and 5, build order SK-3): the server configuration (server.<name>), the application (app.<appID>), its Push Notification settings (app.<appID>, given by the loader) and the iiziRun build (run.<app_id>). Each root calls resolve(PropCnr) when the tree of its file is complete, and whoever saves the file calls commit(PropCnr) once it is written (decision P-2 (b)): never when a value is typed.

What a commit writes. This class remembers, per loaded root and without a field on any property, the context the root was resolved or last committed under and a digest of each secret's value then. A commit puts only a value that changed in this process since, or whose key changed: a renamed mail sender, environment or port, an unmarked member, or a renamed context (design section 3.3). The entry under the old key is removed, unless another loaded root of this process still reads it. A value another process wrote meanwhile (the tool, a development server) is therefore never overwritten by a save that did not touch it. A property whose value is null is never removed: null means missing here (SK2-D-5).

Changes by another process (storeChanged(Set), decision P-9 (a)): a loaded secret that has no change of its own in this process takes the new value quietly. Consumers that cached the old one take it at their next rebuild or restart.

Nothing leaks. A value is never put in a log line or an exception text; the digests stay in memory beside the values themselves and are never printed.

Thread-safe.

Author:
Christopher Mindus
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final Pattern
    A valid context name: 1 to 128 characters of a-z A-Z 0-9 .
    static final int
    The maximum length of a context name: 128.
  • Method Summary

    Modifier and Type
    Method
    Description
    static String
    checkContext(String context, GProp<?> owner)
    Checks a context name: a valid one is answered as it is, null or empty is none, and an invalid one is reported SEVERE once per name - its secrets are neither resolved nor stored.
    static void
    cloned(PropCnr original, PropCnr clone)
    Carries what is remembered of a root over to its clone, called by the roots' clone: a loader that keeps a clone of the tree it loaded - the Designer's module settings - commits the clone as it would the original.
    static int
    commit(PropCnr container)
    Hands the secrets of every root at or below a container to the installed store, called after the container's file has been written (decision P-2 (b)).
    static boolean
    Checks whether a root has a secret-marked member of its own, i.e.
    static String
    proposeContext(String prefix, String... parts)
    Proposes a context name from a prefix and parts joined with '.', e.g.
    static int
    Gives every secret-marked member of a root its value from the installed store, as SecretsStores.resolve(PropCnr) does, and remembers the context and the values for the next commit.
    static int
    Takes the values another process changed into the loaded roots (decision P-9 (a)): the store's change listener on a server.
  • Field Details

    • MAX_CONTEXT_LENGTH

      public static final int MAX_CONTEXT_LENGTH
      The maximum length of a context name: 128.
      See Also:
    • CONTEXT_PATTERN

      public static final Pattern CONTEXT_PATTERN
      A valid context name: 1 to 128 characters of a-z A-Z 0-9 . _ - (design section 3.1).
  • Method Details

    • checkContext

      public static String checkContext(String context, GProp<?> owner)
      Checks a context name: a valid one is answered as it is, null or empty is none, and an invalid one is reported SEVERE once per name - its secrets are neither resolved nor stored.
      Parameters:
      context - The context name, null for none.
      owner - The root, named in the log.
      Returns:
      The context, or null when it is absent or invalid.
    • proposeContext

      public static String proposeContext(String prefix, String... parts)
      Proposes a context name from a prefix and parts joined with '.', e.g. server.Test2.config: every character a context cannot hold becomes '-', a null or blank part is left out, and the name is cut at 128 characters.
      Parameters:
      prefix - The prefix, e.g. "server".
      parts - The parts.
      Returns:
      The context name.
    • hasSecrets

      public static boolean hasSecrets(PropCnr root)
      Checks whether a root has a secret-marked member of its own, i.e. not below a nested root that gives a context of its own.
      Parameters:
      root - The root.
      Returns:
      true when it has at least one.
    • resolve

      public static int resolve(PropCnr root)
      Gives every secret-marked member of a root its value from the installed store, as SecretsStores.resolve(PropCnr) does, and remembers the context and the values for the next commit. Called by the root when the tree of its file is complete, and by a loader that supplies the context of a root afterwards. A root without a member marked secret is neither resolved nor remembered. A root with marked members and no context is reported once per call - SEVERE on a production server, WARNING elsewhere - and resolves nothing. Never throws: a failure is SEVERE without a value and the load goes on.
      Parameters:
      root - The root, implementing ISecretsContext.
      Returns:
      The number of members that took a value.
    • commit

      public static int commit(PropCnr container)
      Hands the secrets of every root at or below a container to the installed store, called after the container's file has been written (decision P-2 (b)). For each root, a value that changed in this process since the root was resolved or last committed, or whose key changed, is put; a key the root read and no longer has - renamed, unmarked, or of a renamed context - is removed unless another loaded root of this process still reads it (design section 3.3). Unchanged values are not written, so a save never overwrites what another process wrote under a key this process did not change. A null value is skipped, never removed.

      A root with marked members and no context is reported once per call (SEVERE on a production server, WARNING elsewhere) and writes nothing: its values are kept in memory only (design section 3.2). A read-only store is told nothing; that is logged at INFO with the counts. A store that refuses a key is SEVERE naming the key, never the value, and the commit goes on. Never throws.

      Parameters:
      container - The container just saved: a root itself, or a container holding roots (the Designer's module settings hold the application's root).
      Returns:
      The number of keys put and removed.
    • cloned

      public static void cloned(PropCnr original, PropCnr clone)
      Carries what is remembered of a root over to its clone, called by the roots' clone: a loader that keeps a clone of the tree it loaded - the Designer's module settings - commits the clone as it would the original.
      Parameters:
      original - The root cloned.
      clone - The clone.
    • storeChanged

      public static int storeChanged(Set<String> keys)
      Takes the values another process changed into the loaded roots (decision P-9 (a)): the store's change listener on a server. A secret whose value has no change of its own in this process since it was resolved or committed takes the store's value quietly, without an event and without a changed state, as a value read from its file would. A secret with a change of its own keeps it: the next save commits it. A key the store no longer has leaves the value in memory as it is. A value its class cannot convert is SEVERE, naming the key and the class.
      Parameters:
      keys - The keys whose value changed.
      Returns:
      The number of members updated.