content: /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you 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 com.aliyun.odps.security;
  
  import java.io.UnsupportedEncodingException;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.Objects;
  
  import com.aliyun.odps.OdpsException;
  import com.aliyun.odps.commons.transport.Headers;
  import com.aliyun.odps.commons.transport.Response;
  import com.aliyun.odps.rest.ResourceBuilder;
  import com.aliyun.odps.rest.RestClient;
  import com.aliyun.odps.rest.SimpleXmlUtils;
  import com.aliyun.odps.security.CheckPermissionConstants.ActionType;
  import com.aliyun.odps.security.CheckPermissionConstants.CheckPermissionResult;
  import com.aliyun.odps.security.CheckPermissionConstants.ObjectType;
  import com.aliyun.odps.security.Role.RoleModel;
  import com.aliyun.odps.security.User.UserModel;
  import com.aliyun.odps.simpleframework.xml.Element;
  import com.aliyun.odps.simpleframework.xml.ElementList;
  import com.aliyun.odps.simpleframework.xml.Root;
  import com.aliyun.odps.simpleframework.xml.convert.Convert;
  import com.aliyun.odps.utils.GsonObjectBuilder;
  import com.aliyun.odps.utils.OdpsConstants;
  import com.aliyun.odps.utils.StringUtils;
  import com.google.gson.GsonBuilder;
  import com.google.gson.JsonArray;
  import com.google.gson.JsonObject;
  
  /**
   * ODPS安全管理类
   *
   * @author mengzhe.yangmz@aliyun-inc.com
   */
  public class SecurityManager {
  
    private String project;
    private RestClient client;
    private SecurityConfiguration securityConfigration;
  
    @Root(name = "Authorization", strict = false)
    static class AuthorizationQueryRequest {
  
      @Element(name = "Query", required = false)
      @Convert(SimpleXmlUtils.EmptyStringConverter.class)
      private String query;
  
      @Element(name = "ResponseInJsonFormat", required = false)
      private boolean responseInJsonFormat;
  
      @Element(name = "Settings", required = false)
      private String settings;
  
      @SuppressWarnings("unused")
      public AuthorizationQueryRequest() {
        this.query = "";
        this.responseInJsonFormat = true;
      }
  
      public AuthorizationQueryRequest(String query, boolean jsonFormat) {
        this.query = query;
        this.responseInJsonFormat = jsonFormat;
      }
  
      public AuthorizationQueryRequest(String query, boolean jsonFormat, String settings) {
        this.query = query;
        this.responseInJsonFormat = jsonFormat;
        this.settings = settings;
      }
  
    }
  
    @Root(name = "Authorization", strict = false)
    static class AuthorizationQueryResponse {
  
      @Element(name = "Result", required = false)
      @Convert(SimpleXmlUtils.EmptyStringConverter.class)
      private String result;
  
      public static AuthorizationQueryResponse from(byte[] body) {
        if (body == null) {
          return null;
        }
  
        return fromXml(body);
      }
  
      private static AuthorizationQueryResponse fromXml(byte[] body) {
        try {
          return SimpleXmlUtils.unmarshal(body, AuthorizationQueryResponse.class);
        } catch (Exception ignore) {
          return null;
        }
      }
  
      public String getResult() {
        return result;
      }
    }
  
    public enum AuthorizationQueryStatus {
      TERMINATED,
      RUNNING,
      FAILED;
    }
  
    @Root(name = "AuthorizationQuery", strict = false)
    private static class AuthorizationQueryStatusModel {
  
      @Element(name = "Result", required = false)
      @Convert(SimpleXmlUtils.EmptyStringConverter.class)
      private String result;
  
      @Element(name = "Status", required = false)
      @Convert(SimpleXmlUtils.EmptyStringConverter.class)
      private String status;
  
      public String getResult() {
        return result;
      }
  
      public AuthorizationQueryStatus getStatus() throws OdpsException {
        if (StringUtils.isNullOrEmpty(status)) {
          throw new IllegalArgumentException("Cannot get authorization query status.");
        }
  
        try {
          return AuthorizationQueryStatus.valueOf(status.toUpperCase());
        } catch (IllegalArgumentException e) {
          throw new OdpsException("Unknown authorization query status: " + status);
        }
      }
    }
  
    public static class AuthorizationQueryInstance {
  
      private String queryResult;
      private String instanceId;
      private String projectName;
      private RestClient client;
      private boolean isSync;
  
  
      public AuthorizationQueryInstance(String result) {
        this.queryResult = result;
        this.isSync = true;
      }
  
      public AuthorizationQueryInstance(String projectName, String instanceId, SecurityManager sm) {
        if (StringUtils.isNullOrEmpty(projectName) || StringUtils.isNullOrEmpty(instanceId)) {
          throw new IllegalArgumentException(
              "Arguments: project and instance id cannot be null or empty.");
        }
        this.projectName = projectName;
        this.instanceId = instanceId;
        this.client = sm.client;
        this.isSync = false;
      }
  
      public String getId() {
        if (isSync) {
          return null;
        }
  
        return instanceId;
      }
  
      public boolean isSync() {
        return isSync;
      }
  
      public String waitForSuccess() throws OdpsException {
        return waitForSuccess(1000);
      }
  
      public String waitForSuccess(long interval) throws OdpsException {
        if (isSync) {
          return queryResult;
        }
  
        while (!isTerminated()) {
          try {
            Thread.sleep(interval);
          } catch (InterruptedException e) {
            throw new OdpsException(e);
          }
        }
  
        AuthorizationQueryStatusModel model = getModel();
        if (model.getStatus() == AuthorizationQueryStatus.TERMINATED) {
          return model.getResult();
        } else {
          throw new OdpsException("Authorization query failed: " + model.getResult());
        }
      }
  
      private AuthorizationQueryStatusModel getModel() throws OdpsException {
        String resource =
            ResourceBuilder.buildProjectAuthorizationInstanceResource(projectName, instanceId);
        return client.request(AuthorizationQueryStatusModel.class, resource, "GET", null, null, null);
      }
  
      public boolean isTerminated() throws OdpsException {
        return (getStatus() != AuthorizationQueryStatus.RUNNING);
      }
  
      public AuthorizationQueryStatus getStatus() throws OdpsException {
        if (!isSync) {
          return getModel().getStatus();
        }
  
        return AuthorizationQueryStatus.TERMINATED;
      }
  
      public String getResult() throws OdpsException {
        if (!isSync) {
          queryResult = getModel().getResult();
        }
        return queryResult;
      }
    }
  
    @Root(name = "Users", strict = false)
    private static class ListUsersResponse {
  
      @ElementList(entry = "User", inline = true, required = false)
      private List<UserModel> users = new ArrayList<UserModel>();
    }
  
    @Root(name = "Roles", strict = false)
    private static class ListRolesResponse {
  
      @ElementList(entry = "Role", inline = true, required = false)
      private List<RoleModel> roles = new ArrayList<RoleModel>();
    }
  
    @Root(name = "Auth", strict = false)
    private static class CheckPermissionResponse {
  
      @Element(name = "Result", required = false)
      @Convert(SimpleXmlUtils.EmptyStringConverter.class)
      private String result;
  
      @Element(name = "Message", required = false)
      @Convert(SimpleXmlUtils.EmptyStringConverter.class)
      private String message;
  
      public String getResult() {
        return result;
      }
  
      public String getMessage() {
        return message;
      }
    }
  
    public SecurityManager(String project, RestClient client) {
      this.project = project;
      this.client = client;
      this.securityConfigration = null;
    }
  
    public SecurityConfiguration getSecurityConfiguration() {
      return getSecurityConfiguration(false);
    }
  
    public SecurityConfiguration getSecurityConfiguration(boolean strip) {
      SecurityConfiguration securityConfiguration;
      if (strip) {
        if (this.securityConfigration == null) {
          securityConfiguration = new SecurityConfiguration(project, client, true);
        } else {
          // If security configuration is cached, return it
          securityConfiguration = this.securityConfigration;
        }
      } else {
        if (this.securityConfigration == null) {
          // If strip is false and security configuration is not cached, cache it
          this.securityConfigration = new SecurityConfiguration(project, client, false);
        }
        securityConfiguration = this.securityConfigration;
      }
  
      return securityConfiguration;
    }
  
    public void setSecurityConfiguration(
        SecurityConfiguration securityConfigration
    ) throws OdpsException {
      securityConfigration.update(null);
    }
  
    public void setSecurityConfiguration(
        SecurityConfiguration securityConfigration, String supervisionToken
    )
        throws OdpsException {
      securityConfigration.update(supervisionToken);
    }
  
    public String getProjectPolicy() throws OdpsException {
      String resource = ResourceBuilder.buildProjectResource(project);
      Map<String, String> params = new HashMap<String, String>();
      params.put("policy", null);
      Response response = client.request(resource, "GET", params, null,
                                         null
      );
      try {
        return new String(response.getBody(), "UTF-8");
      } catch (UnsupportedEncodingException e) {
        throw new OdpsException("Can't parse response!", e);
      }
    }
  
    public void putProjectPolicy(String policy) throws OdpsException {
      String resource = ResourceBuilder.buildProjectResource(project);
      Map<String, String> params = new HashMap<String, String>();
      params.put("policy", null);
      client.stringRequest(resource, "PUT", params, null, policy);
    }
  
    public String getSecurityPolicy() throws OdpsException {
      String resource = ResourceBuilder.buildProjectResource(project);
      Map<String, String> params = new HashMap<String, String>();
      params.put("security_policy", null);
      Response response = client.request(resource, "GET", params, null, null);
      try {
        return new String(response.getBody(), "UTF-8");
      } catch (UnsupportedEncodingException e) {
        throw new OdpsException("Can't parse response!", e);
      }
    }
  
    public void putSecurityPolicy(String securityPolicy) throws OdpsException {
      String resource = ResourceBuilder.buildProjectResource(project);
      Map<String, String> params = new HashMap<String, String>();
      params.put("security_policy", null);
      Map<String, String> headers = new HashMap<String, String>();
      headers.put(Headers.CONTENT_TYPE, "application/json");
      client.stringRequest(resource, "PUT", params, headers, securityPolicy);
    }
  
    public String getRolePolicy(String roleName) throws OdpsException {
      String resource = ResourceBuilder.buildRoleResource(project, roleName);
      Map<String, String> params = new HashMap<String, String>();
      params.put("policy", null);
      Response response = client.request(resource, "GET", params, null,
                                         null
      );
      try {
        return new String(response.getBody(), "UTF-8");
      } catch (UnsupportedEncodingException e) {
        throw new OdpsException("Can't parse response!", e);
      }
    }
  
    public void putRolePolicy(String roleName, String policy)
        throws OdpsException {
      String resource = ResourceBuilder.buildRoleResource(project, roleName);
      Map<String, String> params = new HashMap<String, String>();
      params.put("policy", null);
      client.stringRequest(resource, "PUT", params, null, policy);
    }
  
    public User getUserById(String id) throws OdpsException {
      String resource = ResourceBuilder.buildUserResource(project, id);
      UserModel resp = client.request(UserModel.class, resource, "GET");
      return new User(resp, project, client);
    }
  
    public User getUserByName(String name) throws OdpsException {
      String resource = ResourceBuilder.buildUserResource(project, name);
      Map<String, String> params = new HashMap<String, String>();
      params.put("type", "displayname");
      UserModel resp = client.request(UserModel.class, resource, "GET", params);
      return new User(resp, project, client);
    }
  
    public List<User> listUsers() throws OdpsException {
      String resource = ResourceBuilder.buildUsersResource(project);
      ListUsersResponse resp = client.request(ListUsersResponse.class,
                                              resource, "GET"
      );
      List<User> users = new ArrayList<User>();
      for (UserModel model : resp.users) {
        User t = new User(model, project, client);
        users.add(t);
      }
      return users;
    }
  
    public List<Role> listRoles() throws OdpsException {
      String resource = ResourceBuilder.buildRolesResource(project);
      ListRolesResponse resp = client.request(ListRolesResponse.class,
                                              resource, "GET"
      );
      List<Role> roles = new ArrayList<Role>();
      for (RoleModel model : resp.roles) {
        Role t = new Role(model, project, client);
        roles.add(t);
      }
      return roles;
    }
  
    @Deprecated
    public List<Role> listRolesForUser(String uid) throws OdpsException {
      return listRolesForUserID(uid);
    }
  
    /**
     * 获取指定用户 id 的角色列表
     *
     * @param uid
     * @return
     * @throws OdpsException
     */
    public List<Role> listRolesForUserID(String uid) throws OdpsException {
      return listRolesForUserInternal(uid, null);
    }
  
    /**
     * 获取制定用户名的角色列表
     *
     * @param userName
     * @return
     * @throws OdpsException
     */
    public List<Role> listRolesForUserName(String userName) throws OdpsException {
      return listRolesForUserInternal(userName, "displayname");
    }
  
    private List<Role> listRolesForUserInternal(String user, String type) throws OdpsException {
      String resource = ResourceBuilder.buildUserResource(project, user);
      Map<String, String> params = new HashMap<String, String>();
      params.put("roles", null);
      if (!StringUtils.isNullOrEmpty(type)) {
        params.put("type", type);
      }
      ListRolesResponse resp = client.request(ListRolesResponse.class,
                                              resource, "GET", params, null, null
      );
      List<Role> roles = new ArrayList<Role>();
      for (RoleModel model : resp.roles) {
        Role t = new Role(model, project, client);
        roles.add(t);
      }
      return roles;
    }
  
    public List<User> listUsersForRole(String roleName) throws OdpsException {
      String resource = ResourceBuilder.buildRoleResource(project, roleName);
      Map<String, String> params = new HashMap<String, String>();
      params.put("users", null);
      ListUsersResponse resp = client.request(ListUsersResponse.class,
                                              resource, "GET", params, null, null
      );
      List<User> users = new ArrayList<User>();
      for (UserModel model : resp.users) {
        User t = new User(model, project, client);
        users.add(t);
      }
      return users;
    }
  
    public static class CheckPermissionResultInfo {
      public CheckPermissionResult result;
      public String message;
  
      public CheckPermissionResultInfo(CheckPermissionResult result, String message) {
        this.result = Objects.requireNonNull(result);
        this.message = message;
      }
  
      public CheckPermissionResult getResult() {
        return result;
      }
  
      public String getMessage() {
        return message;
      }
    }
  
    public static class PermissionDesc {
      private String projectName;
      private String schemaName;
      private ObjectType objectType;
      private String objectName;
      private ActionType actionType;
      private Map<String, String> params;
  
      public PermissionDesc(String projectName,
                            ObjectType objectType,
                            String objectName,
                            ActionType actionType) {
        this(projectName, null, objectType, objectName, actionType);
      }
  
      public PermissionDesc(String projectName,
                            String schemaName,
                            ObjectType objectType,
                            String objectName,
                            ActionType actionType) {
        this.projectName = Objects.requireNonNull(projectName);
        this.schemaName = schemaName;
        this.objectType = Objects.requireNonNull(objectType);
        this.objectName = Objects.requireNonNull(objectName);
        this.actionType = Objects.requireNonNull(actionType);
        params = new HashMap<>();
      }
  
      public String getProjectName() {
        return projectName;
      }
  
      public String getSchemaName() {
        return schemaName;
      }
  
      public ObjectType getObjectType() {
        return objectType;
      }
  
      public String getObjectName() {
        return objectName;
      }
  
      public ActionType getActionType() {
        return actionType;
      }
  
      public Map<String, String> getParams() {
        return new HashMap<>(params);
      }
  
      public void setPrincipal(String principal) {
        params.put("Principal", principal);
      }
  
      public void setColumns(List<String> columns) {
        params.put("odps:SelectColumns", GsonObjectBuilder.get().toJson(columns));
      }
  
      public void addParam(String key, String value) {
        params.put(key, value);
      }
  
      private String buildResourceString(ObjectType objectType, String objectName) {
        switch (objectType) {
          case Project:
            return ResourceBuilder.buildProjectResource(projectName);
          case Table:
            return ResourceBuilder.buildTableResource(projectName, objectName);
          case Function:
            return ResourceBuilder.buildFunctionResource(projectName, objectName);
          case Instance:
            return ResourceBuilder.buildInstanceResource(projectName, objectName);
          case Resource:
            return ResourceBuilder.buildResourceResource(projectName, objectName);
          default:
            throw new IllegalArgumentException("Unsupported object type");
        }
      }
  
      public String toJson() {
        JsonArray jsonArray = new JsonArray();
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("Action", actionType.name());
        String resource = buildResourceString(objectType, objectName);
        if (getSchemaName() != null) {
          resource = resource.substring(1);
        }
        jsonObject.addProperty("Resource", resource);
  
        for (Map.Entry<String, String> param : params.entrySet()) {
          jsonObject.addProperty(param.getKey(), param.getValue());
        }
  
        jsonArray.add(jsonObject);
        return GsonObjectBuilder.get().toJson(jsonArray);
      }
    }
  
    /**
     * Check permission
     *
     * @param desc Permission description. See {@link PermissionDesc}
     * @return {@link CheckPermissionResultInfo}
     * @throws OdpsException
     */
    public CheckPermissionResultInfo checkPermission(PermissionDesc desc)
        throws OdpsException {
      String resource = "/projects/" + ResourceBuilder.encodeObjectName(desc.projectName)
                        + "/auth/";
      Map<String, String> headers = new HashMap<>();
      Map<String, String> params = new HashMap<>();
      if (desc.getSchemaName() != null) {
        params.put("curr_schema", desc.getSchemaName());
      }
      headers.put(Headers.CONTENT_TYPE, "application/json");
      CheckPermissionResponse response = client.stringRequest(CheckPermissionResponse.class,
                                                              resource,
                                                              "POST",
                                                              params,
                                                              headers,
                                                              desc.toJson());
      CheckPermissionResult result = CheckPermissionResult.valueOf(response.result);
      return new CheckPermissionResultInfo(result, response.message);
    }
  
    /**
     * 查看是否有操作权限
     *
     * @param type
     *     查看权限的对象类型
     * @param objectName
     *     查看权限的对象名称
     * @param action
     *     查看的权限类型
     * @param projectName
     *     查看对象所在项目名称
     * @param columns
     *     查看权限的列名，若查看列操作权限，type 值为 Table {@link ObjectType}
     * @return CheckPermissionResult
     * @throws OdpsException
     */
    @Deprecated
    public CheckPermissionResult checkPermission(
        ObjectType type, String objectName,
        ActionType action, String projectName,
        List<String> columns
    ) throws OdpsException {
  
      Map<String, String> params = new HashMap<String, String>();
      params.put("type", type.toString());
      params.put("name", objectName);
      params.put("grantee", action.toString());
      if ((columns != null) && !columns.isEmpty()) {
        params.put("columns", StringUtils.join(columns.toArray(), ","));
      }
  
      String resource = "/projects/" + ResourceBuilder.encodeObjectName(projectName)
                        + "/auth/";
      CheckPermissionResponse response = client.request(CheckPermissionResponse.class,
                                                        resource,
                                                        "GET",
                                                        params,
                                                        null,
                                                        null);
      return response.getResult().toUpperCase().equals("ALLOW") ?
             CheckPermissionResult.Allow : CheckPermissionResult.Deny;
    }
  
    /**
     * 查看是否有操作权限
     *
     * @param type
     *     查看权限的对象类型
     * @param objectName
     *     查看权限的对象名称
     * @param action
     *     查看的权限类型
     * @param columns
     *     查看权限的列名，若查看列操作权限，type 值为 Table {@link ObjectType}
     * @return CheckPermissionResult
     * @throws OdpsException
     */
    @Deprecated
    public CheckPermissionResult checkPermission(
        ObjectType type, String objectName,
        ActionType action, List<String> columns
    )
        throws OdpsException {
      return checkPermission(type, objectName, action, project, columns);
    }
  
    /**
     * 查看是否有操作权限
     *
     * @param type
     *     查看权限的对象类型
     * @param objectName
     *     查看权限的对象名称
     * @param action
     *     查看的权限类型
     * @return CheckPermissionResult
     * @throws OdpsException
     */
    @Deprecated
    public CheckPermissionResult checkPermission(
        ObjectType type, String objectName,
        ActionType action
    ) throws OdpsException {
      return checkPermission(type, objectName, action, project);
    }
  
    /**
     * 查看是否有操作权限
     *
     * @param type
     *     查看权限的对象类型
     * @param objectName
     *     查看权限的对象名称
     * @param action
     *     查看的权限类型
     * @param projectName
     *     查看对象所在项目名称
     * @return CheckPermissionResult
     * @throws OdpsException
     */
    @Deprecated
    public CheckPermissionResult checkPermission(
        ObjectType type, String objectName,
        ActionType action, String projectName
    ) throws OdpsException {
      return checkPermission(type, objectName, action, projectName, null);
    }
  
    /**
     * 执行安全命令, 返回 query 实例
     *
     * @param query
     * @param jsonOutput
     * @return query 实例
     * @throws OdpsException
     */
    public AuthorizationQueryInstance run(String query, Boolean jsonOutput) throws OdpsException {
      return run(query, jsonOutput, null);
    }
  
    /**
     * 执行安全命令, 返回 query 实例
     *
     * @param query
     * @param jsonOutput
     * @return query 实例
     * @throws OdpsException
     */
    public AuthorizationQueryInstance run(String query, Boolean jsonOutput, String supervisionToken) throws OdpsException {
      return run(query, jsonOutput, supervisionToken, null);
    }
  
    /**
     * 执行安全命令, 返回 query 实例
     *
     * @param query
     * @param jsonOutput
     * @param supervisionToken
     * @return query 实例
     * @throws OdpsException
     */
    public AuthorizationQueryInstance run(String query, Boolean jsonOutput, String supervisionToken, Map<String, String> settings)
        throws OdpsException {
      String resource = ResourceBuilder.buildProjectSecurityManagerResource(project);
  
      AuthorizationQueryRequest request;
      if (settings == null) {
        request = new AuthorizationQueryRequest(query, jsonOutput);
      } else {
        // default schema priority: hints.get(ODPS_DEFAULT_SCHEMA) > odps.getCurrentSchema()
        if (!settings.containsKey(OdpsConstants.ODPS_DEFAULT_SCHEMA)) {
          settings.put(OdpsConstants.ODPS_DEFAULT_SCHEMA, client.getCurrentSchema());
        }
  
        String settingsString = new GsonBuilder().create().toJson(settings);
        request = new AuthorizationQueryRequest(query, jsonOutput, settingsString);
      }
  
      String xmlRequest;
      try {
        xmlRequest = SimpleXmlUtils.marshal(request);
      } catch (Exception e) {
        throw new OdpsException(e.getMessage(), e);
      }
      HashMap<String, String> headers = new HashMap<String, String>();
      if (supervisionToken != null) {
        headers.put(Headers.ODPS_SUPERVISION_TOKEN, supervisionToken);
      }
      headers.put(Headers.CONTENT_TYPE, "application/xml");
  
      Response response =
          client.stringRequest(resource, "POST", null, headers, xmlRequest);
      try {
        AuthorizationQueryResponse queryResponse =
            AuthorizationQueryResponse.from(response.getBody());
  
        if (response.getStatus() == 200) {
          return new AuthorizationQueryInstance(queryResponse.getResult());
        }
  
        return new AuthorizationQueryInstance(project, queryResponse.getResult(), this);
      } catch (Exception e) {
        throw new OdpsException(e.getMessage(), e);
      }
    }
  
    /**
     * 执行安全命令, 返回 query 结果
     *
     * @param query
     * @param jsonOutput
     * @return query 结果
     * @throws OdpsException
     */
    public String runQuery(String query, Boolean jsonOutput) throws OdpsException {
      return runQuery(query, jsonOutput, null);
    }
  
    /**
     * 执行安全命令, 返回 query 结果
     *
     * @param query
     * @param jsonOutput
     * @param supervisionToken
     * @return query 结果
     * @throws OdpsException
     */
    public String runQuery(String query, Boolean jsonOutput, String supervisionToken)
        throws OdpsException {
      return run(query, jsonOutput, supervisionToken).waitForSuccess();
    }
  
    public String runQuery(String query, Boolean jsonOutput, String supervisionToken, Map<String, String> settings)
        throws OdpsException {
      return run(query, jsonOutput, supervisionToken, settings).waitForSuccess();
    }
  
    public String generateAuthorizationToken(String policy, String type)
        throws OdpsException {
      if ("Bearer".equalsIgnoreCase(type)) {
        String resource = ResourceBuilder.buildProjectSecurityManagerResource(project);
        HashMap<String, String> headers = new HashMap<String, String>();
        headers.put(Headers.CONTENT_TYPE, "application/json");
        Map<String, String> params = new HashMap<String, String>();
        params.put("sign_bearer_token", null);
        AuthorizationQueryResponse response = client.stringRequest(
            AuthorizationQueryResponse.class, resource, "POST", params,
            headers, policy
        );
        return response.getResult();
      } else {
        // 目前只支持bearer类型的token
        throw new OdpsException("Unsupport token type" + type);
      }
  
    }
  }
  