Java源码示例:org.eclipse.che.commons.annotation.Nullable

示例1
@GET
@Produces({MediaType.APPLICATION_JSON})
public RootResourcesList listJSON(@Context ServletContext context) {
  ResourceBinder binder = (ResourceBinder) context.getAttribute(ResourceBinder.class.getName());
  return new RootResourcesList(
      binder
          .getResources()
          .stream()
          .map(
              new Function<ObjectFactory<ResourceDescriptor>, RootResource>() {
                @Nullable
                @Override
                public RootResource apply(ObjectFactory<ResourceDescriptor> input) {
                  ResourceDescriptor descriptor = input.getObjectModel();
                  return new RootResource(
                      descriptor.getObjectClass().getName(), //
                      descriptor.getPathValue().getPath(), //
                      descriptor.getUriPattern().getRegex());
                }
              })
          .collect(toList()));
}
 
示例2
@Inject
public End2EndFlowService(
    @Nullable @Named("che.fabric8.end2end.protect.site_key") String siteKey,
    @Nullable @Named("che.fabric8.end2end.protect.secret_key") String secretKey,
    @Named("che.fabric8.end2end.protect.verify_with_ip") boolean verifyWithIp) {
  this.verifyWithIp = verifyWithIp;
  this.reCaptchaSiteKey = siteKey;
  this.reCaptchaSecretKey = secretKey;
  this.staticFilesFilters = new HashMap<>();
  String siteKeyDecl;
  if (siteKey != null && !siteKey.isEmpty()) {
    siteKeyDecl = "var siteKey='" + siteKey + "';";
  } else {
    siteKeyDecl = "var siteKey='';";
    LOG.warn("No ReCaptcha site key was provided. ReCaptcha user verification is disabled !");
  }
  staticFilesFilters.put(
      "files/provision.html", line -> line.replace("const siteKey;", siteKeyDecl));
}
 
示例3
public OrganizationDto create(String name, @Nullable String parentId) throws Exception {
  OrganizationDto data = newDto(OrganizationDto.class).withName(name).withParent(parentId);

  OrganizationDto organizationDto =
      requestFactory
          .fromUrl(getApiUrl())
          .setBody(data)
          .usePostMethod()
          .request()
          .asDto(OrganizationDto.class);

  LOG.info(
      "Organization with name='{}', id='{}', parent's id='{}' created",
      name,
      organizationDto.getId(),
      parentId);

  return organizationDto;
}
 
示例4
@Inject
public LinkedInOAuthAuthenticator(
    @Nullable @Named("oauth.linkedin.clientid") String clientId,
    @Nullable @Named("oauth.linkedin.clientsecret") String clientSecret,
    @Nullable @Named("oauth.linkedin.redirecturis") String[] redirectUris,
    @Nullable @Named("oauth.linkedin.authuri") String authUri,
    @Nullable @Named("oauth.linkedin.tokenuri") String tokenUri,
    @Nullable @Named("oauth.linkedin.useruri") String userUri)
    throws IOException {
  if (!isNullOrEmpty(clientId)
      && !isNullOrEmpty(clientSecret)
      && !isNullOrEmpty(authUri)
      && !isNullOrEmpty(tokenUri)
      && !isNullOrEmpty(userUri)
      && redirectUris != null
      && redirectUris.length != 0) {
    configure(
        clientId, clientSecret, redirectUris, authUri, tokenUri, new MemoryDataStoreFactory());
  }
  this.userUri = userUri;
}
 
