/** * Copyright (C) 2009-2015 Dell, Inc. * See annotations for authorship information * * ==================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ==================================================================== */ package org.dasein.cloud; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Describes what is required for a specific cloud in order to configure Dasein to connect with that cloud. * <p>Created by George Reese: 2/27/14 8:09 PM</p> * @author George Reese * @version 2014.03 initial version (issue #123) * @since 2014.03 */ public class ContextRequirements { /** * The data type associated with a configurable value */ static public enum FieldType { /** * A general text value */ TEXT, /** * A password field that should be treated as sensitive data */ PASSWORD, /** * A secret token, as may be required alternatively to a key-pair, e.g. in OAuth authenticating accounts */ TOKEN, /** * A combo text + password value with the first value being a public-like key thing or user name and the second value being a secret key or password */ KEYPAIR, /** * A straight-up integer number */ INTEGER, /** * A floating point number */ FLOAT } /** * A pairing of field name and its type */ static public class Field { static public final String ACCESS_KEYS = "accessKeys"; // legacy compatibility field name static public final String X509 = "x509"; public String compatName; public String description; public String name; public boolean required; public FieldType type; public Field(@Nonnull String name, @Nonnull FieldType type) { this(name, type, true); } public Field(@Nonnull String name, @Nonnull String description, @Nonnull FieldType type) { this(name, description, type, true); } public Field(@Nonnull String name, @Nonnull FieldType type, @Nonnull String compatName) { this(name, type, compatName, true); } public Field(@Nonnull String name, @Nonnull String description, @Nonnull FieldType type, @Nonnull String compatName) { this(name, description, type, compatName, true); } public Field(@Nonnull String name, @Nonnull FieldType type, boolean required) { this.name = name; this.type = type; this.required = required; } public Field(@Nonnull String name, @Nonnull String description, @Nonnull FieldType type, boolean required) { this.name = name; this.description = description; this.type = type; this.required = required; } public Field(@Nonnull String name, @Nonnull FieldType type, @Nonnull String compatName, boolean required) { this.name = name; this.type = type; this.compatName = compatName; this.required = required; } public Field(@Nonnull String name, @Nonnull String description, @Nonnull FieldType type, @Nonnull String compatName, boolean required) { this.name = name; this.description = description; this.type = type; this.compatName = compatName; this.required = required; } public @Nonnull String toString() { return (name + " (" + type + "): " + description); } } private List<Field> configurableValues = new ArrayList<Field>(); /** * Constructs a set of context requirements from the ordered fields provided. Order is useful in * helping a user interface to present these requirements meaningfully. * @param fields the ordered list of configurable fields */ public ContextRequirements(@Nonnull Field ... fields) { Collections.addAll(configurableValues, fields); } /** * Identifies the field that matches the old accessPublic and accessPrivate fields. Because the new * mechanism treats them as one value, this returns a single field that matches both. If compatibility has * not been defined, the first {@link FieldType#KEYPAIR} field is considered a match. * @return the field that matches the old style keypair of accessPublic and accessPrivate */ public @Nullable Field getCompatAccessKeys() { boolean hasX509 = false; Field def = null; for( Field f : configurableValues ) { if( !hasX509 && Field.X509.equals(f.compatName) ) { hasX509 = true; } if( Field.ACCESS_KEYS.equals(f.compatName) ) { return f; } else if( def == null && f.compatName == null && f.type.equals(FieldType.KEYPAIR) ) { def = f; } } if( hasX509 ) { return null; } return def; } /** * Identifies the field that matches the old x509Cert and x509Key fields. Because the new * mechanism treats them as one value, this returns a single field that matches both. If compatability has * not been defined, the second {@link FieldType#KEYPAIR} field is considered a match. If compatibility was * defined for access keys and not for x509, however, this method will return <code>null</code>. * @return the field that matches the old style keypair of x509Cert and x509Key */ public @Nullable Field getCompatAccessX509() { Field d1 = null, d2 = null; boolean hasAccess = false; for( Field f : configurableValues ) { if( !hasAccess && Field.ACCESS_KEYS.equals(f.compatName) ) { hasAccess = true; } if( Field.X509.equals(f.compatName) ) { return f; } else if( f.type.equals(FieldType.KEYPAIR) && f.compatName == null ) { if( d1 == null ) { d1 = f; } else if( d2 == null ) { d2 = f; } } } if( hasAccess ) { return null; } return d2; } /** * @return an ordered list of configurable fields */ public @Nonnull List<Field> getConfigurableValues() { return Collections.unmodifiableList(configurableValues); } }