/**
 * Validates capability configuration field is valid URI.
 *
 * @since 2.7
 */
public class IntegerValidator extends ValidatorSupport implements Validator {
  private static interface Messages extends MessageBundle {
    @DefaultMessage("%s is an integer value")
    String valid(String fieldLabel);

    @DefaultMessage("%s is not an integer value")
    String invalid(String fieldLabel);

    @DefaultMessage("%s is not an integer value (%s)")
    String invalidReason(String fieldLabel, String failure);
  }

  private static final Messages messages = I18N.create(Messages.class);

  private final String key;

  private final String label;

  @Inject
  public IntegerValidator(
      final Provider<CapabilityDescriptorRegistry> capabilityDescriptorRegistryProvider,
      final @Assisted CapabilityType type,
      final @Assisted String key) {
    super(capabilityDescriptorRegistryProvider, type);
    this.key = checkNotNull(key);
    this.label = propertyName(key);
  }

  @Override
  public ValidationResult validate(final Map<String, String> properties) {
    String value = properties.get(key);
    if (StringUtils.isNotEmpty(value)) {
      try {
        Integer.valueOf(value);
      } catch (NumberFormatException e) {
        return new DefaultValidationResult()
            .add(key, messages.invalidReason(label, e.getMessage()));
      }
    }
    return ValidationResult.VALID;
  }

  @Override
  public String explainValid() {
    return messages.valid(label);
  }

  @Override
  public String explainInvalid() {
    return messages.invalid(label);
  }
}
/**
 * Capability for generating identity key-pair.
 *
 * @since 3.0
 */
@Named(IdentityCapabilityDescriptor.TYPE_ID)
public class IdentityCapability extends CapabilitySupport<IdentityCapabilityConfiguration> {
  private interface Messages extends MessageBundle {
    @DefaultMessage("%s")
    String description(String nodeId);
  }

  private static final Messages messages = I18N.create(Messages.class);

  private final KeyStoreManager keyStoreManager;

  private final LocalNodeAccess localNode;

  private String fingerprint;

  @Inject
  public IdentityCapability(
      final @Named(KeyStoreManagerImpl.NAME) KeyStoreManager keyStoreManager,
      final LocalNodeAccess localNode) {
    this.keyStoreManager = checkNotNull(keyStoreManager);
    this.localNode = checkNotNull(localNode);
  }

  @Override
  protected IdentityCapabilityConfiguration createConfig(final Map<String, String> properties) {
    return new IdentityCapabilityConfiguration(properties);
  }

  public Certificate certificate() throws KeystoreException {
    return keyStoreManager.getCertificate();
  }

  public String certificateAsPem() throws Exception {
    return CertificateUtil.serializeCertificateInPEM(certificate());
  }

  public String certificateFingerprint() throws Exception {
    return fingerprint;
  }

  @Override
  protected void configure(final IdentityCapabilityConfiguration config) throws Exception {
    // Generate identity key-pair if not already created
    if (!keyStoreManager.isKeyPairInitialized()) {
      log.info("Generating identity certificate");

      // For now give something unique to the cert for additional identification purposes
      UUID cn = UUID.randomUUID();
      keyStoreManager.generateAndStoreKeyPair(
          cn.toString(), "Nexus", "Sonatype", "Silver Spring", "MD", "US");
    }

    Certificate cert = certificate();
    log.trace("Certificate:\n{}", cert);

    fingerprint = CertificateUtil.calculateFingerprint(cert);
    log.debug("Fingerprint: {}", fingerprint);
  }

  @Override
  protected void onActivate(final IdentityCapabilityConfiguration config) throws Exception {
    // prime local node-id now
    localNode.getId();
  }

  @Override
  protected void onPassivate(final IdentityCapabilityConfiguration config) throws Exception {
    localNode.reset();
  }

  @Override
  protected void onRemove(final IdentityCapabilityConfiguration config) throws Exception {
    if (keyStoreManager.isKeyPairInitialized()) {
      log.debug("Clearing identity keys");
      keyStoreManager.removePrivateKey();
    }
    fingerprint = null;
  }

  @Override
  protected String renderDescription() throws Exception {
    return messages.description(localNode.getId());
  }

  @Override
  protected String renderStatus() throws Exception {
    return render(
        IdentityCapabilityDescriptor.TYPE_ID + "-status.vm",
        new TemplateParameters()
            .set("nodeId", localNode.getId())
            .set("fingerprint", fingerprint)
            .set("pem", certificateAsPem())
            .set("detail", certificate().toString()));
  }
}