示例5
@Inject
public BitbucketOAuthAuthenticator(
    @Nullable @Named("oauth.bitbucket.clientid") String clientId,
    @Nullable @Named("oauth.bitbucket.clientsecret") String clientSecret,
    @Nullable @Named("oauth.bitbucket.redirecturis") String[] redirectUris,
    @Nullable @Named("oauth.bitbucket.useruri") String userUri,
    @Nullable @Named("oauth.bitbucket.authuri") String authUri,
    @Nullable @Named("oauth.bitbucket.tokenuri") String tokenUri)
    throws IOException {
  super();
  if (!isNullOrEmpty(clientId)
      && !isNullOrEmpty(clientSecret)
      && !isNullOrEmpty(authUri)
      && !isNullOrEmpty(tokenUri)
      && redirectUris != null
      && redirectUris.length != 0) {

    configure(
        clientId, clientSecret, redirectUris, authUri, tokenUri, new MemoryDataStoreFactory());
  }
  this.userUri = userUri;
}
 
示例6
@Inject
public WorkspaceService(
    @Named("che.api") String apiEndpoint,
    @Named(CHE_WORKSPACE_AUTO_START) boolean cheWorkspaceAutoStart,
    WorkspaceManager workspaceManager,
    MachineTokenProvider machineTokenProvider,
    WorkspaceLinksGenerator linksGenerator,
    @Named(CHE_WORKSPACE_PLUGIN_REGISTRY_URL_PROPERTY) @Nullable String pluginRegistryUrl,
    @Named(CHE_WORKSPACE_DEVFILE_REGISTRY_URL_PROPERTY) @Nullable String devfileRegistryUrl,
    @Named(CHE_WORKSPACE_PERSIST_VOLUMES_PROPERTY) boolean defaultPersistVolumes,
    URLFetcher urlFetcher,
    @Named(DEBUG_WORKSPACE_START_LOG_LIMIT_BYTES) Long logLimitBytes) {
  this.apiEndpoint = apiEndpoint;
  this.cheWorkspaceAutoStart = cheWorkspaceAutoStart;
  this.workspaceManager = workspaceManager;
  this.machineTokenProvider = machineTokenProvider;
  this.linksGenerator = linksGenerator;
  this.pluginRegistryUrl = pluginRegistryUrl;
  this.devfileRegistryUrl = devfileRegistryUrl;
  this.devfileContentProvider = new URLFileContentProvider(null, urlFetcher);
  this.defaultPersistVolumes = defaultPersistVolumes;
  this.logLimitBytes = logLimitBytes;
}
 
示例7
@Inject
public ProjectLockerOAuthAuthenticator(
    @Nullable @Named("oauth.projectlocker.clientid") String clientId,
    @Nullable @Named("oauth.projectlocker.clientsecret") String clientSecret,
    @Nullable @Named("oauth.projectlocker.redirecturis") String[] redirectUris,
    @Nullable @Named("oauth.projectlocker.authuri") String authUri,
    @Nullable @Named("oauth.projectlocker.tokenuri") String tokenUri)
    throws IOException {
  if (!isNullOrEmpty(clientId)
      && !isNullOrEmpty(clientSecret)
      && !isNullOrEmpty(authUri)
      && !isNullOrEmpty(tokenUri)
      && redirectUris != null
      && redirectUris.length != 0) {

    configure(
        clientId, clientSecret, redirectUris, authUri, tokenUri, new MemoryDataStoreFactory());
  }
}
 
示例8
@Inject
public OpenShiftOAuthAuthenticator(
    @Nullable @Named("che.oauth.openshift.clientid") String clientId,
    @Nullable @Named("che.oauth.openshift.clientsecret") String clientSecret,
    @Nullable @Named("che.oauth.openshift.oauth_endpoint") String oauthEndpoint,
    @Nullable @Named("che.oauth.openshift.verify_token_url") String verifyTokenUrl,
    @Named("che.api") String apiEndpoint)
    throws IOException {
  this.verifyTokenUrl = verifyTokenUrl;
  String[] redirectUrl = {apiEndpoint + "/oauth/callback"};
  if (!isNullOrEmpty(clientId) && !isNullOrEmpty(clientSecret) && !isNullOrEmpty(oauthEndpoint)) {
    oauthEndpoint = oauthEndpoint.endsWith("/") ? oauthEndpoint : oauthEndpoint + "/";
    configure(
        clientId,
        clientSecret,
        redirectUrl,
        oauthEndpoint + "oauth/authorize",
        oauthEndpoint + "oauth/token",
        new MemoryDataStoreFactory());
  }
}
 
