Java tutorial
/* * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0 * (the "License"). You may not use this work except in compliance with the License, which is * available at www.apache.org/licenses/LICENSE-2.0 * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied, as more fully set forth in the License. * * See the NOTICE file distributed with this work for information regarding copyright ownership. */ package alluxio.underfs.swift; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.javaswift.joss.client.factory.AccountConfig; import org.javaswift.joss.client.factory.AuthenticationMethod.AccessProvider; import org.javaswift.joss.model.Access; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; import java.util.List; /** * Custom {@link AccessProvider} for Keystone V3 authentication. */ public class KeystoneV3AccessProvider implements AccessProvider { private static final Logger LOG = LoggerFactory.getLogger(KeystoneV3AccessProvider.class); private static final String AUTH_METHOD = "password"; private static final int RESPONSE_OK = 201; private AccountConfig mAccountConfig; /** * Create a new instance of {@link KeystoneV3AccessProvider}. * * @param accountConfig account credentials */ public KeystoneV3AccessProvider(AccountConfig accountConfig) { mAccountConfig = accountConfig; } @Override public Access authenticate() { try { String requestBody; try { // Construct request body KeystoneV3Request request = new KeystoneV3Request( new Auth( new Identity(Arrays.asList(AUTH_METHOD), new Password(new User(mAccountConfig.getUsername(), mAccountConfig.getPassword()))), new Scope(new Project(mAccountConfig.getTenantName())))); requestBody = new ObjectMapper().writeValueAsString(request); } catch (JsonProcessingException e) { LOG.error("Error processing JSON request: {}", e.getMessage()); return null; } try (CloseableHttpClient client = HttpClients.createDefault()) { // Send request HttpPost post = new HttpPost(mAccountConfig.getAuthUrl()); post.addHeader("Accept", "application/json"); post.addHeader("Content-Type", "application/json"); post.setEntity(new ByteArrayEntity(requestBody.toString().getBytes())); try (CloseableHttpResponse httpResponse = client.execute(post)) { // Parse response int responseCode = httpResponse.getStatusLine().getStatusCode(); if (responseCode != RESPONSE_OK) { LOG.error("Error with response code {} ", responseCode); return null; } String token = httpResponse.getFirstHeader("X-Subject-Token").getValue(); // Parse response body try (BufferedReader bufReader = new BufferedReader( new InputStreamReader(httpResponse.getEntity().getContent()))) { String responseBody = bufReader.readLine(); KeystoneV3Response response; try { response = new ObjectMapper().readerFor(KeystoneV3Response.class) .readValue(responseBody); // Find endpoints String internalURL = null; String publicURL = null; for (Catalog catalog : response.mToken.mCatalog) { if (catalog.mName.equals("swift") && catalog.mType.equals("object-store")) { for (Endpoint endpoint : catalog.mEndpoints) { if (endpoint.mRegion.equals(mAccountConfig.getPreferredRegion())) { if (endpoint.mInterface.equals("public")) { publicURL = endpoint.mUrl; } else if (endpoint.mInterface.equals("internal")) { internalURL = endpoint.mUrl; } } } } } // Construct access object KeystoneV3Access access = new KeystoneV3Access(internalURL, mAccountConfig.getPreferredRegion(), publicURL, token); return access; } catch (JsonProcessingException e) { LOG.error("Error processing JSON response: {}", e.getMessage()); return null; } } } } } catch (IOException e) { // Unable to authenticate LOG.error("Exception authenticating using KeystoneV3 {}", e.getMessage()); return null; } } /** Classes for creating authentication JSON request. */ @JsonPropertyOrder({ "auth" }) private class KeystoneV3Request { @JsonProperty("auth") public Auth mAuth; public KeystoneV3Request(Auth auth) { mAuth = auth; } } @JsonPropertyOrder({ "identity", "scope" }) private class Auth { @JsonProperty("identity") public Identity mIdentity; @JsonProperty("scope") public Scope mScope; public Auth(Identity identity, Scope scope) { mIdentity = identity; mScope = scope; } } @JsonPropertyOrder({ "methods", "password" }) private class Identity { @JsonProperty("methods") public List<String> mMethods = null; @JsonProperty("password") public Password mPassword; public Identity(List<String> methods, Password password) { mMethods = methods; mPassword = password; } } @JsonPropertyOrder({ "user" }) private class Password { @JsonProperty("user") public User mUser; public Password(User user) { mUser = user; } } @JsonPropertyOrder({ "id" }) private class Project { @JsonProperty("id") public String mId; public Project(String id) { mId = id; } } @JsonPropertyOrder({ "project" }) private class Scope { @JsonProperty("project") public Project mProject; public Scope(Project project) { mProject = project; } } @JsonPropertyOrder({ "id", "password" }) private class User { @JsonProperty("id") public String mId; @JsonProperty("password") public String mPassword; public User(String id, String password) { mId = id; mPassword = password; } } /** Classes for parsing authentication JSON response. */ @JsonIgnoreProperties(ignoreUnknown = true) private static class KeystoneV3Response { public Token mToken; @JsonCreator public KeystoneV3Response(@JsonProperty("token") Token token) { mToken = token; } } @JsonIgnoreProperties(ignoreUnknown = true) private static class Token { public List<Catalog> mCatalog = null; @JsonCreator public Token(@JsonProperty("catalog") List<Catalog> catalog) { mCatalog = catalog; } } @JsonIgnoreProperties(ignoreUnknown = true) private static class Catalog { public List<Endpoint> mEndpoints; public String mType; public String mName; @JsonCreator public Catalog(@JsonProperty("endpoints") List<Endpoint> endpoints, @JsonProperty("type") String type, @JsonProperty("name") String name) { mEndpoints = endpoints; mType = type; mName = name; } } @JsonIgnoreProperties(ignoreUnknown = true) private static class Endpoint { public String mUrl; public String mRegion; public String mInterface; @JsonCreator public Endpoint(@JsonProperty("url") String url, @JsonProperty("region") String region, @JsonProperty("interface") String inter) { mUrl = url; mRegion = region; mInterface = inter; } } }