示例9
@VisibleForTesting
InternalEnvironment createInternalEnvironment(
    @Nullable Environment environment,
    Map<String, String> workspaceConfigAttributes,
    List<? extends Command> commands,
    DevfileImpl devfile)
    throws InfrastructureException, ValidationException, NotFoundException {
  String recipeType;
  if (environment == null) {
    recipeType = Constants.NO_ENVIRONMENT_RECIPE_TYPE;
  } else {
    recipeType = environment.getRecipe().getType();
  }
  InternalEnvironmentFactory factory = environmentFactories.get(recipeType);
  if (factory == null) {
    throw new NotFoundException(
        format("InternalEnvironmentFactory is not configured for recipe type: '%s'", recipeType));
  }
  InternalEnvironment internalEnvironment = factory.create(environment);
  internalEnvironment.setAttributes(new HashMap<>(workspaceConfigAttributes));
  internalEnvironment.setCommands(commands.stream().map(CommandImpl::new).collect(toList()));
  internalEnvironment.setDevfile(devfile);

  return internalEnvironment;
}
 
示例10
protected OAuthAuthenticator(
    String clientId,
    String requestTokenUri,
    String accessTokenUri,
    String authorizeTokenUri,
    String redirectUri,
    @Nullable String clientSecret,
    @Nullable String privateKey) {
  this.clientId = clientId;
  this.clientSecret = clientSecret;
  this.privateKey = privateKey;
  this.requestTokenUri = requestTokenUri;
  this.accessTokenUri = accessTokenUri;
  this.authorizeTokenUri = authorizeTokenUri;
  this.redirectUri = redirectUri;
  this.httpTransport = new NetHttpTransport();
  this.credentialsStore = new HashMap<>();
  this.credentialsStoreLock = new ReentrantLock();
  this.sharedTokenSecrets = new HashMap<>();
}
 
示例11
@Inject
public IdentityProviderConfigFactory(
    KeycloakServiceClient keycloakServiceClient,
    KeycloakSettings keycloakSettings,
    Provider<WorkspaceRuntimes> workspaceRuntimeProvider,
    @Nullable @Named("che.infra.openshift.oauth_identity_provider") String oauthIdentityProvider,
    @Named("che.api") String apiEndpoint) {
  this.keycloakServiceClient = keycloakServiceClient;
  this.workspaceRuntimeProvider = workspaceRuntimeProvider;
  this.oauthIdentityProvider = oauthIdentityProvider;

  messageToLinkAccount =
      "You should link your account with the <strong>"
          + oauthIdentityProvider
          + "</strong> \n"
          + "identity provider by visiting the "
          + "<a href='"
          + keycloakSettings.get().get(AUTH_SERVER_URL_SETTING)
          + "/realms/"
          + keycloakSettings.get().get(REALM_SETTING)
          + "/account/identity?referrer="
          + keycloakSettings.get().get(CLIENT_ID_SETTING)
          + "&referrer_uri="
          + buildReferrerURI(apiEndpoint)
          + "' target='_blank' rel='noopener noreferrer'><strong>Federated Identities</strong></a> page of your Che account";
}
 
示例12
@Inject
public OpenShiftClientFactory(
    OpenShiftClientConfigFactory configBuilder,
    @Nullable @Named("che.infra.kubernetes.master_url") String masterUrl,
    @Nullable @Named("che.infra.kubernetes.trust_certs") Boolean doTrustCerts,
    @Named("che.infra.kubernetes.client.http.async_requests.max") int maxConcurrentRequests,
    @Named("che.infra.kubernetes.client.http.async_requests.max_per_host")
        int maxConcurrentRequestsPerHost,
    @Named("che.infra.kubernetes.client.http.connection_pool.max_idle") int maxIdleConnections,
    @Named("che.infra.kubernetes.client.http.connection_pool.keep_alive_min")
        int connectionPoolKeepAlive,
    EventListener eventListener) {
  super(
      masterUrl,
      doTrustCerts,
      maxConcurrentRequests,
      maxConcurrentRequestsPerHost,
      maxIdleConnections,
      connectionPoolKeepAlive,
      eventListener);
  this.configBuilder = configBuilder;
}
 
示例13
@Inject
public KubernetesNamespaceFactory(
    @Nullable @Named("che.infra.kubernetes.namespace") String legacyNamespaceName,
    @Nullable @Named("che.infra.kubernetes.service_account_name") String serviceAccountName,
    @Nullable @Named("che.infra.kubernetes.cluster_role_name") String clusterRoleName,
    @Nullable @Named("che.infra.kubernetes.namespace.default") String defaultNamespaceName,
    @Named("che.infra.kubernetes.namespace.allow_user_defined")
        boolean allowUserDefinedNamespaces,
    KubernetesClientFactory clientFactory,
    UserManager userManager,
    KubernetesSharedPool sharedPool)
    throws ConfigurationException {
  this.userManager = userManager;
  this.legacyNamespaceName = legacyNamespaceName;
  this.serviceAccountName = serviceAccountName;
  this.clusterRoleName = clusterRoleName;
  this.clientFactory = clientFactory;
  this.defaultNamespaceName = defaultNamespaceName;
  this.allowUserDefinedNamespaces = allowUserDefinedNamespaces;
  this.sharedPool = sharedPool;

  if (isNullOrEmpty(defaultNamespaceName)) {
    throw new ConfigurationException("che.infra.kubernetes.namespace.default must be configured");
  }
}
 
示例14
@Inject
public KubernetesClientFactory(
    @Nullable @Named("che.infra.kubernetes.master_url") String masterUrl,
    @Nullable @Named("che.infra.kubernetes.trust_certs") Boolean doTrustCerts,
    @Named("che.infra.kubernetes.client.http.async_requests.max") int maxConcurrentRequests,
    @Named("che.infra.kubernetes.client.http.async_requests.max_per_host")
        int maxConcurrentRequestsPerHost,
    @Named("che.infra.kubernetes.client.http.connection_pool.max_idle") int maxIdleConnections,
    @Named("che.infra.kubernetes.client.http.connection_pool.keep_alive_min")
        int connectionPoolKeepAlive,
    EventListener eventListener) {
  this.defaultConfig = buildDefaultConfig(masterUrl, doTrustCerts);
  OkHttpClient temporary = HttpClientUtils.createHttpClient(defaultConfig);
  OkHttpClient.Builder builder = temporary.newBuilder();
  ConnectionPool oldPool = temporary.connectionPool();
  builder.connectionPool(
      new ConnectionPool(maxIdleConnections, connectionPoolKeepAlive, TimeUnit.MINUTES));
  oldPool.evictAll();
  this.httpClient = builder.eventListener(eventListener).build();
  httpClient.dispatcher().setMaxRequests(maxConcurrentRequests);
  httpClient.dispatcher().setMaxRequestsPerHost(maxConcurrentRequestsPerHost);
}
 
示例15
@Inject
public GitHubOAuthAuthenticator(
    @Nullable @Named("che.oauth.github.clientid") String clientId,
    @Nullable @Named("che.oauth.github.clientsecret") String clientSecret,
    @Nullable @Named("che.oauth.github.redirecturis") String[] redirectUris,
    @Nullable @Named("che.oauth.github.authuri") String authUri,
    @Nullable @Named("che.oauth.github.tokenuri") String tokenUri)
    throws IOException {
  if (!isNullOrEmpty(clientId)
      && !isNullOrEmpty(clientSecret)
      && !isNullOrEmpty(authUri)
      && !isNullOrEmpty(tokenUri)
      && redirectUris != null
      && redirectUris.length != 0) {

    configure(
        clientId, clientSecret, redirectUris, authUri, tokenUri, new MemoryDataStoreFactory());
  }
}
 
示例16
/**
 * Returns true is specified object is matched by specified selector, false otherwise.
 *
 * <p>An empty selector is considered to match anything.
 *
 * @param metadata object metadata to check matching
 * @param selector the selector to match the metadata with
 */
public static boolean test(@Nullable ObjectMeta metadata, Map<String, String> selector) {
  if (selector.isEmpty()) {
    // anything matches if we have nothing to select with
    return true;
  }

  if (metadata == null) {
    return false;
  }

  Map<String, String> labels = metadata.getLabels();
  if (labels == null) {
    return false;
  }

  return labels.entrySet().containsAll(selector.entrySet());
}
 
示例17
@Override
@Nullable
public String getId() throws ExecutionException, InterruptedException {
  if (future == null) {
    try {
      Workspace wsConfig = testWorkspaceServiceClient.getByName(name, owner.getName());
      id.set(wsConfig.getId());
      return id.get();
    } catch (Exception e) {
      String errorMessage =
          format("Failed to obtain id of workspace name='%s' owner='%s'", name, owner.getName());

      LOG.warn(errorMessage, e);

      return null;
    }
  }

  return future.thenApply(aVoid -> id.get()).get();
}
 
示例18
private String buildPath(String fragment1, @Nullable String fragment2) {
  StringBuilder sb = new StringBuilder(fragment1);

  if (!isNullOrEmpty(fragment2)) {
    if (!fragment1.endsWith("/")) {
      sb.append('/');
    }

    if (fragment2.startsWith("/")) {
      sb.append(fragment2.substring(1));
    } else {
      sb.append(fragment2);
    }
  }

  // always end server URLs with a slash, so that they can be safely sub-path'd..
  if (sb.charAt(sb.length() - 1) != '/') {
    sb.append('/');
  }

  return sb.toString();
}
 
示例19
/**
 * Exposes service port on given service externally (outside kubernetes cluster). The exposed
 * service port is associated with a specific Server configuration. Server configuration should be
 * encoded in the exposing object's annotations, to be used by {@link KubernetesServerResolver}.
 *
 * @param k8sEnv Kubernetes environment
 * @param machineName machine containing servers
 * @param serviceName service associated with machine, mapping all machine server ports
 * @param serverId non-null for a unique server, null for a compound set of servers that should be
 *     exposed together.
 * @param servicePort specific service port to be exposed externally
 * @param externalServers server configs of servers to be exposed externally
 */
public void expose(
    T k8sEnv,
    @Nullable String machineName,
    String serviceName,
    String serverId,
    ServicePort servicePort,
    Map<String, ServerConfig> externalServers) {

  if (serverId == null) {
    // this is the ID for non-unique servers
    serverId = servicePort.getName();
  }

  Ingress ingress =
      generateIngress(machineName, serviceName, serverId, servicePort, externalServers);

  k8sEnv.getIngresses().put(ingress.getMetadata().getName(), ingress);
}
 
示例20
/**
 * Read supported version info from official site.
 *
 * @param webDriverOfficialNotes address of official page with Google driver info
 * @return string with supported version range (for example, "36-40"), or null if version info
 *     doesn't found inside the official notes.
 * @throws IOException
 */
@Nullable
private String readSupportedVersionInfoForGoogleDriver(URL webDriverOfficialNotes)
    throws IOException {
  try (Scanner scanner = new Scanner(webDriverOfficialNotes.openStream(), "UTF-8")) {
    while (scanner.hasNextLine()) {
      String versionLine = scanner.findInLine("Supports Chrome v([\\d-]+)");
      if (versionLine != null) {
        return scanner.match().group(1);
      }

      scanner.nextLine();
    }
  }

  return null;
}
 
示例21
@Inject
public Fabric8OpenShiftClientFactory(
    Fabric8WorkspaceEnvironmentProvider envProvider,
    Provider<WorkspaceRuntimes> workspaceRuntimeProvider,
    WorkspaceSubjectsRegistry subjectsRegistry,
    KubernetesRuntimeStateCache runtimeStateCache,
    CheServiceAccountTokenToggle cheServiceAccountTokenToggle,
    @Nullable @Named("che.infra.kubernetes.trust_certs") Boolean doTrustCerts,
    @Named("che.infra.kubernetes.client.http.async_requests.max") int maxConcurrentRequests,
    @Named("che.infra.kubernetes.client.http.async_requests.max_per_host")
        int maxConcurrentRequestsPerHost,
    @Named("che.infra.kubernetes.client.http.connection_pool.max_idle") int maxIdleConnections,
    @Named("che.infra.kubernetes.client.http.connection_pool.keep_alive_min")
        int connectionPoolKeepAlive,
    EventListener eventListener) {
  super(
      null,
      null,
      doTrustCerts != null ? doTrustCerts.booleanValue() : false,
      maxConcurrentRequests,
      maxConcurrentRequestsPerHost,
      maxIdleConnections,
      connectionPoolKeepAlive,
      eventListener);
  this.envProvider = envProvider;
  this.workspaceRuntimeProvider = workspaceRuntimeProvider;
  this.subjectsRegistry = subjectsRegistry;
  this.runtimeStateCache = runtimeStateCache;
  this.cheServiceAccountTokenToggle = cheServiceAccountTokenToggle;
}
 
示例22
@Override
protected InternalEnvironment doCreate(
    @Nullable InternalRecipe recipe,
    Map<String, InternalMachineConfig> machines,
    List<Warning> warnings)
    throws InternalInfrastructureException {
  if (recipe != null) {
    throw new InternalInfrastructureException(
        "No environment factory doesn't accept non-null workspace recipes");
  }
  return new NoEnvInternalEnvironment();
}
 
示例23
@Inject
public OpenshiftUserTokenProvider(
    @Nullable @Named(OIDC_PROVIDER_SETTING) String oidcProvider,
    @Nullable @Named(AUTH_SERVER_URL_SETTING) String keycloakServerURL,
    @Nullable @Named(REALM_SETTING) String keycloakRealm,
    OkHttpClient httpClient,
    @Named("che.fabric8.standalone") boolean standalone) {

  if (standalone) {
    // When RhChe is used in standalone mode, it uses the dedicated Keycloak as
    // the Che authentication provider

    if (keycloakServerURL == null) {
      throw new RuntimeException("The 'AUTH_SERVER_URL_SETTING' property should be set");
    }
    tokenEndpoint = keycloakServerURL + "/realms/" + keycloakRealm + "/broker/openshift-v3/token";
  } else {
    // When RhChe is used in OSIO mode (along with the oter fabric8 services, it uses the
    // alternate
    // fabric8_auth OIDC provider as the Che authentication provider.

    if (oidcProvider == null) {
      throw new RuntimeException("The 'OIDC_PROVIDER_SETTING' property should be set");
    }
    tokenEndpoint = oidcProvider + "/token?for=openshift";
  }
  this.httpClient = httpClient;
  this.tokenCache =
      CacheBuilder.newBuilder()
          .maximumSize(CONCURRENT_USERS)
          .expireAfterWrite(CACHE_TIMEOUT_MINUTES, TimeUnit.MINUTES)
          .build(CacheLoader.from(this::getOsToken));
}
 
示例24
@Inject
public AnalyticsService(
    @Nullable @Named("che.fabric8.analytics.segment_write_key") String segmentWriteKey,
    @Nullable @Named("che.fabric8.analytics.woopra_domain") String woopraDomain) {
  this.segmentWriteKey = segmentWriteKey;
  this.woopraDomain = woopraDomain;
}
 
示例25
private OAuthHmacSigner getOAuthHmacSigner(
    @Nullable String clientSecret, @Nullable String oauthTemporaryToken)
    throws NoSuchAlgorithmException, InvalidKeySpecException {
  final OAuthHmacSigner signer = new OAuthHmacSigner();
  signer.clientSharedSecret = clientSecret;
  signer.tokenSharedSecret = sharedTokenSecrets.remove(oauthTemporaryToken);
  return signer;
}
 
示例26
@Nullable
private Optional<Constructor<?>> findConstructor(Class<?> type) {
  return Stream.of(type.getConstructors())
      .filter(
          c ->
              c.isAnnotationPresent(com.google.inject.Inject.class)
                  || c.isAnnotationPresent(javax.inject.Inject.class))
      .findAny();
}
 
示例27
@Inject
public PassportValidator(
    ProfileDao profileDao, @Nullable @Named("auth.blocked_country_names") String[] blockedList) {
  this.profileDao = profileDao;
  if (blockedList == null || blockedList.length == 0) {
    this.blockedList = new ArrayList<>();
  } else {
    this.blockedList = Arrays.asList(blockedList);
  }
}
 
示例28
/**
 * Normalizes user identifier by modifying a {@link LdapEntry}, does nothing if the entry doesn't
 * contain id attribute.
 *
 * @param entry the entry to normalize
 */
public void normalize(@Nullable LdapEntry entry) {
  if (entry != null) {
    final LdapAttribute idAttr = entry.getAttribute(idAttributeName);
    if (idAttr != null) {
      final String normalizedId = normalize(idAttr.getStringValue());
      idAttr.clear();
      idAttr.addStringValue(normalizedId);
    }
  }
}
 
示例29
/**
 * Retrieves user identifier from the given {@code entry} and returns a normalized value of it.
 *
 * @param entry the entry to retrieve id from
 * @return normalized id value or null if {@code entry} is null or id is missing from entry
 */
@Nullable
public String retrieveAndNormalize(@Nullable LdapEntry entry) {
  if (entry == null) {
    return null;
  }
  final LdapAttribute idAttr = entry.getAttribute(idAttributeName);
  if (idAttr == null) {
    return null;
  }
  return normalize(idAttr.getStringValue());
}
 
示例30
/**
 * Creates a valid instance of InternalEnvironment.
 *
 * <p>To construct a valid instance it performs the following actions:
 *
 * <ul>
 *   <li>download recipe content if it is needed;
 *   <li>retrieve the configured installers from installers registry;
 *   <li>normalize servers port by adding default protocol in port if it is absent;
 *   <li>validate the environment machines;
 *   <li>invoke implementation specific method that should validate and parse recipe;
 *   <li>ensure there are environment variables pointing to machine names;
 * </ul>
 *
 * @param sourceEnv the environment
 * @return InternalEnvironment a valid InternalEnvironment instance
 * @throws InfrastructureException if exception occurs on recipe downloading
 * @throws InfrastructureException if infrastructure specific error occurs
 * @throws ValidationException if validation fails
 */
public T create(@Nullable final Environment sourceEnv)
    throws InfrastructureException, ValidationException {

  Map<String, InternalMachineConfig> machines = new HashMap<>();
  List<Warning> warnings = new ArrayList<>();
  InternalRecipe recipe = null;

  if (sourceEnv != null) {
    recipe = recipeRetriever.getRecipe(sourceEnv.getRecipe());

    for (Map.Entry<String, ? extends MachineConfig> machineEntry :
        sourceEnv.getMachines().entrySet()) {
      MachineConfig machineConfig = machineEntry.getValue();

      List<Installer> installers = Collections.emptyList();

      machines.put(
          machineEntry.getKey(),
          new InternalMachineConfig(
              normalizeServers(machineConfig.getServers()),
              machineConfig.getEnv(),
              machineConfig.getAttributes(),
              machineConfig.getVolumes()));
    }

    machinesValidator.validate(machines);
  }

  T internalEnv = doCreate(recipe, machines, warnings);

  internalEnv
      .getMachines()
      .values()
      .forEach(m -> m.getAttributes().put(CONTAINER_SOURCE_ATTRIBUTE, RECIPE_CONTAINER_SOURCE));

  return internalEnv;
}