You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by sm...@apache.org on 2019/09/09 19:17:06 UTC

[airavata-custos] 02/48: added profile service, security service, custos common utilities and thrift files

This is an automated email from the ASF dual-hosted git repository.

smarru pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/airavata-custos.git

commit 6aea83bbfdd4a5e09386f47819c5f68b8b9faae2
Author: Aarushi <aa...@gmail.com>
AuthorDate: Mon Jun 24 10:30:34 2019 -0400

    added profile service, security service, custos common utilities and thrift files
---
 custos-commons/pom.xml                             |    29 +
 .../exceptions/ApplicationSettingsException.java   |    14 +
 .../custos/commons/exceptions/CustosException.java |    35 +
 .../exceptions/CustosSecurityException.java        |    39 +
 .../model/error/AuthenticationException.java       |   385 +
 .../model/error/AuthorizationException.java        |   385 +
 .../custos/commons/utils/ApplicationSettings.java  |   185 +
 .../org/apache/custos/commons/utils/Constants.java |    41 +
 .../apache/custos/commons/utils/CustosUtils.java   |    45 +
 .../apache/custos/commons/utils/DBInitConfig.java  |    33 +
 .../apache/custos/commons/utils/JDBCConfig.java    |    29 +
 .../org/apache/custos/commons/utils/JPAUtils.java  |    67 +
 .../commons/utils/KeyStorePasswordCallback.java    |    69 +
 .../apache/custos/commons/utils/SecurityUtil.java  |   192 +
 .../custos/commons/utils/ServerSettings.java       |    56 +
 .../apache/custos/commons/utils/StringUtil.java    |    43 +
 custos-services/custos-security-service/pom.xml    |    71 +
 .../custos/security/authzcache/AuthzCache.java     |    61 +
 .../security/authzcache/AuthzCacheEntry.java       |    63 +
 .../security/authzcache/AuthzCacheIndex.java       |    90 +
 .../security/authzcache/AuthzCacheManager.java     |    80 +
 .../authzcache/AuthzCacheManagerFactory.java       |    60 +
 .../security/authzcache/AuthzCachedStatus.java     |    34 +
 .../authzcache/DefaultAuthzCacheManager.java       |   106 +
 .../security/manager/CustosSecurityManager.java    |    60 +
 .../custos/security/manager/IdentityContext.java   |    44 +
 .../security/manager/KeyCloakSecurityManager.java  |   537 +
 .../security/manager/SecurityManagerFactory.java   |    60 +
 .../apache/custos/security/manager/UserInfo.java   |    84 +
 .../apache/custos/security/model/AuthzToken.java   |   541 +
 .../custos/security/oauth/DefaultOAuthClient.java  |    91 +
 .../security/service/SecurityServiceHandler.java   |    30 +
 .../custos/security/utils/TrustStoreManager.java   |   100 +
 .../custos/security/xacml/DefaultPAPClient.java    |   124 +
 .../custos/security/xacml/DefaultXACMLPEP.java     |   133 +
 custos-services/pom.xml                            |    34 +
 .../iam-admin-services-core/pom.xml                |    89 +
 .../core/impl/TenantManagementKeycloakImpl.java    |   821 +
 .../core/interfaces/TenantManagementInterface.java |   206 +
 .../admin/services/core/tests/SetupNewGateway.java |   141 +
 custos-services/profile-service/pom.xml            |    25 +
 .../java-client-samples/pom.xml                    |    35 +
 .../profile/client/samples/GroupManagerSample.java |    41 +
 .../client/samples/TenantProfileSample.java        |    61 +
 .../profile/client/samples/UserProfileSample.java  |   121 +
 .../client/util/ProfileServiceClientUtil.java      |    47 +
 .../resources/profile-client-sample.properties     |    29 +
 .../profile-service-client-sdks/pom.xml            |    31 +
 .../profile-service-commons/pom.xml                |   124 +
 .../commons/repositories/AbstractRepository.java   |   124 +
 .../commons/tenant/entities/GatewayEntity.java     |   285 +
 .../user/entities/CustomizedDashboardEntity.java   |   325 +
 .../user/entities/NSFDemographicsEntity.java       |   108 +
 .../commons/user/entities/UserProfileEntity.java   |   345 +
 .../service/profile/commons/utils/Committer.java   |    27 +
 .../profile/commons/utils/JPAConstants.java        |    34 +
 .../service/profile/commons/utils/JPAUtils.java    |    53 +
 .../commons/utils/ObjectMapperSingleton.java       |    39 +
 .../commons/utils/ProfileServiceJDBCConfig.java    |    51 +
 .../profile/commons/utils/QueryConstants.java      |    33 +
 .../service/profile/commons/utils/Utils.java       |   122 +
 .../src/main/resources/META-INF/persistence.xml    |    36 +
 .../profile-service/profile-service-models/pom.xml |    14 +
 .../profile/models/tenant/PasswordCredential.java  |   996 +
 .../custos/profile/models/tenant/Tenant.java       |  1543 ++
 .../models/tenant/TenantApprovalStatus.java        |    78 +
 .../custos/profile/models/tenant/TenantConfig.java |   699 +
 .../profile/models/tenant/TenantPreferences.java   |   594 +
 .../profile/models/user/CustomDashboard.java       |  2912 +++
 .../profile/models/user/NSFDemographics.java       |  1085 ++
 .../apache/custos/profile/models/user/Status.java  |    96 +
 .../custos/profile/models/user/USCitizenship.java  |    67 +
 .../custos/profile/models/user/UserProfile.java    |  3221 ++++
 .../custos/profile/models/user/disability.java     |    66 +
 .../custos/profile/models/user/ethnicity.java      |    65 +
 .../apache/custos/profile/models/user/race.java    |    84 +
 .../models/user/user_profile_modelConstants.java   |    31 +
 .../custos/profile/models/workspace/Gateway.java   |  2383 +++
 .../models/workspace/GatewayApprovalStatus.java    |    78 +
 .../profile-service/profile-service-server/pom.xml |    53 +
 .../handlers/GroupManagerServiceHandler.java       |   385 +
 .../profile/handlers/IamAdminServicesHandler.java  |   307 +
 .../handlers/TenantProfileServiceHandler.java      |   244 +
 .../handlers/UserProfileServiceHandler.java        |   239 +
 .../profile/server/ProfileServiceServer.java       |   201 +
 .../profile-service/profile-service-stubs/pom.xml  |    35 +
 .../client/ProfileServiceClientFactory.java        |    93 +
 .../groupmanager/cpi/GroupManagerService.java      | 17625 +++++++++++++++++
 .../exception/GroupManagerServiceException.java    |   381 +
 .../cpi/group_manager_cpiConstants.java            |    32 +
 .../iam/admin/services/cpi/IamAdminServices.java   | 18889 +++++++++++++++++++
 .../cpi/exception/IamAdminServicesException.java   |   381 +
 .../cpi/iam_admin_services_cpiConstants.java       |    32 +
 .../profile/tenant/cpi/TenantProfileService.java   |  9507 ++++++++++
 .../exception/TenantProfileServiceException.java   |   381 +
 .../tenant/cpi/profile_tenant_cpiConstants.java    |    32 +
 .../profile/user/cpi/UserProfileService.java       |  9858 ++++++++++
 .../cpi/exception/UserProfileServiceException.java |   381 +
 .../user/cpi/profile_user_cpiConstants.java        |    32 +
 .../profile-service/profile-services.iml           |    20 +
 .../profile-service/profile-tenant-core/pom.xml    |    43 +
 .../core/repositories/TenantProfileRepository.java |   105 +
 .../profile-service/profile-user-core/pom.xml      |    90 +
 .../exceptions/UserProfileRegistryException.java   |    28 +
 .../core/repositories/UserProfileRepository.java   |   129 +
 .../core/utils/UserProfileCatalogDBInitConfig.java |    42 +
 .../core/utils/UserProfileCatalogJDBCConfig.java   |    52 +
 .../user-profile-catalog-derby.sql                 |   163 +
 .../user-profile-catalog-mysql.sql                 |   163 +
 .../core/repositories/WorkspaceRepositoryTest.java |   176 +
 pom.xml                                            |    47 +
 .../custos-apis/airavata_errors.thrift             |    47 +
 .../custos-apis/security_model.thrift              |    15 +
 .../group_manager_model.thrift                     |    55 +
 .../tenant_profile_model.thrift                    |    75 +
 .../user_profile_model.thrift                      |   230 +
 .../workspace_model.thrift                         |    60 +
 thrift-interfaces/generate-thrift-stubs.sh         |   347 +
 .../group-manager/group-manager-cpi.thrift         |    98 +
 .../group-manager/group_manager_cpi_errors.thrift  |    33 +
 .../iam-admin-services-cpi.thrift                  |   127 +
 .../iam_admin_services_cpi_errors.thrift           |    33 +
 .../profile-service/profile-service-cpi.thrift     |    35 +
 .../profile-tenant/profile-tenant-cpi.thrift       |    80 +
 .../profile_tenant_cpi_errors.thrift               |    33 +
 .../profile-user/profile-user-cpi.thrift           |    86 +
 .../profile-user/profile_user_cpi_errors.thrift    |    33 +
 127 files changed, 82948 insertions(+)

diff --git a/custos-commons/pom.xml b/custos-commons/pom.xml
new file mode 100644
index 0000000..a1a9e93
--- /dev/null
+++ b/custos-commons/pom.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>custos</artifactId>
+        <groupId>org.apache.custos</groupId>
+        <version>1.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    
+    <groupId>org.apache.custos</groupId>
+    <artifactId>custos-commons</artifactId>
+    <version>${parent.version}</version>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.thrift</groupId>
+            <artifactId>libthrift</artifactId>
+            <version>${thrift.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.openjpa</groupId>
+            <artifactId>openjpa</artifactId>
+            <version>${openjpa.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/custos-commons/src/main/java/org/apache/custos/commons/exceptions/ApplicationSettingsException.java b/custos-commons/src/main/java/org/apache/custos/commons/exceptions/ApplicationSettingsException.java
new file mode 100644
index 0000000..25f6260
--- /dev/null
+++ b/custos-commons/src/main/java/org/apache/custos/commons/exceptions/ApplicationSettingsException.java
@@ -0,0 +1,14 @@
+package org.apache.custos.commons.exceptions;
+
+public class ApplicationSettingsException extends CustosException {
+
+	private static final long serialVersionUID = -4901850535475160411L;
+
+	public ApplicationSettingsException(String message) {
+		super(message);
+	}
+	
+	public ApplicationSettingsException(String message, Throwable e) {
+		super(message, e);
+	}
+}
diff --git a/custos-commons/src/main/java/org/apache/custos/commons/exceptions/CustosException.java b/custos-commons/src/main/java/org/apache/custos/commons/exceptions/CustosException.java
new file mode 100644
index 0000000..1675205
--- /dev/null
+++ b/custos-commons/src/main/java/org/apache/custos/commons/exceptions/CustosException.java
@@ -0,0 +1,35 @@
+/**
+ *
+ * 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 org.apache.custos.commons.exceptions;
+
+public class CustosException extends Exception {
+
+	private static final long serialVersionUID = -5665822765183116821L;
+	public CustosException() {
+	}
+	
+	public CustosException(String message, Throwable e) {
+		super(message,e);
+	}
+	
+	public CustosException(String message) {
+		super(message);
+	}
+}
diff --git a/custos-commons/src/main/java/org/apache/custos/commons/exceptions/CustosSecurityException.java b/custos-commons/src/main/java/org/apache/custos/commons/exceptions/CustosSecurityException.java
new file mode 100644
index 0000000..67cef95
--- /dev/null
+++ b/custos-commons/src/main/java/org/apache/custos/commons/exceptions/CustosSecurityException.java
@@ -0,0 +1,39 @@
+/**
+ *
+ * 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 org.apache.custos.commons.exceptions;
+
+public class CustosSecurityException extends Exception {
+    public CustosSecurityException(String message) {
+        super(message);
+    }
+
+    public CustosSecurityException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public CustosSecurityException() {
+        super();
+    }
+
+    public CustosSecurityException(Throwable cause) {
+        super(cause);
+    }
+
+}
diff --git a/custos-commons/src/main/java/org/apache/custos/commons/model/error/AuthenticationException.java b/custos-commons/src/main/java/org/apache/custos/commons/model/error/AuthenticationException.java
new file mode 100644
index 0000000..07ca704
--- /dev/null
+++ b/custos-commons/src/main/java/org/apache/custos/commons/model/error/AuthenticationException.java
@@ -0,0 +1,385 @@
+/**
+ * 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.
+ */
+
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+package org.apache.custos.commons.model.error;
+
+@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
+/**
+ * This exception is thrown for invalid sshKeyAuthentication requests.
+ * 
+ *  message: contains the cause of the authorization failure.
+ */
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)")
+public class AuthenticationException extends org.apache.thrift.TException implements org.apache.thrift.TBase<AuthenticationException, AuthenticationException._Fields>, java.io.Serializable, Cloneable, Comparable<AuthenticationException> {
+  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("AuthenticationException");
+
+  private static final org.apache.thrift.protocol.TField MESSAGE_FIELD_DESC = new org.apache.thrift.protocol.TField("message", org.apache.thrift.protocol.TType.STRING, (short)1);
+
+  private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new AuthenticationExceptionStandardSchemeFactory();
+  private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new AuthenticationExceptionTupleSchemeFactory();
+
+  private String message; // required
+
+  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+  public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+    MESSAGE((short)1, "message");
+
+    private static final java.util.Map<String, _Fields> byName = new java.util.HashMap<String, _Fields>();
+
+    static {
+      for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
+        byName.put(field.getFieldName(), field);
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, or null if its not found.
+     */
+    public static _Fields findByThriftId(int fieldId) {
+      switch(fieldId) {
+        case 1: // MESSAGE
+          return MESSAGE;
+        default:
+          return null;
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, throwing an exception
+     * if it is not found.
+     */
+    public static _Fields findByThriftIdOrThrow(int fieldId) {
+      _Fields fields = findByThriftId(fieldId);
+      if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+      return fields;
+    }
+
+    /**
+     * Find the _Fields constant that matches name, or null if its not found.
+     */
+    public static _Fields findByName(String name) {
+      return byName.get(name);
+    }
+
+    private final short _thriftId;
+    private final String _fieldName;
+
+    _Fields(short thriftId, String fieldName) {
+      _thriftId = thriftId;
+      _fieldName = fieldName;
+    }
+
+    public short getThriftFieldId() {
+      return _thriftId;
+    }
+
+    public String getFieldName() {
+      return _fieldName;
+    }
+  }
+
+  // isset id assignments
+  public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+  static {
+    java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+    tmpMap.put(_Fields.MESSAGE, new org.apache.thrift.meta_data.FieldMetaData("message", org.apache.thrift.TFieldRequirementType.REQUIRED,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
+    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(AuthenticationException.class, metaDataMap);
+  }
+
+  public AuthenticationException() {
+  }
+
+  public AuthenticationException(
+    String message)
+  {
+    this();
+    this.message = message;
+  }
+
+  /**
+   * Performs a deep copy on <i>other</i>.
+   */
+  public AuthenticationException(AuthenticationException other) {
+    if (other.isSetMessage()) {
+      this.message = other.message;
+    }
+  }
+
+  public AuthenticationException deepCopy() {
+    return new AuthenticationException(this);
+  }
+
+  @Override
+  public void clear() {
+    this.message = null;
+  }
+
+  public String getMessage() {
+    return this.message;
+  }
+
+  public void setMessage(String message) {
+    this.message = message;
+  }
+
+  public void unsetMessage() {
+    this.message = null;
+  }
+
+  /** Returns true if field message is set (has been assigned a value) and false otherwise */
+  public boolean isSetMessage() {
+    return this.message != null;
+  }
+
+  public void setMessageIsSet(boolean value) {
+    if (!value) {
+      this.message = null;
+    }
+  }
+
+  public void setFieldValue(_Fields field, Object value) {
+    switch (field) {
+    case MESSAGE:
+      if (value == null) {
+        unsetMessage();
+      } else {
+        setMessage((String)value);
+      }
+      break;
+
+    }
+  }
+
+  public Object getFieldValue(_Fields field) {
+    switch (field) {
+    case MESSAGE:
+      return getMessage();
+
+    }
+    throw new IllegalStateException();
+  }
+
+  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+  public boolean isSet(_Fields field) {
+    if (field == null) {
+      throw new IllegalArgumentException();
+    }
+
+    switch (field) {
+    case MESSAGE:
+      return isSetMessage();
+    }
+    throw new IllegalStateException();
+  }
+
+  @Override
+  public boolean equals(Object that) {
+    if (that == null)
+      return false;
+    if (that instanceof AuthenticationException)
+      return this.equals((AuthenticationException)that);
+    return false;
+  }
+
+  public boolean equals(AuthenticationException that) {
+    if (that == null)
+      return false;
+    if (this == that)
+      return true;
+
+    boolean this_present_message = true && this.isSetMessage();
+    boolean that_present_message = true && that.isSetMessage();
+    if (this_present_message || that_present_message) {
+      if (!(this_present_message && that_present_message))
+        return false;
+      if (!this.message.equals(that.message))
+        return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int hashCode = 1;
+
+    hashCode = hashCode * 8191 + ((isSetMessage()) ? 131071 : 524287);
+    if (isSetMessage())
+      hashCode = hashCode * 8191 + message.hashCode();
+
+    return hashCode;
+  }
+
+  @Override
+  public int compareTo(AuthenticationException other) {
+    if (!getClass().equals(other.getClass())) {
+      return getClass().getName().compareTo(other.getClass().getName());
+    }
+
+    int lastComparison = 0;
+
+    lastComparison = Boolean.valueOf(isSetMessage()).compareTo(other.isSetMessage());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetMessage()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.message, other.message);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    return 0;
+  }
+
+  public _Fields fieldForId(int fieldId) {
+    return _Fields.findByThriftId(fieldId);
+  }
+
+  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+    scheme(iprot).read(iprot, this);
+  }
+
+  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+    scheme(oprot).write(oprot, this);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("AuthenticationException(");
+    boolean first = true;
+
+    sb.append("message:");
+    if (this.message == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.message);
+    }
+    first = false;
+    sb.append(")");
+    return sb.toString();
+  }
+
+  public void validate() throws org.apache.thrift.TException {
+    // check for required fields
+    if (!isSetMessage()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'message' is unset! Struct:" + toString());
+    }
+
+    // check for sub-struct validity
+  }
+
+  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+    try {
+      write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+    try {
+      read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private static class AuthenticationExceptionStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
+    public AuthenticationExceptionStandardScheme getScheme() {
+      return new AuthenticationExceptionStandardScheme();
+    }
+  }
+
+  private static class AuthenticationExceptionStandardScheme extends org.apache.thrift.scheme.StandardScheme<AuthenticationException> {
+
+    public void read(org.apache.thrift.protocol.TProtocol iprot, AuthenticationException struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TField schemeField;
+      iprot.readStructBegin();
+      while (true)
+      {
+        schemeField = iprot.readFieldBegin();
+        if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
+          break;
+        }
+        switch (schemeField.id) {
+          case 1: // MESSAGE
+            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+              struct.message = iprot.readString();
+              struct.setMessageIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          default:
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+      struct.validate();
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot, AuthenticationException struct) throws org.apache.thrift.TException {
+      struct.validate();
+
+      oprot.writeStructBegin(STRUCT_DESC);
+      if (struct.message != null) {
+        oprot.writeFieldBegin(MESSAGE_FIELD_DESC);
+        oprot.writeString(struct.message);
+        oprot.writeFieldEnd();
+      }
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+  }
+
+  private static class AuthenticationExceptionTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
+    public AuthenticationExceptionTupleScheme getScheme() {
+      return new AuthenticationExceptionTupleScheme();
+    }
+  }
+
+  private static class AuthenticationExceptionTupleScheme extends org.apache.thrift.scheme.TupleScheme<AuthenticationException> {
+
+    @Override
+    public void write(org.apache.thrift.protocol.TProtocol prot, AuthenticationException struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
+      oprot.writeString(struct.message);
+    }
+
+    @Override
+    public void read(org.apache.thrift.protocol.TProtocol prot, AuthenticationException struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
+      struct.message = iprot.readString();
+      struct.setMessageIsSet(true);
+    }
+  }
+
+  private static <S extends org.apache.thrift.scheme.IScheme> S scheme(org.apache.thrift.protocol.TProtocol proto) {
+    return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme();
+  }
+}
+
diff --git a/custos-commons/src/main/java/org/apache/custos/commons/model/error/AuthorizationException.java b/custos-commons/src/main/java/org/apache/custos/commons/model/error/AuthorizationException.java
new file mode 100644
index 0000000..dc84307
--- /dev/null
+++ b/custos-commons/src/main/java/org/apache/custos/commons/model/error/AuthorizationException.java
@@ -0,0 +1,385 @@
+/**
+ * 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.
+ */
+
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+package org.apache.custos.commons.model.error;
+
+@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
+/**
+ * This exception is thrown for invalid authorization requests such user does not have acces to an aplication or resource.
+ * 
+ *  message: contains the authorization failure message
+ */
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)")
+public class AuthorizationException extends org.apache.thrift.TException implements org.apache.thrift.TBase<AuthorizationException, AuthorizationException._Fields>, java.io.Serializable, Cloneable, Comparable<AuthorizationException> {
+  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("AuthorizationException");
+
+  private static final org.apache.thrift.protocol.TField MESSAGE_FIELD_DESC = new org.apache.thrift.protocol.TField("message", org.apache.thrift.protocol.TType.STRING, (short)1);
+
+  private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new AuthorizationExceptionStandardSchemeFactory();
+  private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new AuthorizationExceptionTupleSchemeFactory();
+
+  private String message; // required
+
+  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+  public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+    MESSAGE((short)1, "message");
+
+    private static final java.util.Map<String, _Fields> byName = new java.util.HashMap<String, _Fields>();
+
+    static {
+      for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
+        byName.put(field.getFieldName(), field);
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, or null if its not found.
+     */
+    public static _Fields findByThriftId(int fieldId) {
+      switch(fieldId) {
+        case 1: // MESSAGE
+          return MESSAGE;
+        default:
+          return null;
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, throwing an exception
+     * if it is not found.
+     */
+    public static _Fields findByThriftIdOrThrow(int fieldId) {
+      _Fields fields = findByThriftId(fieldId);
+      if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+      return fields;
+    }
+
+    /**
+     * Find the _Fields constant that matches name, or null if its not found.
+     */
+    public static _Fields findByName(String name) {
+      return byName.get(name);
+    }
+
+    private final short _thriftId;
+    private final String _fieldName;
+
+    _Fields(short thriftId, String fieldName) {
+      _thriftId = thriftId;
+      _fieldName = fieldName;
+    }
+
+    public short getThriftFieldId() {
+      return _thriftId;
+    }
+
+    public String getFieldName() {
+      return _fieldName;
+    }
+  }
+
+  // isset id assignments
+  public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+  static {
+    java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+    tmpMap.put(_Fields.MESSAGE, new org.apache.thrift.meta_data.FieldMetaData("message", org.apache.thrift.TFieldRequirementType.REQUIRED,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
+    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(AuthorizationException.class, metaDataMap);
+  }
+
+  public AuthorizationException() {
+  }
+
+  public AuthorizationException(
+    String message)
+  {
+    this();
+    this.message = message;
+  }
+
+  /**
+   * Performs a deep copy on <i>other</i>.
+   */
+  public AuthorizationException(AuthorizationException other) {
+    if (other.isSetMessage()) {
+      this.message = other.message;
+    }
+  }
+
+  public AuthorizationException deepCopy() {
+    return new AuthorizationException(this);
+  }
+
+  @Override
+  public void clear() {
+    this.message = null;
+  }
+
+  public String getMessage() {
+    return this.message;
+  }
+
+  public void setMessage(String message) {
+    this.message = message;
+  }
+
+  public void unsetMessage() {
+    this.message = null;
+  }
+
+  /** Returns true if field message is set (has been assigned a value) and false otherwise */
+  public boolean isSetMessage() {
+    return this.message != null;
+  }
+
+  public void setMessageIsSet(boolean value) {
+    if (!value) {
+      this.message = null;
+    }
+  }
+
+  public void setFieldValue(_Fields field, Object value) {
+    switch (field) {
+    case MESSAGE:
+      if (value == null) {
+        unsetMessage();
+      } else {
+        setMessage((String)value);
+      }
+      break;
+
+    }
+  }
+
+  public Object getFieldValue(_Fields field) {
+    switch (field) {
+    case MESSAGE:
+      return getMessage();
+
+    }
+    throw new IllegalStateException();
+  }
+
+  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+  public boolean isSet(_Fields field) {
+    if (field == null) {
+      throw new IllegalArgumentException();
+    }
+
+    switch (field) {
+    case MESSAGE:
+      return isSetMessage();
+    }
+    throw new IllegalStateException();
+  }
+
+  @Override
+  public boolean equals(Object that) {
+    if (that == null)
+      return false;
+    if (that instanceof AuthorizationException)
+      return this.equals((AuthorizationException)that);
+    return false;
+  }
+
+  public boolean equals(AuthorizationException that) {
+    if (that == null)
+      return false;
+    if (this == that)
+      return true;
+
+    boolean this_present_message = true && this.isSetMessage();
+    boolean that_present_message = true && that.isSetMessage();
+    if (this_present_message || that_present_message) {
+      if (!(this_present_message && that_present_message))
+        return false;
+      if (!this.message.equals(that.message))
+        return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int hashCode = 1;
+
+    hashCode = hashCode * 8191 + ((isSetMessage()) ? 131071 : 524287);
+    if (isSetMessage())
+      hashCode = hashCode * 8191 + message.hashCode();
+
+    return hashCode;
+  }
+
+  @Override
+  public int compareTo(AuthorizationException other) {
+    if (!getClass().equals(other.getClass())) {
+      return getClass().getName().compareTo(other.getClass().getName());
+    }
+
+    int lastComparison = 0;
+
+    lastComparison = Boolean.valueOf(isSetMessage()).compareTo(other.isSetMessage());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetMessage()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.message, other.message);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    return 0;
+  }
+
+  public _Fields fieldForId(int fieldId) {
+    return _Fields.findByThriftId(fieldId);
+  }
+
+  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+    scheme(iprot).read(iprot, this);
+  }
+
+  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+    scheme(oprot).write(oprot, this);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("AuthorizationException(");
+    boolean first = true;
+
+    sb.append("message:");
+    if (this.message == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.message);
+    }
+    first = false;
+    sb.append(")");
+    return sb.toString();
+  }
+
+  public void validate() throws org.apache.thrift.TException {
+    // check for required fields
+    if (!isSetMessage()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'message' is unset! Struct:" + toString());
+    }
+
+    // check for sub-struct validity
+  }
+
+  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+    try {
+      write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+    try {
+      read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private static class AuthorizationExceptionStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
+    public AuthorizationExceptionStandardScheme getScheme() {
+      return new AuthorizationExceptionStandardScheme();
+    }
+  }
+
+  private static class AuthorizationExceptionStandardScheme extends org.apache.thrift.scheme.StandardScheme<AuthorizationException> {
+
+    public void read(org.apache.thrift.protocol.TProtocol iprot, AuthorizationException struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TField schemeField;
+      iprot.readStructBegin();
+      while (true)
+      {
+        schemeField = iprot.readFieldBegin();
+        if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
+          break;
+        }
+        switch (schemeField.id) {
+          case 1: // MESSAGE
+            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+              struct.message = iprot.readString();
+              struct.setMessageIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          default:
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+      struct.validate();
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot, AuthorizationException struct) throws org.apache.thrift.TException {
+      struct.validate();
+
+      oprot.writeStructBegin(STRUCT_DESC);
+      if (struct.message != null) {
+        oprot.writeFieldBegin(MESSAGE_FIELD_DESC);
+        oprot.writeString(struct.message);
+        oprot.writeFieldEnd();
+      }
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+  }
+
+  private static class AuthorizationExceptionTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
+    public AuthorizationExceptionTupleScheme getScheme() {
+      return new AuthorizationExceptionTupleScheme();
+    }
+  }
+
+  private static class AuthorizationExceptionTupleScheme extends org.apache.thrift.scheme.TupleScheme<AuthorizationException> {
+
+    @Override
+    public void write(org.apache.thrift.protocol.TProtocol prot, AuthorizationException struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
+      oprot.writeString(struct.message);
+    }
+
+    @Override
+    public void read(org.apache.thrift.protocol.TProtocol prot, AuthorizationException struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
+      struct.message = iprot.readString();
+      struct.setMessageIsSet(true);
+    }
+  }
+
+  private static <S extends org.apache.thrift.scheme.IScheme> S scheme(org.apache.thrift.protocol.TProtocol proto) {
+    return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme();
+  }
+}
+
diff --git a/custos-commons/src/main/java/org/apache/custos/commons/utils/ApplicationSettings.java b/custos-commons/src/main/java/org/apache/custos/commons/utils/ApplicationSettings.java
new file mode 100644
index 0000000..9f0ad54
--- /dev/null
+++ b/custos-commons/src/main/java/org/apache/custos/commons/utils/ApplicationSettings.java
@@ -0,0 +1,185 @@
+package org.apache.custos.commons.utils;
+
+import org.apache.custos.commons.exceptions.ApplicationSettingsException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+import java.util.regex.Pattern;
+
+public class ApplicationSettings {
+    protected static ApplicationSettings INSTANCE;
+    private Exception propertyLoadException;
+    public static final String SERVER_PROPERTIES="custos-server.properties";
+    public static final String CUSTOS_CONFIG_DIR = "custos.config.dir";
+    public static String ADDITIONAL_SETTINGS_FILES = "external.settings";
+    protected static final String TRUST_STORE_PATH="trust.store";
+    protected static final String TRUST_STORE_PASSWORD="trust.store.password";
+    private final static Logger logger = LoggerFactory.getLogger(ApplicationSettings.class);
+    protected Properties properties = new Properties();
+    // Profile Service Constants
+    public static final String PROFILE_SERVICE_SERVER_HOST = "profile.service.server.host";
+    public static final String PROFILE_SERVICE_SERVER_PORT = "profile.service.server.port";
+
+    // Iam Server Constants
+    public static final String IAM_SERVER_URL = "iam.server.url";
+    public static final String IAM_SERVER_SUPER_ADMIN_USERNAME = "iam.server.super.admin.username";
+    public static final String IAM_SERVER_SUPER_ADMIN_PASSWORD = "iam.server.super.admin.password";
+    {
+        loadProperties();
+    }
+    private void loadProperties() {
+        URL url = getPropertyFileURL();
+        try {
+            properties.load(url.openStream());
+            logger.info("Settings loaded from "+url.toString());
+            URL[] externalSettingsFileURLs = getExternalSettingsFileURLs();
+            for (URL externalSettings : externalSettingsFileURLs) {
+                mergeSettingsImpl(externalSettings.openStream());
+                logger.info("External settings merged from "+url.toString());
+            }
+        } catch (Exception e) {
+            propertyLoadException=e;
+        }
+    }
+    public void mergeSettingsImpl(InputStream stream) throws IOException {
+        Properties tmpProp = new Properties();
+        tmpProp.load(stream);
+        properties.putAll(tmpProp);
+    }
+    private URL[] getExternalSettingsFileURLs(){
+        try {
+            List<URL> externalSettingsFileURLs=new ArrayList<URL>();
+            String externalSettingsFileNames = getSettingImpl(ADDITIONAL_SETTINGS_FILES);
+            String[] externalSettingFiles = externalSettingsFileNames.split(",");
+            for (String externalSettingFile : externalSettingFiles) {
+                URL externalSettingFileURL = ApplicationSettings.loadFile(externalSettingFile);
+                if (externalSettingFileURL==null){
+                    logger.warn("Could not file external settings file "+externalSettingFile);
+                }else{
+                    externalSettingsFileURLs.add(externalSettingFileURL);
+                }
+            }
+            return externalSettingsFileURLs.toArray(new URL[]{});
+        } catch (ApplicationSettingsException e) {
+            return new URL[]{};
+        }
+    }
+    private URL getPropertyFileURL() {
+        return ApplicationSettings.loadFile(SERVER_PROPERTIES);
+    }
+    private static URL loadFile(String fileName) {
+
+        if(System.getProperty(CUSTOS_CONFIG_DIR) != null) {
+            String custosConfigDir = System.getProperty(CUSTOS_CONFIG_DIR);
+            try {
+                custosConfigDir = custosConfigDir.endsWith(File.separator) ? custosConfigDir : custosConfigDir + File.separator;
+                String filePath = custosConfigDir + fileName;
+
+                File asfile  = new File(filePath);
+                if (asfile.exists()) {
+
+                    return asfile.toURI().toURL();
+                }
+            } catch (MalformedURLException e) {
+                logger.error("Error parsing the file from custos.config.dir", custosConfigDir);
+            }
+        }
+
+        return ApplicationSettings.class.getClassLoader().getResource(fileName);
+
+    }
+    protected static ApplicationSettings getInstance(){
+        if (INSTANCE==null){
+            INSTANCE=new ApplicationSettings();
+        }
+        return INSTANCE;
+    }
+    public static String getSetting(String key) throws ApplicationSettingsException {
+        return getInstance().getSettingImpl(key);
+    }
+    public static String getSetting(String key, String defaultValue) {
+        return getInstance().getSettingImpl(key,defaultValue);
+
+    }
+    public static void setSetting(String key, String value) throws ApplicationSettingsException{
+        getInstance().properties.setProperty(key, value);
+        getInstance().saveProperties();
+    }
+    private void saveProperties() throws ApplicationSettingsException{
+        URL url = getPropertyFileURL();
+        if (url.getProtocol().equalsIgnoreCase("file")){
+            try {
+                properties.store(new FileOutputStream(url.getPath()), Calendar.getInstance().toString());
+            } catch (Exception e) {
+                throw new ApplicationSettingsException(url.getPath(), e);
+            }
+        }else{
+            logger.warn("Properties cannot be updated to location "+url.toString());
+        }
+    }
+    private String getSettingImpl(String key, String defaultValue){
+        try {
+            return getSettingImpl(key);
+        } catch (ApplicationSettingsException e) {
+            //we'll ignore this error since a default value is provided
+        }
+        return defaultValue;
+    }
+    private String getSettingImpl(String key) throws ApplicationSettingsException{
+        String rawValue=null;
+        if (System.getProperties().containsKey(key)){
+            rawValue=System.getProperties().getProperty(key);
+        }else{
+            validateSuccessfulPropertyFileLoad();
+            if (properties.containsKey(key)){
+                rawValue=properties.getProperty(key);
+            }else{
+                throw new ApplicationSettingsException(key);
+            }
+        }
+        return deriveAbsoluteValueImpl(rawValue);
+    }
+    private String deriveAbsoluteValueImpl(String property){
+        if (property!=null){
+            Map<Integer, String> containedParameters = StringUtil.getContainedParameters(property);
+            List<String> parametersAlreadyProcessed=new ArrayList<String>();
+            for (String parameter : containedParameters.values()) {
+                if (!parametersAlreadyProcessed.contains(parameter)) {
+                    String parameterName = parameter.substring(2,parameter.length() - 1);
+                    String parameterValue = getSetting(parameterName,parameter);
+                    property = property.replaceAll(Pattern.quote(parameter), parameterValue);
+                    parametersAlreadyProcessed.add(parameter);
+                }
+            }
+        }
+        return property;
+    }
+    private void validateSuccessfulPropertyFileLoad() throws ApplicationSettingsException{
+        if (propertyLoadException!=null){
+            throw new ApplicationSettingsException(propertyLoadException.getMessage(), propertyLoadException);
+        }
+    }
+    public static String getTrustStorePath() throws ApplicationSettingsException {
+        return getSetting(TRUST_STORE_PATH);
+    }
+    public static String getTrustStorePassword() throws ApplicationSettingsException {
+        return getSetting(TRUST_STORE_PASSWORD);
+    }
+    public static String getIamServerUrl() throws ApplicationSettingsException {
+        return getSetting(ServerSettings.IAM_SERVER_URL);
+    }
+    public static String getProfileServiceServerHost() throws ApplicationSettingsException {
+        return getSetting(ServerSettings.PROFILE_SERVICE_SERVER_HOST);
+    }
+
+    public static String getProfileServiceServerPort() throws ApplicationSettingsException {
+        return getSetting(ServerSettings.PROFILE_SERVICE_SERVER_PORT);
+    }
+}
diff --git a/custos-commons/src/main/java/org/apache/custos/commons/utils/Constants.java b/custos-commons/src/main/java/org/apache/custos/commons/utils/Constants.java
new file mode 100644
index 0000000..1325f46
--- /dev/null
+++ b/custos-commons/src/main/java/org/apache/custos/commons/utils/Constants.java
@@ -0,0 +1,41 @@
+/**
+ *
+ * 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 org.apache.custos.commons.utils;
+
+/**
+ * Constants used in Custos should go here.
+ */
+public final class Constants {
+    public static final String IN_MEMORY_CACHE_SIZE = "in.memory.cache.size";
+    public static final String AUTHZ_CACHE_MANAGER_CLASS = "authz.cache.manager.class";
+    public static final String API_METHOD_NAME = "api.method.name";
+    public static final String IS_API_SECURED = "api.secured";
+    public static final String AUTHORIZATION_POLICY_NAME = "authorization.policy";
+    public static final String SECURITY_MANAGER_CLASS = "security.manager.class";
+    public static final String AUTHZ_CACHE_ENABLED = "authz.cache.enabled";
+
+    //Names of the attributes that could be passed in the AuthzToken's claims map.
+    public static final String USER_NAME = "userName";
+    public static final String GATEWAY_ID = "gatewayID";
+    public static final String IDENTITY_SERVER_TENANT = "identityServerTenant";
+
+    //constants in XACML authorization response.
+    public static final String PERMIT = "Permit";
+}
diff --git a/custos-commons/src/main/java/org/apache/custos/commons/utils/CustosUtils.java b/custos-commons/src/main/java/org/apache/custos/commons/utils/CustosUtils.java
new file mode 100644
index 0000000..35cfe54
--- /dev/null
+++ b/custos-commons/src/main/java/org/apache/custos/commons/utils/CustosUtils.java
@@ -0,0 +1,45 @@
+/**
+ *
+ * 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 org.apache.custos.commons.utils;
+
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.UUID;
+
+public class CustosUtils {
+
+    public static Timestamp getCurrentTimestamp() {
+        Calendar calender = Calendar.getInstance();
+//        java.util.Date d = calender.getTimeInMillis();
+        return new Timestamp(calender.getTimeInMillis());
+    }
+
+    public static Timestamp getTime(long time) {
+        if (time == 0 || time < 0){
+            return getCurrentTimestamp();
+        }
+        return new Timestamp(time);
+    }
+
+    public static String getId (String name){
+        String id = name.trim().replaceAll("\\s|\\.", "_");
+        return id + "_" + UUID.randomUUID();
+    }
+}
diff --git a/custos-commons/src/main/java/org/apache/custos/commons/utils/DBInitConfig.java b/custos-commons/src/main/java/org/apache/custos/commons/utils/DBInitConfig.java
new file mode 100644
index 0000000..123541a
--- /dev/null
+++ b/custos-commons/src/main/java/org/apache/custos/commons/utils/DBInitConfig.java
@@ -0,0 +1,33 @@
+/*
+ * 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 org.apache.custos.commons.utils;
+
+public interface DBInitConfig {
+    JDBCConfig getJDBCConfig();
+
+    String getDBInitScriptPrefix();
+
+    String getCheckTableName();
+
+    default void postInit() {
+
+    }
+}
diff --git a/custos-commons/src/main/java/org/apache/custos/commons/utils/JDBCConfig.java b/custos-commons/src/main/java/org/apache/custos/commons/utils/JDBCConfig.java
new file mode 100644
index 0000000..5cdb0ec
--- /dev/null
+++ b/custos-commons/src/main/java/org/apache/custos/commons/utils/JDBCConfig.java
@@ -0,0 +1,29 @@
+/*
+ * 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 org.apache.custos.commons.utils;
+
+public interface JDBCConfig {
+    String getURL();
+    String getDriver();
+    String getUser();
+    String getPassword();
+    String getValidationQuery();
+}
diff --git a/custos-commons/src/main/java/org/apache/custos/commons/utils/JPAUtils.java b/custos-commons/src/main/java/org/apache/custos/commons/utils/JPAUtils.java
new file mode 100644
index 0000000..9e02ce7
--- /dev/null
+++ b/custos-commons/src/main/java/org/apache/custos/commons/utils/JPAUtils.java
@@ -0,0 +1,67 @@
+package org.apache.custos.commons.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * JPAUtils
+ */
+public class JPAUtils {
+
+    private final static Logger logger = LoggerFactory.getLogger(JPAUtils.class);
+    private final static Map<String, String> DEFAULT_ENTITY_MANAGER_FACTORY_PROPERTIES;
+    static {
+        Map<String, String> properties = new HashMap<String, String>();
+        properties.put("openjpa.ConnectionDriverName", "org.apache.commons.dbcp.BasicDataSource");
+        properties.put("openjpa.DynamicEnhancementAgent", "true");
+        properties.put("openjpa.RuntimeUnenhancedClasses", "unsupported");
+        properties.put("openjpa.RemoteCommitProvider", "sjvm");
+        properties.put("openjpa.Log", "DefaultLevel=INFO, Runtime=INFO, Tool=INFO, SQL=INFO");
+        properties.put("openjpa.jdbc.SynchronizeMappings", "validate");
+        properties.put("openjpa.jdbc.QuerySQLCache", "false");
+        properties.put("openjpa.DetachState", "all");
+        properties.put("openjpa.ConnectionFactoryProperties", "PrettyPrint=true, PrettyPrintLineLength=72,"
+                + " PrintParameters=true, MaxActive=10, MaxIdle=5, MinIdle=2, MaxWait=31536000,  autoReconnect=true");
+        DEFAULT_ENTITY_MANAGER_FACTORY_PROPERTIES = properties;
+    }
+
+    /**
+     * Create an {@link EntityManagerFactory} with the default settings.
+     * @param persistenceUnitName
+     * @param jdbcConfig
+     * @return {@link EntityManagerFactory}
+     */
+    public static EntityManagerFactory getEntityManagerFactory(String persistenceUnitName, JDBCConfig jdbcConfig){
+
+        return getEntityManagerFactory(persistenceUnitName, jdbcConfig, Collections.emptyMap());
+    }
+
+    /**
+     * Create an {@link EntityManagerFactory}. The given properties will override the default properties.
+     * @param persistenceUnitName
+     * @param jdbcConfig
+     * @param properties
+     * @return {@link EntityManagerFactory}
+     */
+    public static EntityManagerFactory getEntityManagerFactory(String persistenceUnitName, JDBCConfig jdbcConfig, Map<String, String> properties) {
+
+        Map<String, String> finalProperties = new HashMap<>(DEFAULT_ENTITY_MANAGER_FACTORY_PROPERTIES);
+        finalProperties.putAll(createConnectionProperties(jdbcConfig));
+        finalProperties.putAll(properties);
+        return Persistence.createEntityManagerFactory(persistenceUnitName, finalProperties);
+    }
+
+    private static Map<String, String> createConnectionProperties(JDBCConfig jdbcConfig) {
+        String connectionProperties = "DriverClassName=" + jdbcConfig.getDriver() + "," + "Url=" + jdbcConfig.getURL()
+                + "?autoReconnect=true," + "Username=" + jdbcConfig.getUser() + "," + "Password="
+                + jdbcConfig.getPassword() + ",validationQuery=" + jdbcConfig.getValidationQuery();
+        logger.debug("Connection properties={}", connectionProperties);
+        return Collections.singletonMap("openjpa.ConnectionProperties", connectionProperties);
+    }
+}
diff --git a/custos-commons/src/main/java/org/apache/custos/commons/utils/KeyStorePasswordCallback.java b/custos-commons/src/main/java/org/apache/custos/commons/utils/KeyStorePasswordCallback.java
new file mode 100644
index 0000000..f08f6c2
--- /dev/null
+++ b/custos-commons/src/main/java/org/apache/custos/commons/utils/KeyStorePasswordCallback.java
@@ -0,0 +1,69 @@
+/**
+ *
+ * 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 org.apache.custos.commons.utils;/*
+ *
+ * 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.
+ *
+ */
+
+/**
+ * User: AmilaJ (amilaj@apache.org)
+ * Date: 10/11/13
+ * Time: 11:30 AM
+ */
+
+/**
+ * An interface to get keystore password in a form of a callback.
+ */
+public interface KeyStorePasswordCallback {
+
+    /**
+     * Caller should implement the interface. Should return the password for
+     * the keystore. This should return the keystore password. i.e. password used to open the keystore.
+     * Instead of the actual file.
+     * @return The password to open the keystore.
+     */
+    char[] getStorePassword() throws RuntimeException;
+
+    /**
+     * Caller should implement the interface. Should return the pass phrase for
+     * the secret key.
+     * Instead of the actual file.
+     * @param keyAlias The alias of the key
+     * @return The pass phrase for the secret key.
+     */
+    char[] getSecretKeyPassPhrase(String keyAlias);
+
+}
diff --git a/custos-commons/src/main/java/org/apache/custos/commons/utils/SecurityUtil.java b/custos-commons/src/main/java/org/apache/custos/commons/utils/SecurityUtil.java
new file mode 100644
index 0000000..9a8cec3
--- /dev/null
+++ b/custos-commons/src/main/java/org/apache/custos/commons/utils/SecurityUtil.java
@@ -0,0 +1,192 @@
+/**
+ *
+ * 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 org.apache.custos.commons.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import java.io.*;
+import java.security.*;
+import java.security.cert.CertificateException;
+
+/**
+ * Class which includes security utilities.
+ */
+public class SecurityUtil {
+
+    public static final String PASSWORD_HASH_METHOD_PLAINTEXT = "PLAINTEXT";
+
+    public static final String CHARSET_ENCODING = "UTF-8";
+    public static final String ENCRYPTION_ALGORITHM = "AES";
+    public static final String PADDING_MECHANISM = "AES/CBC/PKCS5Padding";
+
+    private static final Logger logger = LoggerFactory.getLogger(SecurityUtil.class);
+
+    /**
+     * Creates a hash of given string with the given hash algorithm.
+     * 
+     * @param stringToDigest
+     *            The string to digest.
+     * @param digestingAlgorithm
+     *            Hash algorithm.
+     * @return The digested string.
+     * @throws NoSuchAlgorithmException
+     *             If given hash algorithm doesnt exists.
+     */
+    public static String digestString(String stringToDigest, String digestingAlgorithm) throws NoSuchAlgorithmException {
+
+        if (digestingAlgorithm == null || digestingAlgorithm.equals(PASSWORD_HASH_METHOD_PLAINTEXT)) {
+            return stringToDigest;
+        }
+
+        MessageDigest messageDigest = MessageDigest.getInstance(digestingAlgorithm);
+        try {
+            return new String(messageDigest.digest(stringToDigest.getBytes("UTF-8")));
+        } catch (UnsupportedEncodingException e) {
+            logger.error("Error encoding password string when creating digest", e);
+            throw new RuntimeException("Error encoding password string when creating digest", e);
+        }
+    }
+
+    /**
+     * Sets the truststore for application. Useful when communicating over HTTPS.
+     * 
+     * @param trustStoreFilePath
+     *            Where trust store is located.
+     * @param trustStorePassword
+     *            The trust store password.
+     */
+    public static void setTrustStoreParameters(String trustStoreFilePath, String trustStorePassword) {
+
+        if (System.getProperty("javax.net.ssl.trustStrore") == null) {
+            logger.info("Setting Java trust store to " + trustStoreFilePath);
+            System.setProperty("javax.net.ssl.trustStrore", trustStoreFilePath);
+        }
+
+        if (System.getProperty("javax.net.ssl.trustStorePassword") == null) {
+            System.setProperty("javax.net.ssl.trustStorePassword", trustStoreFilePath);
+        }
+
+    }
+
+    public static byte[] encryptString(String keyStorePath, String keyAlias,
+                                 KeyStorePasswordCallback passwordCallback, String value)
+            throws GeneralSecurityException, IOException {
+        return encrypt(keyStorePath, keyAlias, passwordCallback, value.getBytes(CHARSET_ENCODING));
+    }
+
+    public static byte[] encrypt(String keyStorePath, String keyAlias,
+                                 KeyStorePasswordCallback passwordCallback, byte[] value)
+            throws GeneralSecurityException, IOException {
+
+        Key secretKey = getSymmetricKey(keyStorePath, keyAlias, passwordCallback);
+
+        Cipher cipher = Cipher.getInstance(PADDING_MECHANISM);
+        cipher.init(Cipher.ENCRYPT_MODE, secretKey,
+                new IvParameterSpec(new byte[16]));
+        return cipher.doFinal(value);
+    }
+
+    private static Key getSymmetricKey(String keyStorePath, String keyAlias,
+                                       KeyStorePasswordCallback passwordCallback)
+            throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException,
+            UnrecoverableKeyException {
+
+        KeyStore ks = SecurityUtil.loadKeyStore(keyStorePath, "jceks", passwordCallback);
+
+        if (ks == null) {
+            throw new IOException("Unable to load Java keystore " + keyStorePath);
+        }
+
+        return ks.getKey(keyAlias, passwordCallback.getSecretKeyPassPhrase(keyAlias));
+
+    }
+
+    public static byte[] decrypt(String keyStorePath, String keyAlias,
+                                 KeyStorePasswordCallback passwordCallback, byte[] encrypted)
+            throws GeneralSecurityException, IOException {
+
+        Key secretKey = getSymmetricKey(keyStorePath, keyAlias, passwordCallback);
+
+        Cipher cipher = Cipher.getInstance(PADDING_MECHANISM);
+        cipher.init(Cipher.DECRYPT_MODE, secretKey,
+                new IvParameterSpec(new byte[16]));
+
+        return cipher.doFinal(encrypted);
+    }
+
+    public static String decryptString(String keyStorePath, String keyAlias,
+                                       KeyStorePasswordCallback passwordCallback, byte[] encrypted)
+            throws GeneralSecurityException, IOException {
+
+        byte[] decrypted = decrypt(keyStorePath, keyAlias, passwordCallback, encrypted);
+        return new String(decrypted, CHARSET_ENCODING);
+    }
+
+    public static KeyStore loadKeyStore(String keyStoreFilePath, String keyStoreType,
+                                        KeyStorePasswordCallback passwordCallback)
+            throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
+
+        File keystoreFile = new File(keyStoreFilePath);
+
+        InputStream is;
+        if (keystoreFile.exists()) {
+            logger.debug("Loading keystore file from path " + keyStoreFilePath);
+            is = new FileInputStream(keyStoreFilePath);
+        } else {
+            logger.debug("Trying to load keystore file form class path " + keyStoreFilePath);
+            is = SecurityUtil.class.getClassLoader().getResourceAsStream(keyStoreFilePath);
+            if (is != null) {
+                logger.debug("Trust store file was loaded form class path " + keyStoreFilePath);
+            }
+        }
+
+        if (is == null) {
+            throw new KeyStoreException("Could not find a keystore file in path " + keyStoreFilePath);
+        }
+
+        try {
+            return loadKeyStore(is, keyStoreType, passwordCallback);
+        } finally {
+            is.close();
+        }
+    }
+
+    public static KeyStore loadKeyStore(InputStream inputStream, String keyStoreType,
+                                        KeyStorePasswordCallback passwordCallback)
+            throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
+
+        if (keyStoreType == null) {
+            keyStoreType = KeyStore.getDefaultType();
+        }
+
+        KeyStore ks = KeyStore.getInstance(keyStoreType);
+        ks.load(inputStream, passwordCallback.getStorePassword());
+
+        return ks;
+    }
+
+
+
+
+
+}
diff --git a/custos-commons/src/main/java/org/apache/custos/commons/utils/ServerSettings.java b/custos-commons/src/main/java/org/apache/custos/commons/utils/ServerSettings.java
new file mode 100644
index 0000000..2ead9e3
--- /dev/null
+++ b/custos-commons/src/main/java/org/apache/custos/commons/utils/ServerSettings.java
@@ -0,0 +1,56 @@
+/**
+ *
+ * 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 org.apache.custos.commons.utils;
+
+import org.apache.custos.commons.exceptions.ApplicationSettingsException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ServerSettings extends ApplicationSettings {
+
+    private static final Logger log = LoggerFactory.getLogger(ServerSettings.class);
+    public static int getCacheSize() throws ApplicationSettingsException {
+        return Integer.valueOf(getSetting(Constants.IN_MEMORY_CACHE_SIZE));
+    }
+    public static String getAuthzCacheManagerClassName() throws ApplicationSettingsException {
+        return getSetting(Constants.AUTHZ_CACHE_MANAGER_CLASS);
+    }
+    public static boolean isAPISecured() throws ApplicationSettingsException {
+        return Boolean.valueOf(getSetting(Constants.IS_API_SECURED));
+    }
+    public static String getAuthorizationPoliyName() throws ApplicationSettingsException {
+        return getSetting(Constants.AUTHORIZATION_POLICY_NAME);
+    }
+    public static String getSecurityManagerClassName() throws ApplicationSettingsException {
+        return getSetting(Constants.SECURITY_MANAGER_CLASS);
+    }
+    public static String getRemoteIDPServiceUrl() throws ApplicationSettingsException {
+        return getSetting(ServerSettings.IAM_SERVER_URL);
+    }
+    public static boolean isAuthzCacheEnabled() throws ApplicationSettingsException {
+        return Boolean.valueOf(getSetting(Constants.AUTHZ_CACHE_ENABLED));
+    }
+    public static String getIamServerSuperAdminUsername() throws ApplicationSettingsException {
+        return getSetting(ServerSettings.IAM_SERVER_SUPER_ADMIN_USERNAME);
+    }
+    public static String getIamServerSuperAdminPassword() throws ApplicationSettingsException {
+        return getSetting(ServerSettings.IAM_SERVER_SUPER_ADMIN_PASSWORD);
+    }
+}
diff --git a/custos-commons/src/main/java/org/apache/custos/commons/utils/StringUtil.java b/custos-commons/src/main/java/org/apache/custos/commons/utils/StringUtil.java
new file mode 100644
index 0000000..1306dbf
--- /dev/null
+++ b/custos-commons/src/main/java/org/apache/custos/commons/utils/StringUtil.java
@@ -0,0 +1,43 @@
+/**
+ *
+ * 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 org.apache.custos.commons.utils;
+
+import java.util.*;
+
+public class StringUtil {
+	
+	public static Map<Integer, String> getContainedParameters(String s) {
+		Map<Integer,String> parameterMap=new HashMap<Integer,String>();
+		int i=0;
+		for(i=0;i<s.length();i++){
+			if (s.charAt(i)=='$' && (i+1)<s.length() && s.charAt(i+1)=='{'){
+				int i2=s.indexOf('{', i+2);
+				int e=s.indexOf('}', i+2);
+				if (e!=-1){
+					if (i2==-1 || e<i2){
+						parameterMap.put(i, s.substring(i,e+1));
+						i=e;
+					}
+				}
+			}
+		}
+		return parameterMap;
+	}
+}
\ No newline at end of file
diff --git a/custos-services/custos-security-service/pom.xml b/custos-services/custos-security-service/pom.xml
new file mode 100644
index 0000000..fe585cd
--- /dev/null
+++ b/custos-services/custos-security-service/pom.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>custos-services</artifactId>
+        <groupId>org.apache.custos</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>custos-security-service</artifactId>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.custos</groupId>
+            <artifactId>custos-commons</artifactId>
+            <version>${parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.wso2.carbon</groupId>
+            <artifactId>org.wso2.carbon.identity.oauth.stub</artifactId>
+            <version>4.2.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.axis2.wso2</groupId>
+            <artifactId>axis2</artifactId>
+            <version>1.6.1.wso2v4</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.4</version>
+        </dependency>
+        <dependency>
+            <groupId>org.wso2.carbon</groupId>
+            <artifactId>org.wso2.carbon.utils</artifactId>
+            <version>4.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.wso2.carbon</groupId>
+            <artifactId>org.wso2.carbon.identity.entitlement.stub</artifactId>
+            <version>4.2.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.wso2.carbon</groupId>
+            <artifactId>org.wso2.carbon.identity.entitlement.common</artifactId>
+            <version>4.2.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+            <version>4.0</version>
+        </dependency>
+        <dependency>
+            <groupId>aopalliance</groupId>
+            <artifactId>aopalliance</artifactId>
+            <version>1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.oltu.oauth2</groupId>
+            <artifactId>org.apache.oltu.oauth2.client</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <version>1.9.13</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCache.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCache.java
new file mode 100644
index 0000000..5be2f04
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCache.java
@@ -0,0 +1,61 @@
+/*
+ *
+ * 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 org.apache.custos.security.authzcache;
+
+import org.apache.custos.commons.exceptions.ApplicationSettingsException;
+import org.apache.custos.commons.utils.ServerSettings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class AuthzCache extends LinkedHashMap<AuthzCacheIndex, AuthzCacheEntry> {
+
+    private static int MAX_SIZE;
+    private final static Logger logger = LoggerFactory.getLogger(AuthzCache.class);
+
+    private static AuthzCache authzCache = null;
+
+    public static AuthzCache getInstance() throws ApplicationSettingsException {
+        if (authzCache == null) {
+            synchronized (AuthzCache.class) {
+                if (authzCache == null) {
+                    authzCache = new AuthzCache(ServerSettings.getCacheSize());
+                }
+            }
+        }
+        return authzCache;
+    }
+
+    private AuthzCache(int initialCapacity) {
+        super(initialCapacity);
+        MAX_SIZE = initialCapacity;
+    }
+
+    @Override
+    protected boolean removeEldestEntry(Map.Entry<AuthzCacheIndex, AuthzCacheEntry> eldest) {
+        if (size() > MAX_SIZE) {
+            logger.info("Authz cache max size exceeded. Removing the old entries.");
+        }
+        return size() > MAX_SIZE;
+    }
+}
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCacheEntry.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCacheEntry.java
new file mode 100644
index 0000000..967ea02
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCacheEntry.java
@@ -0,0 +1,63 @@
+/*
+ *
+ * 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 org.apache.custos.security.authzcache;
+
+/**
+ * Cache entry in the default authorization cache.
+ */
+public class AuthzCacheEntry {
+    //authorization decision for the authorization request associated with this cache entry.
+    private boolean decision;
+    //time to live value for the access token in seconds.
+    private long expiryTime;
+    //time stamp in milli seconds at the time this entry is put into the cache
+    private long entryTimestamp;
+
+    public AuthzCacheEntry(boolean decision, long expiryTime, long entryTimestamp) {
+        this.decision = decision;
+        this.expiryTime = expiryTime;
+        this.entryTimestamp = entryTimestamp;
+    }
+
+    public long getEntryTimestamp() {
+        return entryTimestamp;
+    }
+
+    public void setEntryTimestamp(long entryTimestamp) {
+        this.entryTimestamp = entryTimestamp;
+    }
+
+    public long getExpiryTime() {
+        return expiryTime;
+    }
+
+    public void setExpiryTime(long timestamp) {
+        this.expiryTime = timestamp;
+    }
+
+    public boolean getDecision() {
+        return decision;
+    }
+
+    public void setDecision(boolean decision) {
+        this.decision = decision;
+    }
+}
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCacheIndex.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCacheIndex.java
new file mode 100644
index 0000000..90c6f9d
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCacheIndex.java
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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 org.apache.custos.security.authzcache;
+
+/**
+ * Cache index of the default authorization cache.
+ */
+public class AuthzCacheIndex {
+
+    private String subject;
+    private String oauthAccessToken;
+//    private String action;
+    private String gatewayId;
+
+    public AuthzCacheIndex(String userName, String gatewayId, String accessToken) {
+        this.subject = userName;
+        this.oauthAccessToken = accessToken;
+//        this.action = actionString;
+        this.gatewayId = gatewayId;
+    }
+
+    public String getSubject() {
+        return subject;
+    }
+
+    public void setSubject(String subject) {
+        this.subject = subject;
+    }
+
+//    public String getAction() {
+//        return action;
+//    }
+//
+//    public void setAction(String action) {
+//        this.action = action;
+//    }
+
+    public String getOauthAccessToken() {
+        return oauthAccessToken;
+    }
+
+    public void setOauthAccessToken(String oauthAccessToken) {
+        this.oauthAccessToken = oauthAccessToken;
+    }
+
+    public String getGatewayId() {
+        return gatewayId;
+    }
+
+    public void setGatewayId(String gatewayId) {
+        this.gatewayId = gatewayId;
+    }
+
+    /*Equals and hash code methods are overridden since this is being used as an index of a map and that containsKey method
+        * should return true if the values of two index objects are equal.*/
+    @Override
+    public boolean equals(Object other) {
+        if (other == null || other.getClass() != getClass()) {
+            return false;
+        }
+        return ((this.getSubject().equals(((AuthzCacheIndex) other).getSubject()))
+                && (this.getGatewayId().equals(((AuthzCacheIndex) other).getGatewayId()))
+                && (this.getOauthAccessToken().equals(((AuthzCacheIndex) other).getOauthAccessToken())));
+                //&& (this.getAction().equals(((AuthzCacheIndex) other).getAction())));
+    }
+
+    @Override
+    public int hashCode() {
+        return this.getSubject().hashCode() + this.getOauthAccessToken().hashCode() + this.getGatewayId().hashCode();
+                //+ this.getAction().hashCode();
+    }
+}
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCacheManager.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCacheManager.java
new file mode 100644
index 0000000..8c39897
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCacheManager.java
@@ -0,0 +1,80 @@
+/*
+ *
+ * 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 org.apache.custos.security.authzcache;
+
+import org.apache.custos.commons.exceptions.CustosSecurityException;
+
+/**
+ * This is the interface through which security manager accesses the underlying caching implementation
+ * See the DefaultAuthzCacheManager.java for an example implementation of this interface.
+ */
+public interface AuthzCacheManager {
+    /**
+     * Returns the status of the cache w.r.t the given authorization request which is encapsulated in
+     * the AuthzCacheIndex.
+     *
+     * @param authzCacheIndex
+     * @return
+     */
+    public AuthzCachedStatus getAuthzCachedStatus(AuthzCacheIndex authzCacheIndex) throws CustosSecurityException;
+
+    /**
+     * Add to cache the authorization decision pertaining to a given authorization request.
+     *
+     * @param authzCacheIndex
+     * @param authzCacheEntry
+     * @throws CustosSecurityException
+     */
+    public void addToAuthzCache(AuthzCacheIndex authzCacheIndex, AuthzCacheEntry authzCacheEntry) throws CustosSecurityException;
+
+    /**
+     * Check if a valid decision is cached for a given authorization request.
+     *
+     * @param authzCacheIndex
+     * @return
+     */
+    public boolean isAuthzDecisionCached(AuthzCacheIndex authzCacheIndex) throws CustosSecurityException;
+
+    /**
+     * Returns the AuthzCacheEntry for a given authorization request.
+     *
+     * @param authzCacheIndex
+     * @return
+     * @throws CustosSecurityException
+     */
+    public AuthzCacheEntry getAuthzCacheEntry(AuthzCacheIndex authzCacheIndex) throws CustosSecurityException;
+
+    /**
+     * Removes the authorization cache entry for a given authorization request.
+     *
+     * @param authzCacheIndex
+     * @throws CustosSecurityException
+     */
+    public void removeAuthzCacheEntry(AuthzCacheIndex authzCacheIndex) throws CustosSecurityException;
+
+    /**
+     * Clear the authorization cache.
+     *
+     * @return
+     */
+    public void clearCache() throws CustosSecurityException;
+
+}
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCacheManagerFactory.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCacheManagerFactory.java
new file mode 100644
index 0000000..d9a8d68
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCacheManagerFactory.java
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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 org.apache.custos.security.authzcache;
+
+import org.apache.custos.commons.exceptions.ApplicationSettingsException;
+import org.apache.custos.commons.exceptions.CustosSecurityException;
+import org.apache.custos.commons.utils.ServerSettings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This initializes the AuthzCacheManager implementation to be used as defined by the configuration.
+ */
+public class AuthzCacheManagerFactory {
+    private final static Logger logger = LoggerFactory.getLogger(AuthzCacheManagerFactory.class);
+
+    public static AuthzCacheManager getAuthzCacheManager() throws CustosSecurityException {
+        try {
+            Class authzCacheManagerImpl = Class.forName(ServerSettings.getAuthzCacheManagerClassName());
+            AuthzCacheManager authzCacheManager  = (AuthzCacheManager) authzCacheManagerImpl.newInstance();
+            return  authzCacheManager;
+        } catch (ClassNotFoundException e) {
+            String error = "Authorization Cache Manager class could not be found.";
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException(error);
+        } catch (ApplicationSettingsException e) {
+            String error = "Error in reading the configuration related to Authorization Cache Manager class.";
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException(error);
+        } catch (InstantiationException e) {
+            String error = "Error in instantiating the Authorization Cache Manager class.";
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException(error);
+        } catch (IllegalAccessException e) {
+            String error = "Error in instantiating the Authorization Cache Manager class.";
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException(error);
+
+        }
+    }
+
+}
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCachedStatus.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCachedStatus.java
new file mode 100644
index 0000000..182f072
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/AuthzCachedStatus.java
@@ -0,0 +1,34 @@
+/*
+ *
+ * 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 org.apache.custos.security.authzcache;
+
+/**
+ * This enum defines the status of the authorization cache returned by the authorization cache manager
+ * when an authorization status is checked against an authorization request.
+ */
+public enum AuthzCachedStatus {
+    /*Authorization decision is cached for the given authrization request and the decision authorizes the request.*/
+    AUTHORIZED,
+    /*Authorization decision is cached for the given authorization request and the decision denies authorization.*/
+    NOT_AUTHORIZED,
+    /*Authorization decision is not either cached or the cached entry is invalid such that re-authorization is needed.*/
+    NOT_CACHED
+}
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/DefaultAuthzCacheManager.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/DefaultAuthzCacheManager.java
new file mode 100644
index 0000000..7b8754a
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/authzcache/DefaultAuthzCacheManager.java
@@ -0,0 +1,106 @@
+/*
+ *
+ * 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 org.apache.custos.security.authzcache;
+
+import org.apache.custos.commons.exceptions.ApplicationSettingsException;
+import org.apache.custos.commons.exceptions.CustosSecurityException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DefaultAuthzCacheManager implements AuthzCacheManager {
+
+    private final static Logger logger = LoggerFactory.getLogger(DefaultAuthzCacheManager.class);
+
+    @Override
+    public AuthzCachedStatus getAuthzCachedStatus(AuthzCacheIndex authzCacheIndex) throws CustosSecurityException {
+        if (isAuthzDecisionCached(authzCacheIndex)) {
+            AuthzCacheEntry cacheEntry = getAuthzCacheEntry(authzCacheIndex);
+            long expiryTime = cacheEntry.getExpiryTime();
+            long currentTime = System.currentTimeMillis();
+            long timePassed = (currentTime - cacheEntry.getEntryTimestamp()) / 1000;
+            if (expiryTime > timePassed) {
+                //access token is still valid. Hence, return the cached decision
+                if (cacheEntry.getDecision()) {
+                    return AuthzCachedStatus.AUTHORIZED;
+                } else {
+                    return AuthzCachedStatus.NOT_AUTHORIZED;
+                }
+            } else {
+                //access token has been expired. Hence, remove the entry and return.
+                removeAuthzCacheEntry(authzCacheIndex);
+                return AuthzCachedStatus.NOT_CACHED;
+            }
+        } else {
+            return AuthzCachedStatus.NOT_CACHED;
+        }
+    }
+
+    @Override
+    public void addToAuthzCache(AuthzCacheIndex authzCacheIndex, AuthzCacheEntry authzCacheEntry) throws CustosSecurityException {
+        try {
+            AuthzCache.getInstance().put(authzCacheIndex, authzCacheEntry);
+        } catch (ApplicationSettingsException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in obtaining the authorization cache instance.");
+        }
+    }
+
+    @Override
+    public boolean isAuthzDecisionCached(AuthzCacheIndex authzCacheIndex) throws CustosSecurityException {
+        try {
+            return AuthzCache.getInstance().containsKey(authzCacheIndex);
+        } catch (ApplicationSettingsException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in obtaining the authorization cache instance.");
+        }
+    }
+
+    @Override
+    public AuthzCacheEntry getAuthzCacheEntry(AuthzCacheIndex authzCacheIndex) throws CustosSecurityException {
+        try {
+            return AuthzCache.getInstance().get(authzCacheIndex);
+        } catch (ApplicationSettingsException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in obtaining the authorization cache instance.");
+        }
+    }
+
+    @Override
+    public void removeAuthzCacheEntry(AuthzCacheIndex authzCacheIndex) throws CustosSecurityException {
+        try {
+            AuthzCache.getInstance().remove(authzCacheIndex);
+        } catch (ApplicationSettingsException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in obtaining the authorization cache instance.");
+        }
+    }
+
+    @Override
+    public void clearCache() throws CustosSecurityException {
+        try {
+            AuthzCache.getInstance().clear();
+        } catch (ApplicationSettingsException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in obtaining the authorization cache instance.");
+
+        }
+    }
+}
\ No newline at end of file
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/manager/CustosSecurityManager.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/manager/CustosSecurityManager.java
new file mode 100644
index 0000000..afeb1d2
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/manager/CustosSecurityManager.java
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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 org.apache.custos.security.manager;
+
+import org.apache.custos.commons.exceptions.CustosSecurityException;
+import org.apache.custos.security.model.AuthzToken;
+
+import java.util.Map;
+
+public interface CustosSecurityManager {
+    /**
+     * Implement this method in your SecurityManager to perform necessary initializations at the server startup.
+     * @throws CustosSecurityException
+     */
+    public void initializeSecurityInfra() throws CustosSecurityException;
+
+    /**
+     * Implement this method with the user authentication/authorization logic in your SecurityManager.
+     * @param authzToken : this includes OAuth token and user's claims
+     * @param metaData : this includes other meta data needed for security enforcements.
+     * @return
+     * @throws CustosSecurityException
+     */
+    public boolean isUserAuthorized(AuthzToken authzToken, Map<String, String> metaData) throws CustosSecurityException;
+
+
+    /**
+     * Return an AuthzToken that has the appropriate access to manage user's in the IAM service.
+     * @param gatewayId
+     * @return
+     * @throws CustosSecurityException
+     */
+    public AuthzToken getUserManagementServiceAccountAuthzToken(String gatewayId, String clientId, String clientSecret) throws CustosSecurityException;
+
+    /**
+     * Get OpenID Connect user profile information from the given AuthzToken.
+     * @param authzToken
+     * @return
+     * @throws CustosSecurityException
+     */
+    public UserInfo getUserInfoFromAuthzToken(AuthzToken authzToken, String identityServerRealm) throws CustosSecurityException;
+}
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/manager/IdentityContext.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/manager/IdentityContext.java
new file mode 100644
index 0000000..f5648ba
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/manager/IdentityContext.java
@@ -0,0 +1,44 @@
+/*
+ *
+ * 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 org.apache.custos.security.manager;
+
+import org.apache.custos.security.model.AuthzToken;
+
+/**
+ * This provides a thread local container for AuthzToken through out the execution of a particular thread.
+ */
+public class IdentityContext {
+    private static ThreadLocal authzTokenContainer = new ThreadLocal();
+
+    public static void set(AuthzToken authzToken){
+        authzTokenContainer.set(authzToken);
+    }
+
+    public static void unset(){
+        authzTokenContainer.remove();
+    }
+
+    public static AuthzToken get(){
+        return (AuthzToken) authzTokenContainer.get();
+    }
+
+}
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/manager/KeyCloakSecurityManager.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/manager/KeyCloakSecurityManager.java
new file mode 100644
index 0000000..ea1cbb2
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/manager/KeyCloakSecurityManager.java
@@ -0,0 +1,537 @@
+/*
+ *
+ * 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 org.apache.custos.security.manager;
+
+
+import org.apache.custos.commons.exceptions.ApplicationSettingsException;
+import org.apache.custos.commons.exceptions.CustosSecurityException;
+import org.apache.custos.commons.utils.Constants;
+import org.apache.custos.commons.utils.ServerSettings;
+import org.apache.custos.security.authzcache.*;
+import org.apache.custos.security.model.AuthzToken;
+import org.apache.custos.security.utils.TrustStoreManager;
+import org.apache.http.Consts;
+import org.apache.http.HttpHeaders;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+import java.util.Map;
+
+public class KeyCloakSecurityManager implements CustosSecurityManager {
+    private final static Logger logger = LoggerFactory.getLogger(KeyCloakSecurityManager.class);
+
+//    private HashMap<String, String> rolePermissionConfig = new HashMap<>();
+//
+//    // Methods that users user to manage their user resource profile
+//    private final static String USER_RESOURCE_PROFILE_USER_METHODS = "/airavata/registerUserResourceProfile|/airavata/getUserResourceProfile" +
+//            "|/airavata/updateUserResourceProfile|/airavata/deleteUserResourceProfile|/airavata/addUserComputeResourcePreference" +
+//            "|/airavata/addUserStoragePreference|/airavata/getUserComputeResourcePreference|/airavata/getUserStoragePreference" +
+//            "|/airavata/getAllUserComputeResourcePreferences|/airavata/getAllUserStoragePreferences" +
+//            "|/airavata/updateUserComputeResourcePreference|/airavata/updateUserStoragePreference" +
+//            "|/airavata/deleteUserComputeResourcePreference|/airavata/deleteUserStoragePreference" +
+//            "|/airavata/generateAndRegisterSSHKeys|/airavata/getAllCredentialSummaryForUsersInGateway" +
+//            "|/airavata/deleteSSHPubKey|/airavata/isUserResourceProfileExists";
+//    private final static String SHARING_RESOURCE_METHODS = "/airavata/shareResourceWithUsers|/airavata/revokeSharingOfResourceFromUsers" +
+//            "|/airavata/shareResourceWithGroups|/airavata/revokeSharingOfResourceFromGroups|/airavata/getAllAccessibleUsers" +
+//            "|/airavata/getAllAccessibleGroups|/airavata/userHasAccess|/airavata/getAllDirectlyAccessibleUsers" +
+//            "|/airavata/getAllDirectlyAccessibleGroups";
+//    private final static String SSH_ACCOUNT_PROVISIONER_METHODS =
+//            "/airavata/getSSHAccountProvisioners|/airavata/doesUserHaveSSHAccount|/airavata" +
+//                    "/setupUserComputeResourcePreferencesForSSH|" +
+//                    // getGatewayResourceProfile is needed to look up whether ssh account provisioning is
+//                    // configured for a gateway's compute resource preference
+//                    "/airavata/getGatewayResourceProfile";
+//    // These methods are protected by sharing registry authorization
+//    private final static String GROUP_RESOURCE_PROFILE_METHODS =
+//            "/airavata/createGroupResourceProfile|/airavata/updateGroupResourceProfile|/airavata/getGroupResourceProfile" +
+//                    "|/airavata/removeGroupResourceProfile|/airavata/getGroupResourceList|/airavata/removeGroupComputePrefs" +
+//                    "|/airavata/removeGroupComputeResourcePolicy|/airavata/removeGroupBatchQueueResourcePolicy" +
+//                    "|/airavata/getGroupComputeResourcePreference|/airavata/getGroupComputeResourcePolicy" +
+//                    "|/airavata/getBatchQueueResourcePolicy|/airavata/getGroupComputeResourcePrefList" +
+//                    "|/airavata/getGroupBatchQueueResourcePolicyList|/airavata/getGroupComputeResourcePolicyList";
+//    // These methods are protected by sharing registry authorization
+//    private final static String APPLICATION_DEPLOYMENT_METHODS =
+//            "/airavata/registerApplicationDeployment|/airavata/getApplicationDeployment|/airavata/updateApplicationDeployment" +
+//                    "|/airavata/deleteApplicationDeployment|/airavata/getAllApplicationDeployments|/airavata/getAccessibleApplicationDeployments" +
+//                    "|/airavata/getApplicationDeploymentsForAppModuleAndGroupResourceProfile";
+//    private final static String APPLICATION_MODULE_METHODS = "/airavata/getAccessibleAppModules";
+//    private final static String CREDENTIAL_TOKEN_METHODS = "/airavata/getCredentialSummary|/airavata/getAllCredentialSummaries|/airavata/generateAndRegisterSSHKeys|/airavata/registerPwdCredential|/airavata/deleteSSHPubKey|/airavata/deletePWDCredential";
+//    // Misc. other methods needed for group based authorization
+//    private final static String GROUP_BASED_AUTH_METHODS = "/airavata/getGatewayGroups";
+//
+//    private RegistryService.Client registryServiceClient = null;
+//    private SharingRegistryService.Client sharingRegistryServiceClient = null;
+//
+//    private static class GatewayGroupMembership {
+//        private boolean inAdminsGroup = false;
+//        private boolean inReadOnlyAdminsGroup = false;
+//
+//        public boolean isInAdminsGroup() {
+//            return inAdminsGroup;
+//        }
+//
+//        public void setInAdminsGroup(boolean inAdminsGroup) {
+//            this.inAdminsGroup = inAdminsGroup;
+//        }
+//
+//        public boolean isInReadOnlyAdminsGroup() {
+//            return inReadOnlyAdminsGroup;
+//        }
+//
+//        public void setInReadOnlyAdminsGroup(boolean inReadOnlyAdminsGroup) {
+//            this.inReadOnlyAdminsGroup = inReadOnlyAdminsGroup;
+//        }
+//    }
+
+    public KeyCloakSecurityManager() throws CustosSecurityException {
+//        rolePermissionConfig.put("admin", "/airavata/.*");
+//        rolePermissionConfig.put("gateway-provider", "/airavata/.*");
+//        rolePermissionConfig.put("admin-read-only", "/airavata/getSSHPubKey|/airavata/getAllGatewaySSHPubKeys" +
+//                "|/airavata/getAllGatewayPWDCredentials|/airavata/getApplicationModule|/airavata/getAllAppModules" +
+//                "|/airavata/getApplicationDeployment|/airavata/getAllApplicationDeployments|/airavata/getAppModuleDeployedResources" +
+//                "|/airavata/getStorageResource|/airavata/getAllStorageResourceNames|/airavata/getSCPDataMovement" +
+//                "|/airavata/getUnicoreDataMovement|/airavata/getGridFTPDataMovement|/airavata/getResourceJobManager" +
+//                "|/airavata/deleteResourceJobManager|/airavata/getGatewayResourceProfile|/airavata/getGatewayComputeResourcePreference" +
+//                "|/airavata/getGatewayStoragePreference|/airavata/getAllGatewayComputeResourcePreferences" +
+//                "|/airavata/getAllGatewayStoragePreferences|/airavata/getAllGatewayResourceProfiles|/airavata/getAPIVersion" +
+//                "|/airavata/getNotification|/airavata/getAllNotifications|/airavata/createProject|/airavata/updateProject" +
+//                "|/airavata/getProject|/airavata/deleteProject|/airavata/getUserProjects|/airavata/searchProjectsByProjectName" +
+//                "|/airavata/searchProjectsByProjectDesc|/airavata/searchExperimentsByName|/airavata/searchExperimentsByDesc" +
+//                "|/airavata/searchExperimentsByApplication|/airavata/searchExperimentsByStatus|/airavata/searchExperimentsByCreationTime" +
+//                "|/airavata/searchExperiments|/airavata/getExperimentStatistics|/airavata/getExperimentsInProject" +
+//                "|/airavata/getUserExperiments|/airavata/createExperiment|/airavata/deleteExperiment|/airavata/getExperiment" +
+//                "|/airavata/getDetailedExperimentTree|/airavata/updateExperiment|/airavata/updateExperimentConfiguration" +
+//                "|/airavata/updateResourceScheduleing|/airavata/validateExperiment|/airavata/launchExperiment" +
+//                "|/airavata/getExperimentStatus|/airavata/getExperimentOutputs|/airavata/getIntermediateOutputs" +
+//                "|/airavata/getJobStatuses|/airavata/getJobDetails|/airavata/cloneExperiment|/airavata/terminateExperiment" +
+//                "|/airavata/getApplicationInterface|/airavata/getAllApplicationInterfaceNames|/airavata/getAllApplicationInterfaces" +
+//                "|/airavata/getApplicationInputs|/airavata/getApplicationOutputs|/airavata/getAvailableAppInterfaceComputeResources" +
+//                "|/airavata/getComputeResource|/airavata/getAllComputeResourceNames|/airavata/getWorkflow|/airavata/getWorkflowTemplateId" +
+//                "|/airavata/isWorkflowExistWithName|/airavata/registerDataProduct|/airavata/getDataProduct|/airavata/registerReplicaLocation" +
+//                "|/airavata/getParentDataProduct|/airavata/getChildDataProducts|/airavata/getAllAccessibleUsers" +
+//                "|/airavata/getExperimentByAdmin|/airavata/cloneExperimentByAdmin|/airavata/getAllCredentialSummaryForGateway" +
+//                "|" + USER_RESOURCE_PROFILE_USER_METHODS + "|/airavata/getAllUserResourceProfiles" +
+//                "|" + SHARING_RESOURCE_METHODS + "|/airavata/getGateway|" + SSH_ACCOUNT_PROVISIONER_METHODS + "|" + GROUP_RESOURCE_PROFILE_METHODS +
+//                "|" + APPLICATION_DEPLOYMENT_METHODS + "|" + GROUP_BASED_AUTH_METHODS + "|" + APPLICATION_MODULE_METHODS +
+//                "|" + CREDENTIAL_TOKEN_METHODS);
+//        rolePermissionConfig.put("gateway-user", "/airavata/getAPIVersion|/airavata/getNotification|/airavata/getAllNotifications|" +
+//                "/airavata/createProject|/airavata/updateProject|/airavata/getProject|/airavata/deleteProject|/airavata/getUserProjects|" +
+//                "/airavata/searchProjectsByProjectName|/airavata/searchProjectsByProjectDesc|/airavata/searchExperimentsByName|" +
+//                "/airavata/searchExperimentsByDesc|/airavata/searchExperimentsByApplication|/airavata/searchExperimentsByStatus|" +
+//                "/airavata/searchExperimentsByCreationTime|/airavata/searchExperiments|/airavata/getExperimentStatistics|" +
+//                "/airavata/getExperimentsInProject|/airavata/getUserExperiments|/airavata/createExperiment|/airavata/deleteExperiment|" +
+//                "/airavata/getExperiment|/airavata/getDetailedExperimentTree|/airavata/updateExperiment|/airavata/updateExperimentConfiguration|" +
+//                "/airavata/updateResourceScheduleing|/airavata/validateExperiment|/airavata/launchExperiment|/airavata/getExperimentStatus|" +
+//                "/airavata/getExperimentOutputs|/airavata/getIntermediateOutputs|/airavata/getJobStatuses|/airavata/getJobDetails|" +
+//                "/airavata/cloneExperiment|/airavata/terminateExperiment|/airavata/getApplicationInterface|/airavata/getAllApplicationInterfaceNames|" +
+//                "/airavata/getAllApplicationInterfaces|/airavata/getApplicationInputs|/airavata/getApplicationOutputs|" +
+//                "/airavata/getAvailableAppInterfaceComputeResources|/airavata/getComputeResource|/airavata/getAllComputeResourceNames|" +
+//                "/airavata/getWorkflow|/airavata/getWorkflowTemplateId|/airavata/isWorkflowExistWithName|/airavata/registerDataProduct|" +
+//                "/airavata/getDataProduct|/airavata/registerReplicaLocation|/airavata/getParentDataProduct|/airavata/getChildDataProducts|" +
+//                "/airavata/getAllAccessibleUsers|/airavata/getAllApplicationDeployments|/airavata/getAllAppModules|/airavata/getApplicationModule|" + USER_RESOURCE_PROFILE_USER_METHODS + "|" +
+//                SHARING_RESOURCE_METHODS + "|" + SSH_ACCOUNT_PROVISIONER_METHODS + "|" + GROUP_RESOURCE_PROFILE_METHODS +
+//                "|" + APPLICATION_DEPLOYMENT_METHODS + "|" + GROUP_BASED_AUTH_METHODS + "|" + APPLICATION_MODULE_METHODS +
+//                "|" + CREDENTIAL_TOKEN_METHODS);
+
+        initializeSecurityInfra();
+    }
+
+    /**
+     * Implement this method in your SecurityManager to perform necessary initializations at the server startup.
+     *
+     * @throws CustosSecurityException
+     */
+    @Override
+    public void initializeSecurityInfra() throws CustosSecurityException {
+        try {
+            //initialize SSL context with the trust store that contains the public cert of WSO2 Identity Server.
+            TrustStoreManager trustStoreManager = new TrustStoreManager();
+            trustStoreManager.initializeTrustStoreManager(ServerSettings.getTrustStorePath(),
+                    ServerSettings.getTrustStorePassword());
+        } catch (Exception e) {
+            throw new CustosSecurityException(e.getMessage(), e);
+        }
+
+    }
+
+    /**
+     * Implement this method with the user authentication/authorization logic in your SecurityManager.
+     *
+     * @param authzToken : this includes OAuth token and user's claims
+     * @param metaData   : this includes other meta data needed for security enforcements.
+     * @return
+     * @throws CustosSecurityException
+     */
+    @Override
+    public boolean isUserAuthorized(AuthzToken authzToken, Map<String, String> metaData) throws CustosSecurityException {
+        String subject = authzToken.getClaimsMap().get(Constants.USER_NAME);
+        String accessToken = authzToken.getAccessToken();
+        String gatewayId = authzToken.getClaimsMap().get(Constants.GATEWAY_ID);
+        String identityServerRealm = metaData.get(Constants.IDENTITY_SERVER_TENANT);
+        //String action = "/airavata/" + metaData.get(Constants.API_METHOD_NAME);
+        try {
+//            if (!ServerSettings.isAPISecured()) {
+//                return true;
+//            }
+//            initServiceClients();
+
+            if (ServerSettings.isAuthzCacheEnabled()) {
+                //obtain an instance of AuthzCacheManager implementation.
+                AuthzCacheManager authzCacheManager = AuthzCacheManagerFactory.getAuthzCacheManager();
+
+                //check in the cache
+                AuthzCachedStatus authzCachedStatus = authzCacheManager.getAuthzCachedStatus(
+                        new AuthzCacheIndex(subject, gatewayId, accessToken));
+
+                if (AuthzCachedStatus.AUTHORIZED.equals(authzCachedStatus)) {
+                    logger.debug("Authz decision for: (" + subject + ", " + accessToken + ") is retrieved from cache.");
+                    return true;
+                } else if (AuthzCachedStatus.NOT_AUTHORIZED.equals(authzCachedStatus)) {
+                    logger.debug("Authz decision for: (" + subject + ", " + accessToken + ") is retrieved from cache.");
+                    return false;
+                } else if (AuthzCachedStatus.NOT_CACHED.equals(authzCachedStatus)) {
+                    logger.debug("Authz decision for: (" + subject + ", " + accessToken + ") is not in the cache. " +
+                            "Generating decision based on group membership.");
+//                    GatewayGroupMembership gatewayGroupMembership = getGatewayGroupMembership(subject, accessToken, gatewayId);
+//                    boolean authorizationDecision = hasPermission(gatewayGroupMembership, action);
+                    boolean authorizationDecision = validateToken(subject, accessToken, gatewayId, identityServerRealm);
+                    //cache the authorization decision
+                    long currentTime = System.currentTimeMillis();
+                    //TODO get the actual token expiration time
+                    authzCacheManager.addToAuthzCache(new AuthzCacheIndex(subject, gatewayId, accessToken),
+                            new AuthzCacheEntry(authorizationDecision, currentTime + 1000 * 60 * 60, currentTime));
+                    return authorizationDecision;
+                } else {
+                    //undefined status returned from the authz cache manager
+                    throw new CustosSecurityException("Error in reading from the authorization cache.");
+                }
+            } else {
+//                GatewayGroupMembership gatewayGroupMembership = getGatewayGroupMembership(subject, accessToken, gatewayId);
+//                return hasPermission(gatewayGroupMembership, action);
+                return validateToken(subject, accessToken, gatewayId, identityServerRealm);
+            }
+
+        } catch (ApplicationSettingsException e) {
+            logger.error("Missing or invalid application setting.", e);
+            throw new CustosSecurityException(e.getMessage(), e);
+        } catch (Exception e) {
+            logger.error("Error occurred while checking if user: " + subject + " is authorized in gateway: " + gatewayId, e);
+            throw new CustosSecurityException(e.getMessage(), e);
+        }
+//        } finally {
+//            closeServiceClients();
+//        }
+    }
+
+    @Override
+    public AuthzToken getUserManagementServiceAccountAuthzToken(String gatewayId, String clientId, String clientSecret) throws CustosSecurityException {
+        try {
+//            initServiceClients();
+//            Gateway gateway = registryServiceClient.getGateway(gatewayId);
+            String tokenURL = getTokenEndpoint(gatewayId);
+//            JSONObject clientCredentials = getClientCredentials(tokenURL, gateway.getOauthClientId(), gateway.getOauthClientSecret());
+            JSONObject clientCredentials = getClientCredentials(tokenURL, clientId, clientSecret);
+            String accessToken = clientCredentials.getString("access_token");
+            AuthzToken authzToken = new AuthzToken(accessToken);
+            authzToken.putToClaimsMap(Constants.GATEWAY_ID, gatewayId);
+            authzToken.putToClaimsMap(Constants.USER_NAME, clientId);
+            return authzToken;
+        } catch (Exception e) {
+            throw new CustosSecurityException(e);
+        }
+//        } finally {
+//            closeServiceClients();
+//        }
+    }
+
+    @Override
+    public UserInfo getUserInfoFromAuthzToken(AuthzToken authzToken, String identityServerRealm) throws CustosSecurityException {
+        try {
+//            initServiceClients();
+            final String gatewayId = authzToken.getClaimsMap().get(Constants.GATEWAY_ID);
+            final String token = authzToken.getAccessToken();
+            return getUserInfo(gatewayId, token, identityServerRealm);
+        } catch (Exception e) {
+            throw new CustosSecurityException(e);
+        }
+//        } finally {
+//            closeServiceClients();
+//        }
+    }
+
+    private UserInfo getUserInfo(String gatewayId, String token, String identityServerRealm) throws Exception {
+//        GatewayResourceProfile gwrp = registryServiceClient.getGatewayResourceProfile(gatewayId);
+//        String identityServerRealm = gwrp.getIdentityServerTenant();
+        String openIdConnectUrl = getOpenIDConfigurationUrl(identityServerRealm);
+        JSONObject openIdConnectConfig = new JSONObject(getFromUrl(openIdConnectUrl, null));
+        String userInfoEndPoint = openIdConnectConfig.getString("userinfo_endpoint");
+        JSONObject userInfo = new JSONObject(getFromUrl(userInfoEndPoint, token));
+        return new UserInfo()
+                .setSub(userInfo.getString("sub"))
+                .setFullName(userInfo.getString("name"))
+                .setFirstName(userInfo.getString("given_name"))
+                .setLastName(userInfo.getString("family_name"))
+                .setEmailAddress(userInfo.getString("email"))
+                .setUsername(userInfo.getString("preferred_username"));
+    }
+
+//    private GatewayGroupMembership getGatewayGroupMembership(String username, String token, String gatewayId) throws Exception {
+//        validateToken(username, token, gatewayId);
+//        GatewayGroups gatewayGroups = getGatewayGroups(gatewayId);
+//        List<UserGroup> userGroups = sharingRegistryServiceClient.getAllMemberGroupsForUser(gatewayId, username + "@" + gatewayId);
+//        List<String> userGroupIds = userGroups.stream().map(g -> g.getGroupId()).collect(Collectors.toList());
+//        GatewayGroupMembership gatewayGroupMembership = new GatewayGroupMembership();
+//        gatewayGroupMembership.setInAdminsGroup(userGroupIds.contains(gatewayGroups.getAdminsGroupId()));
+//        gatewayGroupMembership.setInReadOnlyAdminsGroup(userGroupIds.contains(gatewayGroups.getReadOnlyAdminsGroupId()));
+//        return gatewayGroupMembership;
+//    }
+
+//    private GatewayGroups getGatewayGroups(String gatewayId) throws Exception {
+//        if (registryServiceClient.isGatewayGroupsExists(gatewayId)) {
+//            return registryServiceClient.getGatewayGroups(gatewayId);
+//        } else {
+//            return GatewayGroupsInitializer.initializeGatewayGroups(gatewayId);
+//        }
+//    }
+
+    private boolean validateToken(String username, String token, String gatewayId, String identityServerRealm) throws Exception {
+        UserInfo userInfo = getUserInfo(gatewayId, token, identityServerRealm);
+        if (!username.equals(userInfo.getUsername())) {
+            throw new CustosSecurityException("Subject name and username for the token doesn't match");
+        }
+        return true;
+    }
+
+//    private String[] getUserRolesFromOAuthToken(String username, String token, String gatewayId) throws Exception {
+//        GatewayResourceProfile gwrp = getRegistryServiceClient().getGatewayResourceProfile(gatewayId);
+//        String identityServerRealm = gwrp.getIdentityServerTenant();
+//        String openIdConnectUrl = getOpenIDConfigurationUrl(identityServerRealm);
+//        JSONObject openIdConnectConfig = new JSONObject(getFromUrl(openIdConnectUrl, token));
+//        String userInfoEndPoint = openIdConnectConfig.getString("userinfo_endpoint");
+//        JSONObject userInfo = new JSONObject(getFromUrl(userInfoEndPoint, token));
+//        if (!username.equals(userInfo.get("preferred_username"))) {
+//            throw new CustosSecurityException("Subject name and username for the token doesn't match");
+//        }
+//        String userId = userInfo.getString("sub");
+//
+//        String userRoleMappingUrl = ServerSettings.getRemoteIDPServiceUrl() + "/admin/realms/"
+//                + identityServerRealm + "/users/"
+//                + userId + "/role-mappings/realm";
+//        JSONArray roleMappings = new JSONArray(getFromUrl(userRoleMappingUrl, getAdminAccessToken(gatewayId)));
+//        String[] roles = new String[roleMappings.length()];
+//        for (int i = 0; i < roleMappings.length(); i++) {
+//            roles[i] = (new JSONObject(roleMappings.get(i).toString())).get("name").toString();
+//        }
+//
+//        return roles;
+//    }
+
+    private String getOpenIDConfigurationUrl(String realm) throws ApplicationSettingsException {
+        return ServerSettings.getRemoteIDPServiceUrl() + "/realms/" + realm + "/.well-known/openid-configuration";
+    }
+
+    private String getFromUrl(String urlToRead, String token) throws Exception {
+        StringBuilder result = new StringBuilder();
+        URL url = new URL(urlToRead);
+        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+        conn.setRequestMethod("GET");
+        conn.setDoInput(true);
+        if (token != null) {
+            String bearerAuth = "Bearer " + token;
+            conn.setRequestProperty("Authorization", bearerAuth);
+        }
+        BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+        String line;
+        while ((line = rd.readLine()) != null) {
+            result.append(line);
+        }
+        rd.close();
+        return result.toString();
+    }
+
+//    private String getAdminAccessToken(String gatewayId) throws Exception {
+//        CredentialStoreService.Client csClient = getCredentialStoreServiceClient();
+//        GatewayResourceProfile gwrp = getRegistryServiceClient().getGatewayResourceProfile(gatewayId);
+//        String identityServerRealm = gwrp.getIdentityServerTenant();
+//        String openIdConnectUrl = getOpenIDConfigurationUrl(identityServerRealm);
+//        JSONObject openIdConnectConfig = new JSONObject(getFromUrl(openIdConnectUrl, null));
+//        PasswordCredential credential = csClient.getPasswordCredential(gwrp.getIdentityServerPwdCredToken(), gwrp.getGatewayID());
+//        String username = credential.getLoginUserName();
+//        String password = credential.getPassword();
+//        String urlString = openIdConnectConfig.getString("token_endpoint");
+//        StringBuilder result = new StringBuilder();
+//        URL url = new URL(urlString);
+//        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+//        conn.setRequestMethod("POST");
+//        conn.setDoOutput(true);
+//        String postFields = "client_id=admin-cli&username=" + username + "&password=" + password + "&grant_type=password";
+//        conn.getOutputStream().write(postFields.getBytes());
+//        BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+//        String line;
+//        while ((line = rd.readLine()) != null) {
+//            result.append(line);
+//        }
+//        rd.close();
+//        JSONObject tokenInfo = new JSONObject(result.toString());
+//        return tokenInfo.get("access_token").toString();
+//    }
+
+    private String getTokenEndpoint(String gatewayId) throws Exception {
+        String openIdConnectUrl = getOpenIDConfigurationUrl(gatewayId);
+        JSONObject openIdConnectConfig = new JSONObject(getFromUrl(openIdConnectUrl, null));
+        return openIdConnectConfig.getString("token_endpoint");
+    }
+
+    private JSONObject getClientCredentials(String tokenURL, String clientId, String clientSecret) throws ApplicationSettingsException, CustosSecurityException {
+
+        CloseableHttpClient httpClient = HttpClients.createSystem();
+
+        HttpPost httpPost = new HttpPost(tokenURL);
+        String encoded = Base64.getEncoder().encodeToString((clientId+":"+clientSecret).getBytes(StandardCharsets.UTF_8));
+        httpPost.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + encoded);
+        List<NameValuePair> formParams = new ArrayList<>();
+        formParams.add(new BasicNameValuePair("grant_type", "client_credentials"));
+        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, Consts.UTF_8);
+        httpPost.setEntity(entity);
+        try {
+            CloseableHttpResponse response = httpClient.execute(httpPost);
+            try {
+                String responseBody = EntityUtils.toString(response.getEntity());
+                JSONObject tokenInfo = new JSONObject(responseBody);
+                return tokenInfo;
+            } finally {
+                response.close();
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        } finally {
+            try {
+                httpClient.close();
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+//    private boolean hasPermission(GatewayGroupMembership gatewayGroupMembership, String apiMethod) {
+//
+//        // Note: as a stopgap solution, until all resources are secured with group-based authorization, map the Admins
+//        // and Read Only Admins groups to the corresponding roles
+//        final String role;
+//        if (gatewayGroupMembership.isInAdminsGroup()) {
+//            return true;
+//        } else if (gatewayGroupMembership.isInReadOnlyAdminsGroup()) {
+//            role = "admin-read-only";
+//        } else {
+//            // If not in Admins or Read Only Admins groups, treat as a gateway-user
+//            role = "gateway-user";
+//        }
+//        Pattern pattern = Pattern.compile(this.rolePermissionConfig.get(role));
+//        Matcher matcher = pattern.matcher(apiMethod);
+//        return matcher.matches();
+//    }
+//
+//    private boolean hasPermission(String[] roles, String apiMethod) {
+//        for (int i = 0; i < roles.length; i++) {
+//            String role = roles[i];
+//            if (this.rolePermissionConfig.keySet().contains(role)) {
+//                Pattern pattern = Pattern.compile(this.rolePermissionConfig.get(role));
+//                Matcher matcher = pattern.matcher(apiMethod);
+//                if (matcher.matches())
+//                    return true;
+//            }
+//        }
+//        return false;
+//    }
+//
+//    private void initServiceClients() throws TException, ApplicationSettingsException {
+//        registryServiceClient = getRegistryServiceClient();
+//        sharingRegistryServiceClient = getSharingRegistryServiceClient();
+//    }
+
+//    private void closeServiceClients() {
+//        if (registryServiceClient != null) {
+//            ThriftUtils.close(registryServiceClient);
+//        }
+//        if (sharingRegistryServiceClient != null) {
+//            ThriftUtils.close(sharingRegistryServiceClient);
+//        }
+//    }
+
+//    private RegistryService.Client getRegistryServiceClient() throws TException, ApplicationSettingsException {
+//        final int serverPort = Integer.parseInt(ServerSettings.getRegistryServerPort());
+//        final String serverHost = ServerSettings.getRegistryServerHost();
+//        try {
+//            return RegistryServiceClientFactory.createRegistryClient(serverHost, serverPort);
+//        } catch (RegistryServiceException e) {
+//            throw new TException("Unable to create registry client...", e);
+//        }
+//    }
+//
+//    private CredentialStoreService.Client getCredentialStoreServiceClient() throws TException, ApplicationSettingsException {
+//        final int serverPort = Integer.parseInt(ServerSettings.getCredentialStoreServerPort());
+//        final String serverHost = ServerSettings.getCredentialStoreServerHost();
+//        try {
+//            return CredentialStoreClientFactory.createAiravataCSClient(serverHost, serverPort);
+//        } catch (CredentialStoreException e) {
+//            throw new TException("Unable to create credential store client...", e);
+//        }
+//    }
+//
+//    private SharingRegistryService.Client getSharingRegistryServiceClient() throws TException, ApplicationSettingsException {
+//        final int serverPort = Integer.parseInt(ServerSettings.getSharingRegistryPort());
+//        final String serverHost = ServerSettings.getSharingRegistryHost();
+//        try {
+//            return SharingRegistryServiceClientFactory.createSharingRegistryClient(serverHost, serverPort);
+//        } catch (SharingRegistryException e) {
+//            throw new TException("Unable to create sharing registry client...", e);
+//        }
+//    }
+
+//    public static void main(String[] args) throws CustosSecurityException, ApplicationSettingsException {
+//        ServerSettings.setSetting("trust.store", "./modules/configuration/server/src/main/resources/client_truststore.jks");
+//        ServerSettings.setSetting("trust.store.password", "airavata");
+//        KeyCloakSecurityManager keyCloakSecurityManager = new KeyCloakSecurityManager();
+//        final String tokenURL = "...";
+//        final String clientId = "...";
+//        final String clientSecret = "...";
+//        JSONObject jsonObject = keyCloakSecurityManager.getClientCredentials(tokenURL, clientId, clientSecret);
+//        System.out.println("access_token=" + jsonObject.getString("access_token"));
+//    }
+}
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/manager/SecurityManagerFactory.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/manager/SecurityManagerFactory.java
new file mode 100644
index 0000000..42f0af1
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/manager/SecurityManagerFactory.java
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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 org.apache.custos.security.manager;
+
+import org.apache.custos.commons.exceptions.ApplicationSettingsException;
+import org.apache.custos.commons.exceptions.CustosSecurityException;
+import org.apache.custos.commons.utils.ServerSettings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This initializes an instance of the appropriate security manager according to the
+ * configuration.
+ */
+public class SecurityManagerFactory {
+    private final static Logger logger = LoggerFactory.getLogger(SecurityManagerFactory.class);
+
+    public static CustosSecurityManager getSecurityManager() throws CustosSecurityException {
+        try {
+            Class secManagerImpl = Class.forName(ServerSettings.getSecurityManagerClassName());
+            CustosSecurityManager securityManager = (CustosSecurityManager) secManagerImpl.newInstance();
+            return securityManager;
+        } catch (ClassNotFoundException e) {
+            String error = "Security Manager class could not be found.";
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException(error);
+        } catch (ApplicationSettingsException e) {
+            String error = "Error in reading the configuration related to Security Manager class.";
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException(error);
+        } catch (InstantiationException e) {
+            String error = "Error in instantiating the Security Manager class.";
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException(error);
+        } catch (IllegalAccessException e) {
+            String error = "Error in instantiating the Security Manager class.";
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException(error);
+
+        }
+    }
+}
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/manager/UserInfo.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/manager/UserInfo.java
new file mode 100644
index 0000000..4687748
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/manager/UserInfo.java
@@ -0,0 +1,84 @@
+/*
+ * 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 org.apache.custos.security.manager;
+
+public class UserInfo {
+    private String sub;
+    private String firstName;
+    private String lastName;
+    private String fullName;
+    private String emailAddress;
+    private String username;
+
+    public String getSub() {
+        return sub;
+    }
+
+    public UserInfo setSub(String sub) {
+        this.sub = sub;
+        return this;
+    }
+
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public UserInfo setFirstName(String firstName) {
+        this.firstName = firstName;
+        return this;
+    }
+
+    public String getLastName() {
+        return lastName;
+    }
+
+    public UserInfo setLastName(String lastName) {
+        this.lastName = lastName;
+        return this;
+    }
+
+    public String getFullName() {
+        return fullName;
+    }
+
+    public UserInfo setFullName(String fullName) {
+        this.fullName = fullName;
+        return this;
+    }
+
+    public String getEmailAddress() {
+        return emailAddress;
+    }
+
+    public UserInfo setEmailAddress(String emailAddress) {
+        this.emailAddress = emailAddress;
+        return this;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public UserInfo setUsername(String username) {
+        this.username = username;
+        return this;
+    }
+}
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/model/AuthzToken.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/model/AuthzToken.java
new file mode 100644
index 0000000..448df68
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/model/AuthzToken.java
@@ -0,0 +1,541 @@
+/**
+ * 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.
+ */
+
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+package org.apache.custos.security.model;
+
+@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)")
+public class AuthzToken implements org.apache.thrift.TBase<AuthzToken, AuthzToken._Fields>, java.io.Serializable, Cloneable, Comparable<AuthzToken> {
+  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("AuthzToken");
+
+  private static final org.apache.thrift.protocol.TField ACCESS_TOKEN_FIELD_DESC = new org.apache.thrift.protocol.TField("accessToken", org.apache.thrift.protocol.TType.STRING, (short)1);
+  private static final org.apache.thrift.protocol.TField CLAIMS_MAP_FIELD_DESC = new org.apache.thrift.protocol.TField("claimsMap", org.apache.thrift.protocol.TType.MAP, (short)2);
+
+  private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new AuthzTokenStandardSchemeFactory();
+  private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new AuthzTokenTupleSchemeFactory();
+
+  private String accessToken; // required
+  private java.util.Map<String, String> claimsMap; // optional
+
+  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+  public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+    ACCESS_TOKEN((short)1, "accessToken"),
+    CLAIMS_MAP((short)2, "claimsMap");
+
+    private static final java.util.Map<String, _Fields> byName = new java.util.HashMap<String, _Fields>();
+
+    static {
+      for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
+        byName.put(field.getFieldName(), field);
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, or null if its not found.
+     */
+    public static _Fields findByThriftId(int fieldId) {
+      switch(fieldId) {
+        case 1: // ACCESS_TOKEN
+          return ACCESS_TOKEN;
+        case 2: // CLAIMS_MAP
+          return CLAIMS_MAP;
+        default:
+          return null;
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, throwing an exception
+     * if it is not found.
+     */
+    public static _Fields findByThriftIdOrThrow(int fieldId) {
+      _Fields fields = findByThriftId(fieldId);
+      if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+      return fields;
+    }
+
+    /**
+     * Find the _Fields constant that matches name, or null if its not found.
+     */
+    public static _Fields findByName(String name) {
+      return byName.get(name);
+    }
+
+    private final short _thriftId;
+    private final String _fieldName;
+
+    _Fields(short thriftId, String fieldName) {
+      _thriftId = thriftId;
+      _fieldName = fieldName;
+    }
+
+    public short getThriftFieldId() {
+      return _thriftId;
+    }
+
+    public String getFieldName() {
+      return _fieldName;
+    }
+  }
+
+  // isset id assignments
+  private static final _Fields optionals[] = {_Fields.CLAIMS_MAP};
+  public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+  static {
+    java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+    tmpMap.put(_Fields.ACCESS_TOKEN, new org.apache.thrift.meta_data.FieldMetaData("accessToken", org.apache.thrift.TFieldRequirementType.REQUIRED,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.CLAIMS_MAP, new org.apache.thrift.meta_data.FieldMetaData("claimsMap", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+        new org.apache.thrift.meta_data.MapMetaData(org.apache.thrift.protocol.TType.MAP,
+            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING),
+            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
+    metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
+    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(AuthzToken.class, metaDataMap);
+  }
+
+  public AuthzToken() {
+  }
+
+  public AuthzToken(
+    String accessToken)
+  {
+    this();
+    this.accessToken = accessToken;
+  }
+
+  /**
+   * Performs a deep copy on <i>other</i>.
+   */
+  public AuthzToken(AuthzToken other) {
+    if (other.isSetAccessToken()) {
+      this.accessToken = other.accessToken;
+    }
+    if (other.isSetClaimsMap()) {
+      java.util.Map<String, String> __this__claimsMap = new java.util.HashMap<String, String>(other.claimsMap);
+      this.claimsMap = __this__claimsMap;
+    }
+  }
+
+  public AuthzToken deepCopy() {
+    return new AuthzToken(this);
+  }
+
+  @Override
+  public void clear() {
+    this.accessToken = null;
+    this.claimsMap = null;
+  }
+
+  public String getAccessToken() {
+    return this.accessToken;
+  }
+
+  public void setAccessToken(String accessToken) {
+    this.accessToken = accessToken;
+  }
+
+  public void unsetAccessToken() {
+    this.accessToken = null;
+  }
+
+  /** Returns true if field accessToken is set (has been assigned a value) and false otherwise */
+  public boolean isSetAccessToken() {
+    return this.accessToken != null;
+  }
+
+  public void setAccessTokenIsSet(boolean value) {
+    if (!value) {
+      this.accessToken = null;
+    }
+  }
+
+  public int getClaimsMapSize() {
+    return (this.claimsMap == null) ? 0 : this.claimsMap.size();
+  }
+
+  public void putToClaimsMap(String key, String val) {
+    if (this.claimsMap == null) {
+      this.claimsMap = new java.util.HashMap<String, String>();
+    }
+    this.claimsMap.put(key, val);
+  }
+
+  public java.util.Map<String, String> getClaimsMap() {
+    return this.claimsMap;
+  }
+
+  public void setClaimsMap(java.util.Map<String, String> claimsMap) {
+    this.claimsMap = claimsMap;
+  }
+
+  public void unsetClaimsMap() {
+    this.claimsMap = null;
+  }
+
+  /** Returns true if field claimsMap is set (has been assigned a value) and false otherwise */
+  public boolean isSetClaimsMap() {
+    return this.claimsMap != null;
+  }
+
+  public void setClaimsMapIsSet(boolean value) {
+    if (!value) {
+      this.claimsMap = null;
+    }
+  }
+
+  public void setFieldValue(_Fields field, Object value) {
+    switch (field) {
+    case ACCESS_TOKEN:
+      if (value == null) {
+        unsetAccessToken();
+      } else {
+        setAccessToken((String)value);
+      }
+      break;
+
+    case CLAIMS_MAP:
+      if (value == null) {
+        unsetClaimsMap();
+      } else {
+        setClaimsMap((java.util.Map<String, String>)value);
+      }
+      break;
+
+    }
+  }
+
+  public Object getFieldValue(_Fields field) {
+    switch (field) {
+    case ACCESS_TOKEN:
+      return getAccessToken();
+
+    case CLAIMS_MAP:
+      return getClaimsMap();
+
+    }
+    throw new IllegalStateException();
+  }
+
+  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+  public boolean isSet(_Fields field) {
+    if (field == null) {
+      throw new IllegalArgumentException();
+    }
+
+    switch (field) {
+    case ACCESS_TOKEN:
+      return isSetAccessToken();
+    case CLAIMS_MAP:
+      return isSetClaimsMap();
+    }
+    throw new IllegalStateException();
+  }
+
+  @Override
+  public boolean equals(Object that) {
+    if (that == null)
+      return false;
+    if (that instanceof AuthzToken)
+      return this.equals((AuthzToken)that);
+    return false;
+  }
+
+  public boolean equals(AuthzToken that) {
+    if (that == null)
+      return false;
+    if (this == that)
+      return true;
+
+    boolean this_present_accessToken = true && this.isSetAccessToken();
+    boolean that_present_accessToken = true && that.isSetAccessToken();
+    if (this_present_accessToken || that_present_accessToken) {
+      if (!(this_present_accessToken && that_present_accessToken))
+        return false;
+      if (!this.accessToken.equals(that.accessToken))
+        return false;
+    }
+
+    boolean this_present_claimsMap = true && this.isSetClaimsMap();
+    boolean that_present_claimsMap = true && that.isSetClaimsMap();
+    if (this_present_claimsMap || that_present_claimsMap) {
+      if (!(this_present_claimsMap && that_present_claimsMap))
+        return false;
+      if (!this.claimsMap.equals(that.claimsMap))
+        return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int hashCode = 1;
+
+    hashCode = hashCode * 8191 + ((isSetAccessToken()) ? 131071 : 524287);
+    if (isSetAccessToken())
+      hashCode = hashCode * 8191 + accessToken.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetClaimsMap()) ? 131071 : 524287);
+    if (isSetClaimsMap())
+      hashCode = hashCode * 8191 + claimsMap.hashCode();
+
+    return hashCode;
+  }
+
+  @Override
+  public int compareTo(AuthzToken other) {
+    if (!getClass().equals(other.getClass())) {
+      return getClass().getName().compareTo(other.getClass().getName());
+    }
+
+    int lastComparison = 0;
+
+    lastComparison = Boolean.valueOf(isSetAccessToken()).compareTo(other.isSetAccessToken());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetAccessToken()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.accessToken, other.accessToken);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetClaimsMap()).compareTo(other.isSetClaimsMap());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetClaimsMap()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.claimsMap, other.claimsMap);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    return 0;
+  }
+
+  public _Fields fieldForId(int fieldId) {
+    return _Fields.findByThriftId(fieldId);
+  }
+
+  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+    scheme(iprot).read(iprot, this);
+  }
+
+  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+    scheme(oprot).write(oprot, this);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("AuthzToken(");
+    boolean first = true;
+
+    sb.append("accessToken:");
+    if (this.accessToken == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.accessToken);
+    }
+    first = false;
+    if (isSetClaimsMap()) {
+      if (!first) sb.append(", ");
+      sb.append("claimsMap:");
+      if (this.claimsMap == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.claimsMap);
+      }
+      first = false;
+    }
+    sb.append(")");
+    return sb.toString();
+  }
+
+  public void validate() throws org.apache.thrift.TException {
+    // check for required fields
+    if (!isSetAccessToken()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'accessToken' is unset! Struct:" + toString());
+    }
+
+    // check for sub-struct validity
+  }
+
+  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+    try {
+      write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+    try {
+      read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private static class AuthzTokenStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
+    public AuthzTokenStandardScheme getScheme() {
+      return new AuthzTokenStandardScheme();
+    }
+  }
+
+  private static class AuthzTokenStandardScheme extends org.apache.thrift.scheme.StandardScheme<AuthzToken> {
+
+    public void read(org.apache.thrift.protocol.TProtocol iprot, AuthzToken struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TField schemeField;
+      iprot.readStructBegin();
+      while (true)
+      {
+        schemeField = iprot.readFieldBegin();
+        if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+          break;
+        }
+        switch (schemeField.id) {
+          case 1: // ACCESS_TOKEN
+            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+              struct.accessToken = iprot.readString();
+              struct.setAccessTokenIsSet(true);
+            } else {
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          case 2: // CLAIMS_MAP
+            if (schemeField.type == org.apache.thrift.protocol.TType.MAP) {
+              {
+                org.apache.thrift.protocol.TMap _map0 = iprot.readMapBegin();
+                struct.claimsMap = new java.util.HashMap<String, String>(2*_map0.size);
+                String _key1;
+                String _val2;
+                for (int _i3 = 0; _i3 < _map0.size; ++_i3)
+                {
+                  _key1 = iprot.readString();
+                  _val2 = iprot.readString();
+                  struct.claimsMap.put(_key1, _val2);
+                }
+                iprot.readMapEnd();
+              }
+              struct.setClaimsMapIsSet(true);
+            } else {
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          default:
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+      struct.validate();
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot, AuthzToken struct) throws org.apache.thrift.TException {
+      struct.validate();
+
+      oprot.writeStructBegin(STRUCT_DESC);
+      if (struct.accessToken != null) {
+        oprot.writeFieldBegin(ACCESS_TOKEN_FIELD_DESC);
+        oprot.writeString(struct.accessToken);
+        oprot.writeFieldEnd();
+      }
+      if (struct.claimsMap != null) {
+        if (struct.isSetClaimsMap()) {
+          oprot.writeFieldBegin(CLAIMS_MAP_FIELD_DESC);
+          {
+            oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRING, struct.claimsMap.size()));
+            for (java.util.Map.Entry<String, String> _iter4 : struct.claimsMap.entrySet())
+            {
+              oprot.writeString(_iter4.getKey());
+              oprot.writeString(_iter4.getValue());
+            }
+            oprot.writeMapEnd();
+          }
+          oprot.writeFieldEnd();
+        }
+      }
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+  }
+
+  private static class AuthzTokenTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
+    public AuthzTokenTupleScheme getScheme() {
+      return new AuthzTokenTupleScheme();
+    }
+  }
+
+  private static class AuthzTokenTupleScheme extends org.apache.thrift.scheme.TupleScheme<AuthzToken> {
+
+    @Override
+    public void write(org.apache.thrift.protocol.TProtocol prot, AuthzToken struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
+      oprot.writeString(struct.accessToken);
+      java.util.BitSet optionals = new java.util.BitSet();
+      if (struct.isSetClaimsMap()) {
+        optionals.set(0);
+      }
+      oprot.writeBitSet(optionals, 1);
+      if (struct.isSetClaimsMap()) {
+        {
+          oprot.writeI32(struct.claimsMap.size());
+          for (java.util.Map.Entry<String, String> _iter5 : struct.claimsMap.entrySet())
+          {
+            oprot.writeString(_iter5.getKey());
+            oprot.writeString(_iter5.getValue());
+          }
+        }
+      }
+    }
+
+    @Override
+    public void read(org.apache.thrift.protocol.TProtocol prot, AuthzToken struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
+      struct.accessToken = iprot.readString();
+      struct.setAccessTokenIsSet(true);
+      java.util.BitSet incoming = iprot.readBitSet(1);
+      if (incoming.get(0)) {
+        {
+          org.apache.thrift.protocol.TMap _map6 = new org.apache.thrift.protocol.TMap(org.apache.thrift.protocol.TType.STRING, org.apache.thrift.protocol.TType.STRING, iprot.readI32());
+          struct.claimsMap = new java.util.HashMap<String, String>(2*_map6.size);
+          String _key7;
+          String _val8;
+          for (int _i9 = 0; _i9 < _map6.size; ++_i9)
+          {
+            _key7 = iprot.readString();
+            _val8 = iprot.readString();
+            struct.claimsMap.put(_key7, _val8);
+          }
+        }
+        struct.setClaimsMapIsSet(true);
+      }
+    }
+  }
+
+  private static <S extends org.apache.thrift.scheme.IScheme> S scheme(org.apache.thrift.protocol.TProtocol proto) {
+    return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme();
+  }
+}
+
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/oauth/DefaultOAuthClient.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/oauth/DefaultOAuthClient.java
new file mode 100644
index 0000000..505b489
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/oauth/DefaultOAuthClient.java
@@ -0,0 +1,91 @@
+/*
+ *
+ * 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 org.apache.custos.security.oauth;
+
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.context.ConfigurationContext;
+import org.apache.custos.commons.exceptions.CustosSecurityException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
+import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO;
+import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO_OAuth2AccessToken;
+import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO;
+import org.wso2.carbon.utils.CarbonUtils;
+
+import java.rmi.RemoteException;
+
+/**
+ * This is the default OAuth Client that talks to WSO2 IS's OAuth Authentication Server
+ * to get the OAuth token validated.
+ */
+public class DefaultOAuthClient {
+
+    private OAuth2TokenValidationServiceStub stub;
+    private final static Logger logger = LoggerFactory.getLogger(DefaultOAuthClient.class);
+    public static final String BEARER_TOKEN_TYPE = "bearer";
+
+    /**
+     * OAuth2TokenValidationService Admin Service Client
+     *
+     * @param auhorizationServerURL
+     * @param username
+     * @param password
+     * @param configCtx
+     * @throws Exception
+     */
+    public DefaultOAuthClient(String auhorizationServerURL, String username, String password,
+                              ConfigurationContext configCtx) throws CustosSecurityException {
+        try {
+            String serviceURL = auhorizationServerURL + "OAuth2TokenValidationService";
+            stub = new OAuth2TokenValidationServiceStub(configCtx, serviceURL);
+            CarbonUtils.setBasicAccessSecurityHeaders(username, password, true, stub._getServiceClient());
+        } catch (AxisFault e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error initializing OAuth client.");
+        }
+    }
+
+    /**
+     * Validates the OAuth 2.0 access token
+     *
+     * @param accessToken
+     * @return
+     * @throws Exception
+     */
+    public OAuth2TokenValidationResponseDTO validateAccessToken(String accessToken)
+            throws CustosSecurityException {
+
+        try {
+            OAuth2TokenValidationRequestDTO oauthReq = new OAuth2TokenValidationRequestDTO();
+            OAuth2TokenValidationRequestDTO_OAuth2AccessToken token =
+                    new OAuth2TokenValidationRequestDTO_OAuth2AccessToken();
+            token.setIdentifier(accessToken);
+            token.setTokenType(BEARER_TOKEN_TYPE);
+            oauthReq.setAccessToken(token);
+            return stub.validate(oauthReq);
+        } catch (RemoteException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in validating the OAuth access token.");
+        }
+    }
+
+}
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/service/SecurityServiceHandler.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/service/SecurityServiceHandler.java
new file mode 100644
index 0000000..058ed87
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/service/SecurityServiceHandler.java
@@ -0,0 +1,30 @@
+package org.apache.custos.security.service;
+
+import org.apache.custos.commons.exceptions.CustosSecurityException;
+import org.apache.custos.commons.model.error.AuthorizationException;
+import org.apache.custos.security.manager.CustosSecurityManager;
+import org.apache.custos.security.manager.SecurityManagerFactory;
+import org.apache.custos.security.model.AuthzToken;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+
+public class SecurityServiceHandler {
+
+    private final static Logger logger = LoggerFactory.getLogger(SecurityServiceHandler.class);
+
+    public boolean authorize(AuthzToken authzToken, Map<String, String> metaData) throws AuthorizationException {
+        try {
+            CustosSecurityManager securityManager = SecurityManagerFactory.getSecurityManager();
+            boolean isAuthz = securityManager.isUserAuthorized(authzToken, metaData);
+            if (!isAuthz) {
+                throw new AuthorizationException("User is not authenticated or authorized.");
+            }
+        } catch (CustosSecurityException e) {
+            logger.error(e.getMessage(), e);
+            throw new AuthorizationException("Error in authenticating or authorizing user.");
+        }
+        return true;
+    }
+}
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/utils/TrustStoreManager.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/utils/TrustStoreManager.java
new file mode 100644
index 0000000..4477207
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/utils/TrustStoreManager.java
@@ -0,0 +1,100 @@
+/**
+ *
+ * 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 org.apache.custos.security.utils;
+
+import org.apache.custos.commons.exceptions.CustosSecurityException;
+import org.apache.custos.commons.utils.SecurityUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import java.io.*;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+
+public class TrustStoreManager {
+    private final static Logger logger = LoggerFactory.getLogger(TrustStoreManager.class);
+    public SSLContext initializeTrustStoreManager(String trustStorePath, String trustStorePassword)
+            throws CustosSecurityException {
+        try {
+            // load and initialize the trust store
+
+            File trustStoreFile = new File(trustStorePath);
+            InputStream is;
+            if (trustStoreFile.exists()) {
+                logger.debug("Loading trust store file from path " + trustStorePath);
+                is = new FileInputStream(trustStorePath);
+            } else {
+                logger.debug("Trying to load trust store file form class path " + trustStorePath);
+                is = SecurityUtil.class.getClassLoader().getResourceAsStream(trustStorePath);
+                if (is != null) {
+                    logger.debug("Trust store file was loaded form class path " + trustStorePath);
+                }
+            }
+
+            if (is == null) {
+                throw new CustosSecurityException("Could not find a trust store file in path " + trustStorePath);
+            }
+
+            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
+
+            char[] trustPassword = trustStorePassword.toCharArray();
+
+            trustStore.load(is, trustPassword);
+
+            // initialize a trust manager factory
+            TrustManagerFactory trustFactory =
+                    TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+            trustFactory.init(trustStore);
+
+            // get the trust managers from the factory
+            TrustManager[] trustManagers = trustFactory.getTrustManagers();
+
+            // initialize an ssl context to use these managers and set as default
+            SSLContext sslContext = SSLContext.getInstance("SSL");
+            sslContext.init(null, trustManagers, null);
+            SSLContext.setDefault(sslContext);
+            return sslContext;
+        } catch (CertificateException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in initializing the trust store.");
+        } catch (NoSuchAlgorithmException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in initializing the trust store.");
+        } catch (KeyStoreException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in initializing the trust store.");
+        } catch (KeyManagementException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in initializing the trust store.");
+        } catch (FileNotFoundException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in initializing the trust store.");
+        } catch (IOException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in initializing the trust store.");
+        }
+    }
+}
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/xacml/DefaultPAPClient.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/xacml/DefaultPAPClient.java
new file mode 100644
index 0000000..c76c301
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/xacml/DefaultPAPClient.java
@@ -0,0 +1,124 @@
+/*
+ *
+ * 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 org.apache.custos.security.xacml;
+
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.context.ConfigurationContext;
+import org.apache.custos.commons.exceptions.ApplicationSettingsException;
+import org.apache.custos.commons.exceptions.CustosSecurityException;
+import org.apache.custos.commons.utils.ServerSettings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.wso2.carbon.identity.entitlement.common.EntitlementConstants;
+import org.wso2.carbon.identity.entitlement.stub.EntitlementPolicyAdminServiceEntitlementException;
+import org.wso2.carbon.identity.entitlement.stub.EntitlementPolicyAdminServiceStub;
+import org.wso2.carbon.identity.entitlement.stub.dto.PaginatedStatusHolder;
+import org.wso2.carbon.identity.entitlement.stub.dto.PolicyDTO;
+import org.wso2.carbon.identity.entitlement.stub.dto.StatusHolder;
+import org.wso2.carbon.utils.CarbonUtils;
+import java.rmi.RemoteException;
+
+/**
+ * This publishes the airavata-default-xacml-policy.xml to the PDP via PAP API (of WSO2 Identity Server)
+ */
+public class DefaultPAPClient {
+
+    private final static Logger logger = LoggerFactory.getLogger(DefaultPAPClient.class);
+    private EntitlementPolicyAdminServiceStub entitlementPolicyAdminServiceStub;
+
+    public DefaultPAPClient(String auhorizationServerURL, String username, String password,
+                            ConfigurationContext configCtx) throws CustosSecurityException {
+        try {
+
+            String PDPURL = auhorizationServerURL + "EntitlementPolicyAdminService";
+            entitlementPolicyAdminServiceStub = new EntitlementPolicyAdminServiceStub(configCtx, PDPURL);
+            CarbonUtils.setBasicAccessSecurityHeaders(username, password, true,
+                    entitlementPolicyAdminServiceStub._getServiceClient());
+        } catch (AxisFault e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error initializing XACML PEP client.");
+        }
+
+    }
+
+    public boolean isPolicyAdded(String policyName) {
+        try {
+            PolicyDTO policyDTO = entitlementPolicyAdminServiceStub.getPolicy(policyName, false);
+        } catch (RemoteException e) {
+            logger.debug("Error in retrieving the policy.", e);
+            return false;
+        } catch (EntitlementPolicyAdminServiceEntitlementException e) {
+            logger.debug("Error in retrieving the policy.", e);
+            return false;
+        }
+        return true;
+    }
+
+    public void addPolicy(String policy) throws CustosSecurityException {
+        new Thread() {
+            public void run() {
+                try {
+                    PolicyDTO policyDTO = new PolicyDTO();
+                    policyDTO.setPolicy(policy);
+                    entitlementPolicyAdminServiceStub.addPolicy(policyDTO);
+                    entitlementPolicyAdminServiceStub.publishToPDP(new String[]{ServerSettings.getAuthorizationPoliyName()},
+                            EntitlementConstants.PolicyPublish.ACTION_CREATE, null, false, 0);
+
+                    //Since policy publishing happens asynchronously, we need to retrieve the status and verify.
+                    Thread.sleep(2000);
+                    PaginatedStatusHolder paginatedStatusHolder = entitlementPolicyAdminServiceStub.
+                            getStatusData(EntitlementConstants.Status.ABOUT_POLICY, ServerSettings.getAuthorizationPoliyName(),
+                                    EntitlementConstants.StatusTypes.PUBLISH_POLICY, "*", 1);
+                    StatusHolder statusHolder = paginatedStatusHolder.getStatusHolders()[0];
+                    if (statusHolder.getSuccess() && EntitlementConstants.PolicyPublish.ACTION_CREATE.equals(statusHolder.getTargetAction())) {
+                        logger.info("Authorization policy is published successfully.");
+                    } else {
+                        throw new CustosSecurityException("Failed to publish the authorization policy.");
+                    }
+
+                    //enable the published policy
+                    entitlementPolicyAdminServiceStub.enableDisablePolicy(ServerSettings.getAuthorizationPoliyName(), true);
+                    //Since policy enabling happens asynchronously, we need to retrieve the status and verify.
+                    Thread.sleep(2000);
+                    paginatedStatusHolder = entitlementPolicyAdminServiceStub.
+                            getStatusData(EntitlementConstants.Status.ABOUT_POLICY, ServerSettings.getAuthorizationPoliyName(),
+                                    EntitlementConstants.StatusTypes.PUBLISH_POLICY, "*", 1);
+                    statusHolder = paginatedStatusHolder.getStatusHolders()[0];
+                    if (statusHolder.getSuccess() && EntitlementConstants.PolicyPublish.ACTION_ENABLE.equals(statusHolder.getTargetAction())) {
+                        logger.info("Authorization policy is enabled successfully.");
+                    } else {
+                        throw new CustosSecurityException("Failed to enable the authorization policy.");
+                    }
+                } catch (RemoteException e) {
+                    logger.error(e.getMessage(), e);
+                } catch (InterruptedException e) {
+                    logger.error(e.getMessage(), e);
+                } catch (ApplicationSettingsException e) {
+                    logger.error(e.getMessage(), e);
+                } catch (CustosSecurityException e) {
+                    logger.error(e.getMessage(), e);
+                } catch (EntitlementPolicyAdminServiceEntitlementException e) {
+                    logger.error(e.getMessage(), e);
+                }
+            }
+        }.start();
+    }
+}
diff --git a/custos-services/custos-security-service/src/main/java/org/apache/custos/security/xacml/DefaultXACMLPEP.java b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/xacml/DefaultXACMLPEP.java
new file mode 100644
index 0000000..741ffcc
--- /dev/null
+++ b/custos-services/custos-security-service/src/main/java/org/apache/custos/security/xacml/DefaultXACMLPEP.java
@@ -0,0 +1,133 @@
+/*
+ *
+ * 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 org.apache.custos.security.xacml;
+
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.context.ConfigurationContext;
+import org.apache.custos.commons.exceptions.CustosSecurityException;
+import org.apache.custos.commons.utils.Constants;
+import org.apache.custos.security.model.AuthzToken;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.wso2.carbon.identity.entitlement.stub.EntitlementServiceException;
+import org.wso2.carbon.identity.entitlement.stub.EntitlementServiceStub;
+import org.wso2.carbon.utils.CarbonUtils;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.rmi.RemoteException;
+import java.util.Map;
+
+/**
+ * This enforces XACML based fine grained authorization on the API calls, by authorizing the API calls
+ * through default PDP which is WSO2 Identity Server.
+ */
+public class DefaultXACMLPEP {
+
+    private final static Logger logger = LoggerFactory.getLogger(DefaultXACMLPEP.class);
+    private EntitlementServiceStub entitlementServiceStub;
+
+    public DefaultXACMLPEP(String auhorizationServerURL, String username, String password,
+                           ConfigurationContext configCtx) throws CustosSecurityException {
+        try {
+
+            String PDPURL = auhorizationServerURL + "EntitlementService";
+            entitlementServiceStub = new EntitlementServiceStub(configCtx, PDPURL);
+            CarbonUtils.setBasicAccessSecurityHeaders(username, password, true, entitlementServiceStub._getServiceClient());
+        } catch (AxisFault e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error initializing XACML PEP client.");
+        }
+
+    }
+
+    /**
+     * Send the XACML authorization request to XAML PDP and return the authorization decision.
+     *
+     * @param authzToken
+     * @param metaData
+     * @return
+     */
+    public boolean getAuthorizationDecision(AuthzToken authzToken, Map<String, String> metaData) throws CustosSecurityException {
+        String decision;
+        try {
+            String subject = authzToken.getClaimsMap().get(Constants.USER_NAME);
+            //FIXME hacky way to fix OpenID -> CILogon issue in WSO2 IS
+            if(subject.startsWith("http://")){
+                subject = subject.substring(6);
+            }
+            String action = "/airavata/" + metaData.get(Constants.API_METHOD_NAME);
+            String decisionString = entitlementServiceStub.getDecisionByAttributes(subject, null, action, null);
+            //parse the XML decision string and obtain the decision
+            decision = parseDecisionString(decisionString);
+            if (Constants.PERMIT.equals(decision)) {
+                return true;
+            } else {
+                logger.error("Authorization decision is: " + decision);
+                return false;
+            }
+        } catch (RemoteException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in authorizing the user.");
+        } catch (EntitlementServiceException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in authorizing the user.");
+        }
+    }
+
+    /**
+     * This parses the XML based authorization response by the PDP and returns the decision string.
+     *
+     * @param decisionString
+     * @return
+     * @throws CustosSecurityException
+     */
+    private String parseDecisionString(String decisionString) throws CustosSecurityException {
+        try {
+            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
+            InputStream inputStream = new ByteArrayInputStream(decisionString.getBytes("UTF-8"));
+            Document doc = docBuilderFactory.newDocumentBuilder().parse(inputStream);
+            Node resultNode = doc.getDocumentElement().getFirstChild();
+            Node decisionNode = resultNode.getFirstChild();
+            String decision = decisionNode.getTextContent();
+            return decision;
+        } catch (ParserConfigurationException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in parsing XACML authorization response.");
+        } catch (UnsupportedEncodingException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in parsing XACML authorization response.");
+        } catch (SAXException e) {
+            logger.error(e.getMessage(), e);
+            throw new CustosSecurityException("Error in parsing XACML authorization response.");
+        } catch (IOException e) {
+            logger.error("Error in parsing XACML authorization response.");
+            throw new CustosSecurityException("Error in parsing XACML authorization response.");
+        }
+    }
+}
diff --git a/custos-services/pom.xml b/custos-services/pom.xml
new file mode 100644
index 0000000..d0e8239
--- /dev/null
+++ b/custos-services/pom.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--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. -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>custos</artifactId>
+        <groupId>org.apache.custos</groupId>
+        <version>1.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>custos-services</artifactId>
+    <packaging>pom</packaging>
+    <name>Custos Services</name>
+
+    <modules>
+        <module>profile-service</module>
+        <module>custos-security-service</module>
+    </modules>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <openjpa.version>2.4.3</openjpa.version>
+    </properties>
+</project>
\ No newline at end of file
diff --git a/custos-services/profile-service/iam-admin-services-core/pom.xml b/custos-services/profile-service/iam-admin-services-core/pom.xml
new file mode 100644
index 0000000..bc2a6d0
--- /dev/null
+++ b/custos-services/profile-service/iam-admin-services-core/pom.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>8</source>
+                    <target>8</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <parent>
+        <groupId>org.apache.custos</groupId>
+        <artifactId>profile-service</artifactId>
+        <version>1.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    
+    <artifactId>iam-admin-services-core</artifactId>
+    <name>Iam Admin Services</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>commons-httpclient</groupId>
+            <artifactId>commons-httpclient</artifactId>
+            <version>3.1</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.2</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/javax.ws.rs/javax.ws.rs-api -->
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>javax.ws.rs-api</artifactId>
+            <version>2.0.1</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/org.jboss.resteasy/resteasy-client -->
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-client</artifactId>
+            <version>3.0.14.Final</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/org.jboss.resteasy/resteasy-jackson2-provider -->
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jackson2-provider</artifactId>
+            <version>3.0.14.Final</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>2.5.4</version>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/org.keycloak/keycloak-admin-client -->
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-admin-client</artifactId>
+            <version>2.5.5.Final</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.custos</groupId>
+            <artifactId>profile-service-stubs</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.custos</groupId>
+            <artifactId>custos-commons</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.custos</groupId>
+            <artifactId>profile-service-models</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
+    </dependencies>
+    
+</project>
\ No newline at end of file
diff --git a/custos-services/profile-service/iam-admin-services-core/src/main/java/org/apache/custos/service/profile/iam/admin/services/core/impl/TenantManagementKeycloakImpl.java b/custos-services/profile-service/iam-admin-services-core/src/main/java/org/apache/custos/service/profile/iam/admin/services/core/impl/TenantManagementKeycloakImpl.java
new file mode 100644
index 0000000..bab92a2
--- /dev/null
+++ b/custos-services/profile-service/iam-admin-services-core/src/main/java/org/apache/custos/service/profile/iam/admin/services/core/impl/TenantManagementKeycloakImpl.java
@@ -0,0 +1,821 @@
+/*
+ *
+ * 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 org.apache.custos.service.profile.iam.admin.services.core.impl;
+
+import org.apache.custos.commons.exceptions.ApplicationSettingsException;
+import org.apache.custos.commons.utils.SecurityUtil;
+import org.apache.custos.commons.utils.ServerSettings;
+import org.apache.custos.profile.models.tenant.PasswordCredential;
+import org.apache.custos.profile.models.user.Status;
+import org.apache.custos.profile.models.user.UserProfile;
+import org.apache.custos.profile.models.workspace.Gateway;
+import org.apache.custos.service.profile.iam.admin.services.core.interfaces.TenantManagementInterface;
+import org.apache.custos.service.profile.iam.admin.services.cpi.exception.IamAdminServicesException;
+import org.jboss.resteasy.client.jaxrs.ResteasyClient;
+import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.admin.client.KeycloakBuilder;
+import org.keycloak.admin.client.resource.RoleResource;
+import org.keycloak.admin.client.resource.UserResource;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.RoleRepresentation;
+import org.keycloak.representations.idm.RolesRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.core.Response;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyStore;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class TenantManagementKeycloakImpl implements TenantManagementInterface {
+
+    private final static Logger logger = LoggerFactory.getLogger(TenantManagementKeycloakImpl.class);
+
+    private String superAdminRealmId = "master";
+
+    private static Keycloak getClient(String adminUrl, String realm, PasswordCredential AdminPasswordCreds) {
+
+        ResteasyClient resteasyClient = new ResteasyClientBuilder()
+                .connectionPoolSize(10)
+                .trustStore(loadKeyStore())
+                .build();
+        return KeycloakBuilder.builder()
+                .serverUrl(adminUrl)
+                .realm(realm)
+                .username(AdminPasswordCreds.getLoginUserName())
+                .password(AdminPasswordCreds.getPassword())
+                .clientId("admin-cli")
+                .resteasyClient(resteasyClient)
+                .build();
+    }
+
+    private static Keycloak getClient(String adminUrl, String realm, String accessToken) {
+
+        ResteasyClient resteasyClient = new ResteasyClientBuilder()
+                .connectionPoolSize(10)
+                .trustStore(loadKeyStore())
+                .build();
+        return KeycloakBuilder.builder()
+                .serverUrl(adminUrl)
+                .realm(realm)
+                .authorization(accessToken)
+                .resteasyClient(resteasyClient)
+                .build();
+    }
+
+    private static KeyStore loadKeyStore() {
+
+        InputStream is = null;
+        try {
+
+            String trustStorePath =  ServerSettings.getTrustStorePath();
+            File trustStoreFile = new File(trustStorePath);
+
+            if (trustStoreFile.exists()) {
+                logger.debug("Loading trust store file from path " + trustStorePath);
+                is = new FileInputStream(trustStorePath);
+            } else {
+                logger.debug("Trying to load trust store file form class path " + trustStorePath);
+                is = SecurityUtil.class.getClassLoader().getResourceAsStream(trustStorePath);
+                if (is != null) {
+                    logger.debug("Trust store file was loaded form class path " + trustStorePath);
+                }
+            }
+
+            if (is == null) {
+                throw new RuntimeException("Could not find a trust store file in path " + trustStorePath);
+            }
+
+            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+            ks.load(is, ServerSettings.getTrustStorePassword().toCharArray());
+            return ks;
+        } catch (Exception e) {
+            throw new RuntimeException("Failed to load trust store KeyStore instance", e);
+        } finally {
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                    logger.error("Failed to close trust store FileInputStream", e);
+                }
+            }
+        }
+    }
+
+    @Override
+    public Gateway addTenant(PasswordCredential isSuperAdminPasswordCreds, Gateway gatewayDetails) throws IamAdminServicesException {
+        Keycloak client = null;
+        try {
+            // get client
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), this.superAdminRealmId, isSuperAdminPasswordCreds);
+            // create realm
+            RealmRepresentation newRealmDetails = new RealmRepresentation();
+            newRealmDetails.setEnabled(true);
+            newRealmDetails.setId(gatewayDetails.getGatewayId());
+            newRealmDetails.setDisplayName(gatewayDetails.getGatewayName());
+            newRealmDetails.setRealm(gatewayDetails.getGatewayId());
+            // Following two settings allow duplicate email addresses
+            newRealmDetails.setLoginWithEmailAllowed(false);
+            newRealmDetails.setDuplicateEmailsAllowed(true);
+            // Default access token lifespan to 30 minutes, SSO session idle to 60 minutes
+            newRealmDetails.setAccessTokenLifespan(1800);
+            newRealmDetails.setSsoSessionIdleTimeout(3600);
+            RealmRepresentation realmWithRoles = TenantManagementKeycloakImpl.createDefaultRoles(newRealmDetails);
+            client.realms().create(realmWithRoles);
+            return gatewayDetails;
+        } catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting Iam server Url from property file, reason: " + ex.getMessage());
+            throw exception;
+        } catch (Exception ex){
+            logger.error("Error creating Realm in Keycloak Server, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error creating Realm in Keycloak Server, reason: " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+    public static RealmRepresentation createDefaultRoles(RealmRepresentation realmDetails){
+        List<RoleRepresentation> defaultRoles = new ArrayList<RoleRepresentation>();
+        RoleRepresentation adminRole = new RoleRepresentation();
+        adminRole.setName("admin");
+        adminRole.setDescription("Admin role for PGA users");
+        defaultRoles.add(adminRole);
+        RoleRepresentation adminReadOnlyRole = new RoleRepresentation();
+        adminReadOnlyRole.setName("admin-read-only");
+        adminReadOnlyRole.setDescription("Read only role for PGA Admin users");
+        defaultRoles.add(adminReadOnlyRole);
+        RoleRepresentation gatewayUserRole = new RoleRepresentation();
+        gatewayUserRole.setName("gateway-user");
+        gatewayUserRole.setDescription("default role for PGA users");
+        defaultRoles.add(gatewayUserRole);
+        RoleRepresentation pendingUserRole = new RoleRepresentation();
+        pendingUserRole.setName("user-pending");
+        pendingUserRole.setDescription("role for newly registered PGA users");
+        defaultRoles.add(pendingUserRole);
+        RoleRepresentation gatewayProviderRole = new RoleRepresentation();
+        gatewayProviderRole.setName("gateway-provider");
+        gatewayProviderRole.setDescription("role for gateway providers in the super-admin PGA");
+        defaultRoles.add(gatewayProviderRole);
+        RolesRepresentation rolesRepresentation = new RolesRepresentation();
+        rolesRepresentation.setRealm(defaultRoles);
+        realmDetails.setRoles(rolesRepresentation);
+        return realmDetails;
+    }
+
+    @Override
+    public boolean createTenantAdminAccount(PasswordCredential isSuperAdminPasswordCreds, Gateway gatewayDetails, String tenantAdminPassword) throws IamAdminServicesException{
+        Keycloak client = null;
+        try{
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), this.superAdminRealmId, isSuperAdminPasswordCreds);
+            UserRepresentation user = new UserRepresentation();
+            user.setUsername(gatewayDetails.getIdentityServerUserName());
+            user.setFirstName(gatewayDetails.getGatewayAdminFirstName());
+            user.setLastName(gatewayDetails.getGatewayAdminLastName());
+            user.setEmail(gatewayDetails.getGatewayAdminEmail());
+            user.setEmailVerified(true);
+            user.setEnabled(true);
+            Response httpResponse = client.realm(gatewayDetails.getGatewayId()).users().create(user);
+            logger.info("Tenant Admin account creation exited with code : " + httpResponse.getStatus()+" : " +httpResponse.getStatusInfo());
+            if (httpResponse.getStatus() == 201) { //HTTP code for record creation: HTTP 201
+                List<UserRepresentation> retrieveCreatedUserList = client.realm(gatewayDetails.getGatewayId()).users().search(user.getUsername(),
+                        user.getFirstName(),
+                        user.getLastName(),
+                        user.getEmail(),
+                        0, 1);
+                UserResource retrievedUser = client.realm(gatewayDetails.getGatewayId()).users().get(retrieveCreatedUserList.get(0).getId());
+
+                // Add user to the "admin" role
+                RoleResource adminRoleResource = client.realm(gatewayDetails.getGatewayId()).roles().get("admin");
+                retrievedUser.roles().realmLevel().add(Arrays.asList(adminRoleResource.toRepresentation()));
+
+                CredentialRepresentation credential = new CredentialRepresentation();
+                credential.setType(CredentialRepresentation.PASSWORD);
+                credential.setValue(tenantAdminPassword);
+                credential.setTemporary(false);
+                retrievedUser.resetPassword(credential);
+                List<ClientRepresentation> realmClients = client.realm(gatewayDetails.getGatewayId()).clients().findAll();
+                String realmManagementClientId=getRealmManagementClientId(client, gatewayDetails.getGatewayId());
+                for(ClientRepresentation realmClient : realmClients){
+                    if(realmClient.getClientId().equals("realm-management")){
+                        realmManagementClientId = realmClient.getId();
+                    }
+                }
+                retrievedUser.roles().clientLevel(realmManagementClientId).add(retrievedUser.roles().clientLevel(realmManagementClientId).listAvailable());
+                return true;
+            } else {
+                logger.error("Request for Tenant Admin Account Creation failed with HTTP code : " + httpResponse.getStatus());
+                logger.error("Reason for Tenant Admin account creation failure : " + httpResponse.getStatusInfo());
+                return false;
+            }
+        }catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting values from property file, reason " + ex.getMessage());
+            throw exception;
+        }catch (Exception ex){
+            logger.error("Error creating Realm Admin Account in keycloak server, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error creating Realm Admin Account in keycloak server, reason: " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+    @Override
+    public Gateway configureClient(PasswordCredential isSuperAdminPasswordCreds, Gateway gatewayDetails) throws IamAdminServicesException{
+        Keycloak client = null;
+        try{
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), this.superAdminRealmId, isSuperAdminPasswordCreds);
+            ClientRepresentation pgaClient = new ClientRepresentation();
+            pgaClient.setName("pga");
+            pgaClient.setClientId("pga");
+            pgaClient.setProtocol("openid-connect");
+            pgaClient.setStandardFlowEnabled(true);
+            pgaClient.setEnabled(true);
+            pgaClient.setAuthorizationServicesEnabled(true);
+            pgaClient.setDirectAccessGrantsEnabled(true);
+            pgaClient.setServiceAccountsEnabled(true);
+            pgaClient.setFullScopeAllowed(true);
+            pgaClient.setClientAuthenticatorType("client-secret");
+            List<String> redirectUris = new ArrayList<>();
+            if(gatewayDetails.getGatewayURL()!=null){
+                String gatewayURL = gatewayDetails.getGatewayURL();
+                // Remove trailing slash from gatewayURL
+                if(gatewayURL.endsWith("/")) {
+                    gatewayURL = gatewayURL.substring(0, gatewayURL.length() - 1);
+                }
+                // Add redirect URL after login
+                redirectUris.add(gatewayURL + "/callback-url"); // PGA
+                redirectUris.add(gatewayURL + "/auth/callback*"); // Django
+                // Add redirect URL after logout
+                redirectUris.add(gatewayURL);
+            } else {
+                logger.error("Request for Realm Client Creation failed, callback URL not present");
+                IamAdminServicesException ex = new IamAdminServicesException();
+                ex.setMessage("Gateway Url field in GatewayProfile cannot be empty, Realm Client creation failed");
+                throw ex;
+            }
+            pgaClient.setRedirectUris(redirectUris);
+            pgaClient.setPublicClient(false);
+            Response httpResponse = client.realms().realm(gatewayDetails.getGatewayId()).clients().create(pgaClient);
+            logger.info("Tenant Client configuration exited with code : " + httpResponse.getStatus()+" : " +httpResponse.getStatusInfo());
+
+            // Add the manage-users role to the web client
+            UserRepresentation serviceAccountUserRepresentation = getUserByUsername(client, gatewayDetails.getGatewayId(), "service-account-" + pgaClient.getClientId());
+            UserResource serviceAccountUser = client.realms().realm(gatewayDetails.getGatewayId()).users().get(serviceAccountUserRepresentation.getId());
+            String realmManagementClientId = getRealmManagementClientId(client, gatewayDetails.getGatewayId());
+            List<RoleRepresentation> manageUsersRole = serviceAccountUser.roles().clientLevel(realmManagementClientId).listAvailable()
+                    .stream()
+                    .filter(r -> r.getName().equals("manage-users"))
+                    .collect(Collectors.toList());
+            serviceAccountUser.roles().clientLevel(realmManagementClientId).add(manageUsersRole);
+
+            if(httpResponse.getStatus() == 201){
+                String ClientUUID = client.realms().realm(gatewayDetails.getGatewayId()).clients().findByClientId(pgaClient.getClientId()).get(0).getId();
+                CredentialRepresentation clientSecret = client.realms().realm(gatewayDetails.getGatewayId()).clients().get(ClientUUID).getSecret();
+                gatewayDetails.setOauthClientId(pgaClient.getClientId());
+                gatewayDetails.setOauthClientSecret(clientSecret.getValue());
+                return gatewayDetails;
+            } else {
+                logger.error("Request for Realm Client Creation failed with HTTP code : " + httpResponse.getStatus());
+                logger.error("Reason for Realm Client Creation failure : " + httpResponse.getStatusInfo());
+                return null;
+            }
+        }catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting values from property file, reason " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+    private static String getRealmManagementClientId(Keycloak client, String realmId) {
+        List<ClientRepresentation> realmClients = client.realm(realmId).clients().findAll();
+        String realmManagementClientId=null;
+        for(ClientRepresentation realmClient : realmClients){
+            if(realmClient.getClientId().equals("realm-management")){
+                realmManagementClientId = realmClient.getId();
+            }
+        }
+        return realmManagementClientId;
+    }
+
+    @Override
+    public boolean isUsernameAvailable(String accessToken, String tenantId, String username) throws IamAdminServicesException {
+        Keycloak client = null;
+        try {
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), tenantId, accessToken);
+            UserRepresentation userRepresentation = getUserByUsername(client, tenantId, username);
+            return userRepresentation == null;
+        } catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting values from property file, reason " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+    @Override
+    public boolean createUser(String accessToken, String tenantId, String username, String emailAddress, String firstName, String lastName, String newPassword) throws IamAdminServicesException{
+        Keycloak client = null;
+        try{
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), tenantId, accessToken);
+            UserRepresentation user = new UserRepresentation();
+            user.setUsername(username);
+            user.setFirstName(firstName);
+            user.setLastName(lastName);
+            user.setEmail(emailAddress);
+            user.setEnabled(false);
+            Response httpResponse = client.realm(tenantId).users().create(user);
+            if (httpResponse.getStatus() == 201) { //HTTP code for record creation: HTTP 201
+                List<UserRepresentation> retrieveCreatedUserList = client.realm(tenantId).users().search(user.getUsername(),
+                        user.getFirstName(),
+                        user.getLastName(),
+                        user.getEmail(),
+                        0, 1);
+                UserResource retrievedUser = client.realm(tenantId).users().get(retrieveCreatedUserList.get(0).getId());
+                CredentialRepresentation credential = new CredentialRepresentation();
+                credential.setType(CredentialRepresentation.PASSWORD);
+                credential.setValue(newPassword);
+                credential.setTemporary(false);
+                retrievedUser.resetPassword(credential);
+                return true;
+            } else {
+                logger.error("Request for user Account Creation failed with HTTP code : " + httpResponse.getStatus());
+                logger.error("Reason for user account creation failure : " + httpResponse.getStatusInfo());
+                return false;
+            }
+        }catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting values from property file, reason " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+    @Override
+    public boolean enableUserAccount(String accessToken, String tenantId, String username) throws IamAdminServicesException{
+        Keycloak client = null;
+        try{
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), tenantId, accessToken);
+            UserRepresentation userRepresentation = getUserByUsername(client, tenantId, username);
+            UserResource userResource = client.realm(tenantId).users().get(userRepresentation.getId());
+            UserRepresentation profile = userResource.toRepresentation();
+            profile.setEnabled(true);
+            // We require that a user verify their email before enabling the account
+            profile.setEmailVerified(true);
+            userResource.update(profile);
+            return true;
+        } catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting values from property file, reason " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+    @Override
+    public boolean isUserAccountEnabled(String accessToken, String tenantId, String username) throws IamAdminServicesException{
+        Keycloak client = null;
+        try{
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), tenantId, accessToken);
+            UserRepresentation userRepresentation = getUserByUsername(client, tenantId, username);
+            return userRepresentation != null && userRepresentation.isEnabled();
+        } catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting values from property file, reason " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+    @Override
+    public boolean isUserExist(String accessToken, String tenantId, String username) throws IamAdminServicesException {
+        Keycloak client = null;
+        try{
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), tenantId, accessToken);
+            UserRepresentation userRepresentation = getUserByUsername(client, tenantId, username);
+            return userRepresentation != null;
+        } catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting values from property file, reason " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+    @Override
+    public UserProfile getUser(String accessToken, String tenantId, String username) throws IamAdminServicesException {
+        Keycloak client = null;
+        try{
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), tenantId, accessToken);
+            UserRepresentation userRepresentation = getUserByUsername(client, tenantId, username);
+            return userRepresentation != null ? convertUserRepresentationToUserProfile(userRepresentation, tenantId) : null;
+        } catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting values from property file, reason " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+    @Override
+    public List<UserProfile> getUsers(String accessToken, String tenantId, int offset, int limit, String search)
+            throws IamAdminServicesException {
+        Keycloak client = null;
+        try{
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), tenantId, accessToken);
+            List<UserRepresentation> userRepresentationList = client.realm(tenantId).users().search(search, offset, limit);
+            return userRepresentationList.stream().map(ur -> convertUserRepresentationToUserProfile(ur, tenantId))
+                    .collect(Collectors.toList());
+        } catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting values from property file, reason " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+    @Override
+    public boolean resetUserPassword(String accessToken, String tenantId, String username, String newPassword) throws IamAdminServicesException{
+        Keycloak client = null;
+        try{
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), tenantId, accessToken);
+            UserRepresentation userRepresentation = getUserByUsername(client, tenantId, username);
+            if(userRepresentation != null)
+            {
+                UserResource retrievedUser = client.realm(tenantId).users().get(userRepresentation.getId());
+                CredentialRepresentation credential = new CredentialRepresentation();
+                credential.setType(CredentialRepresentation.PASSWORD);
+                credential.setValue(newPassword);
+                credential.setTemporary(false);
+                retrievedUser.resetPassword(credential);
+                // Remove the UPDATE_PASSWORD required action
+                userRepresentation = retrievedUser.toRepresentation();
+                userRepresentation.getRequiredActions().remove("UPDATE_PASSWORD");
+                retrievedUser.update(userRepresentation);
+                return true;
+            }else{
+                logger.error("requested User not found");
+                return false;
+            }
+        } catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting values from property file, reason " + ex.getMessage());
+            throw exception;
+        } catch (Exception ex){
+            logger.error("Error resetting user password in keycloak server, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error resetting user password in keycloak server, reason: " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+    @Override
+    public List<UserProfile> findUser(String accessToken, String tenantId, String email, String userName) throws IamAdminServicesException{
+        Keycloak client = null;
+        try{
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), tenantId, accessToken);
+            List<UserRepresentation> retrieveUserList = client.realm(tenantId).users().search(userName,
+                    null,
+                    null,
+                    email,
+                    0, 1);
+            if(!retrieveUserList.isEmpty())
+            {
+                List<UserProfile> userList = new ArrayList<>();
+                for(UserRepresentation user : retrieveUserList){
+                    UserProfile profile = new UserProfile();
+                    profile.setUserId(user.getUsername());
+                    profile.setFirstName(user.getFirstName());
+                    profile.setLastName(user.getLastName());
+                    profile.setEmails(Arrays.asList(new String[]{user.getEmail()}));
+                    userList.add(profile);
+                }
+                return userList;
+            }else{
+                logger.error("requested User not found");
+                return null;
+            }
+        } catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting values from property file, reason " + ex.getMessage());
+            throw exception;
+        } catch (Exception ex){
+            logger.error("Error finding user in keycloak server, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error finding user in keycloak server, reason: " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+    @Override
+    public void updateUserProfile(String accessToken, String tenantId, String username, UserProfile userDetails) throws IamAdminServicesException {
+
+        Keycloak client = null;
+        try{
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), tenantId, accessToken);
+            UserRepresentation userRepresentation = getUserByUsername(client, tenantId, username);
+            if(userRepresentation != null)
+            {
+                userRepresentation.setFirstName(userDetails.getFirstName());
+                userRepresentation.setLastName(userDetails.getLastName());
+                userRepresentation.setEmail(userDetails.getEmails().get(0));
+                UserResource userResource = client.realm(tenantId).users().get(userRepresentation.getId());
+                userResource.update(userRepresentation);
+            }else{
+                throw new IamAdminServicesException("User [" + username + "] wasn't found in Keycloak!");
+            }
+        } catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting values from property file, reason " + ex.getMessage());
+            throw exception;
+        } catch (Exception ex){
+            logger.error("Error updating user profile in keycloak server, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error updating user profile in keycloak server, reason: " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+    @Override
+    public boolean addRoleToUser(PasswordCredential realmAdminCreds, String tenantId, String username, String roleName) throws IamAdminServicesException {
+
+        Keycloak client = null;
+        try{
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), tenantId, realmAdminCreds);
+            List<UserRepresentation> retrieveCreatedUserList = client.realm(tenantId).users().search(username,
+                    null,
+                    null,
+                    null,
+                    0, 1);
+            UserResource retrievedUser = client.realm(tenantId).users().get(retrieveCreatedUserList.get(0).getId());
+
+            // Add user to the role
+            RoleResource roleResource = client.realm(tenantId).roles().get(roleName);
+            retrievedUser.roles().realmLevel().add(Arrays.asList(roleResource.toRepresentation()));
+            return true;
+        } catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting values from property file, reason " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+    @Override
+    public boolean removeRoleFromUser(PasswordCredential realmAdminCreds, String tenantId, String username, String roleName) throws IamAdminServicesException {
+
+        Keycloak client = null;
+        try{
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), tenantId, realmAdminCreds);
+            List<UserRepresentation> retrieveCreatedUserList = client.realm(tenantId).users().search(username,
+                    null,
+                    null,
+                    null,
+                    0, 1);
+            UserResource retrievedUser = client.realm(tenantId).users().get(retrieveCreatedUserList.get(0).getId());
+
+            // Remove role from user
+            RoleResource roleResource = client.realm(tenantId).roles().get(roleName);
+            retrievedUser.roles().realmLevel().remove(Arrays.asList(roleResource.toRepresentation()));
+            return true;
+        } catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting values from property file, reason " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+    }
+
+    // TODO: this is needed for migrating from roles to group-based auth but after migration we can remove this
+    @Override
+    public List<UserProfile> getUsersWithRole(PasswordCredential realmAdminCreds, String tenantId, String roleName) throws IamAdminServicesException {
+        Keycloak client = null;
+        try{
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), tenantId, realmAdminCreds);
+            // FIXME: this only searches through the most recent 100 users for the given role (assuming there are no more than 10,000 users in the gateway)
+            int totalUserCount = client.realm(tenantId).users().count();
+            logger.debug("getUsersWithRole: totalUserCount=" + totalUserCount);
+            // Load all users in batches
+            List<UserRepresentation> allUsers = new ArrayList<>();
+            int userBatchSize = 100;
+            for (int start = 0; start < totalUserCount; start=start+userBatchSize) {
+
+                logger.debug("getUsersWithRole: fetching " + userBatchSize + " users...");
+                allUsers.addAll(client.realm(tenantId).users().search(null,
+                        null,
+                        null,
+                        null,
+                        start, userBatchSize));
+            }
+            logger.debug("getUsersWithRole: all users count=" + allUsers.size());
+            allUsers.sort((a, b) -> a.getCreatedTimestamp() - b.getCreatedTimestamp() > 0 ? -1 : 1);
+            // The 100 most recently created users
+            List<UserRepresentation> mostRecentUsers = allUsers.subList(0, Math.min(allUsers.size(), 100));
+            logger.debug("getUsersWithRole: most recent users count=" + mostRecentUsers.size());
+
+            List<UserProfile> usersWithRole = new ArrayList<>();
+            for (UserRepresentation user: mostRecentUsers) {
+                UserResource userResource = client.realm(tenantId).users().get(user.getId());
+
+                List<RoleRepresentation> roleRepresentations = userResource.roles().realmLevel().listAll();
+                for (RoleRepresentation roleRepresentation : roleRepresentations){
+                    if (roleRepresentation.getName().equals(roleName)) {
+                        usersWithRole.add(convertUserRepresentationToUserProfile(user, tenantId));
+                        break;
+                    }
+                }
+            }
+            logger.debug("getUsersWithRole: most recent users with role count=" + usersWithRole.size());
+            return usersWithRole;
+        } catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting values from property file, reason " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                logger.debug("getUsersWithRole: closing client...");
+                client.close();
+                logger.debug("getUsersWithRole: client closed");
+            }
+        }
+    }
+
+    public List<String> getUserRoles(PasswordCredential realmAdminCreds, String tenantId, String username) throws IamAdminServicesException {
+        Keycloak client = null;
+        try{
+            client = TenantManagementKeycloakImpl.getClient(ServerSettings.getIamServerUrl(), tenantId, realmAdminCreds);
+            List<UserRepresentation> userRepresentationList = client.realm(tenantId).users().search(username,
+                    null,
+                    null,
+                    null,
+                    0, 1);
+            if (userRepresentationList.isEmpty()) {
+                logger.warn("No Keycloak user found for username [" + username + "] in tenant [" + tenantId + "].");
+                return null;
+            }
+            UserResource retrievedUser = client.realm(tenantId).users().get(userRepresentationList.get(0).getId());
+            return retrievedUser.roles().realmLevel().listAll()
+                    .stream()
+                    .map(roleRepresentation -> roleRepresentation.getName())
+                    .collect(Collectors.toList());
+        } catch (ApplicationSettingsException ex) {
+            logger.error("Error getting values from property file, reason: " + ex.getMessage(), ex);
+            IamAdminServicesException exception = new IamAdminServicesException();
+            exception.setMessage("Error getting values from property file, reason " + ex.getMessage());
+            throw exception;
+        } finally {
+            if (client != null) {
+                logger.debug("getUserRoles: closing client...");
+                client.close();
+                logger.debug("getUserRoles: client closed");
+            }
+        }
+    }
+
+    private UserProfile convertUserRepresentationToUserProfile(UserRepresentation userRepresentation, String tenantId) {
+
+        UserProfile profile = new UserProfile();
+        profile.setAiravataInternalUserId(userRepresentation.getUsername() + "@" + tenantId);
+        profile.setGatewayId(tenantId);
+        profile.setUserId(userRepresentation.getUsername());
+        profile.setFirstName(userRepresentation.getFirstName());
+        profile.setLastName(userRepresentation.getLastName());
+        profile.setEmails(Arrays.asList(new String[]{userRepresentation.getEmail()}));
+        profile.setCreationTime(userRepresentation.getCreatedTimestamp());
+
+        // Just default these. UserProfile isn't a great data model for this data since it isn't actually the Airavata UserProfile
+        profile.setLastAccessTime(0);
+        profile.setValidUntil(0);
+        // Use state field to indicate whether user has been enabled or email verified in Keycloak
+        if (userRepresentation.isEnabled()) {
+            profile.setState(Status.ACTIVE);
+        } else if (userRepresentation.isEmailVerified()) {
+            profile.setState(Status.CONFIRMED);
+        } else {
+            profile.setState(Status.PENDING_CONFIRMATION);
+        }
+
+        return profile;
+    }
+
+    private static UserRepresentation getUserByUsername(Keycloak client, String tenantId, String username) {
+
+        // Searching for users by username returns also partial matches, so need to filter down to an exact match if it exists
+        List<UserRepresentation> userResourceList = client.realm(tenantId).users().search(
+                username, null, null, null, null, null);
+        for (UserRepresentation userRepresentation : userResourceList) {
+            if (userRepresentation.getUsername().equals(username)) {
+                return userRepresentation;
+            }
+        }
+        return null;
+    }
+
+    public static void main(String[] args) throws IamAdminServicesException, ApplicationSettingsException {
+        TenantManagementKeycloakImpl tenantManagementKeycloak = new TenantManagementKeycloakImpl();
+        ServerSettings.setSetting("trust.store", "./modules/configuration/server/src/main/resources/client_truststore.jks");
+        ServerSettings.setSetting("trust.store.password", "airavata");
+        ServerSettings.setSetting("iam.server.url", "");
+        String accessToken = "";
+        String tenantId = "";
+        String username = "";
+        boolean isUsernameAvailable = tenantManagementKeycloak.isUsernameAvailable(accessToken, tenantId, username);
+        System.out.println("Username " + username + " is " + (isUsernameAvailable ? "": "NOT ") + "available");
+    }
+}
diff --git a/custos-services/profile-service/iam-admin-services-core/src/main/java/org/apache/custos/service/profile/iam/admin/services/core/interfaces/TenantManagementInterface.java b/custos-services/profile-service/iam-admin-services-core/src/main/java/org/apache/custos/service/profile/iam/admin/services/core/interfaces/TenantManagementInterface.java
new file mode 100644
index 0000000..d809ad2
--- /dev/null
+++ b/custos-services/profile-service/iam-admin-services-core/src/main/java/org/apache/custos/service/profile/iam/admin/services/core/interfaces/TenantManagementInterface.java
@@ -0,0 +1,206 @@
+/*
+ *
+ * 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 org.apache.custos.service.profile.iam.admin.services.core.interfaces;
+
+import org.apache.custos.profile.models.tenant.PasswordCredential;
+import org.apache.custos.profile.models.user.UserProfile;
+import org.apache.custos.profile.models.workspace.Gateway;
+import org.apache.custos.service.profile.iam.admin.services.cpi.exception.IamAdminServicesException;
+
+import java.util.List;
+
+public interface TenantManagementInterface {
+
+    /**
+     * Method to add Identity server tenant for Airavata gateway creation.
+     *
+     * @param isSuperAdminPasswordCreds identity server super admin credentials
+     * @param gatewayDetails gateway details from workspace catalog
+     * @return Gateway object.
+     */
+    Gateway addTenant(PasswordCredential isSuperAdminPasswordCreds, Gateway gatewayDetails) throws IamAdminServicesException;
+
+    /**
+     * Method to add tenant Admin account in Identity Server.
+     *
+     * @param isSuperAdminPasswordCreds identity server super admin credentials
+     * @param gatewayDetails gateway details from workspace catalog
+     * @param gatewayAdminPassword password to use when creating tenant admin account
+     * @return Gateway object.
+     */
+    boolean createTenantAdminAccount(PasswordCredential isSuperAdminPasswordCreds, Gateway gatewayDetails, String gatewayAdminPassword) throws IamAdminServicesException;
+
+    /**
+     * Method to configure application client in Identity Server
+     *
+     * @param isSuperAdminPasswordCreds identity server super admin credentials
+     * @param gatewayDetails gateway details from workspace catalog
+     * @return Gateway object.
+     */
+    Gateway configureClient(PasswordCredential isSuperAdminPasswordCreds, Gateway gatewayDetails) throws IamAdminServicesException;
+
+    /**
+     * Check if username is available to be used for creating a new user account.
+     * @param accessToken needs to have access to searching across users by username
+     * @param tenantId
+     * @param username
+     * @return
+     */
+    boolean isUsernameAvailable(String accessToken, String tenantId, String username) throws IamAdminServicesException;
+
+    /**
+     * Method to create user in Identity Server
+     *
+     * @param accessToken
+     * @param tenantId
+     * @param username
+     * @param emailAddress
+     * @param firstName
+     * @param lastName
+     * @param newPassword
+     * @return true if user created
+     * @throws IamAdminServicesException
+     */
+    boolean createUser(String accessToken, String tenantId, String username, String emailAddress, String firstName, String lastName, String newPassword) throws IamAdminServicesException;
+
+    /**
+     * Method to enable user in Identity Server
+     *
+     * @param accessToken
+     * @param tenantId
+     * @param username
+     * @return boolean.
+     */
+    boolean enableUserAccount(String accessToken, String tenantId, String username) throws IamAdminServicesException;
+
+    /**
+     * Method to check if user is enabled in Identity Server
+     *
+     * @param accessToken
+     * @param tenantId
+     * @param username
+     * @return boolean.
+     */
+    boolean isUserAccountEnabled(String accessToken, String tenantId, String username) throws IamAdminServicesException;
+
+    /**
+     * Return whether user exists with username.
+     *
+     * @param accessToken
+     * @param tenantId
+     * @param username
+     * @return
+     */
+    boolean isUserExist(String accessToken, String tenantId, String username) throws IamAdminServicesException;
+
+    /**
+     * Get user profile information from Identity Server
+     *
+     * @param accessToken
+     * @param tenantId
+     * @param username
+     * @return
+     */
+    UserProfile getUser(String accessToken, String tenantId, String username) throws IamAdminServicesException;
+
+    /**
+     * Get a paginated list of user profiles from Identity Server
+     * 
+     * @param accessToken
+     * @param tenantId
+     * @param offset
+     * @param limit
+     * @param search String - optional, if specified used to search user profiles
+     * @return
+     * @throws IamAdminServicesException
+     */
+    List<UserProfile> getUsers(String accessToken, String tenantId, int offset, int limit, String search) throws IamAdminServicesException;
+
+    /**
+     * Method to reset user password in Identity Server
+     *
+     * @param accessToken
+     * @param tenantId
+     * @param username
+     * @param newPassword
+     * @return boolean
+     */
+    boolean resetUserPassword(String accessToken, String tenantId, String username, String newPassword) throws IamAdminServicesException;
+
+    /**
+     * Method to find user in Identity Server
+     *
+     * @param accessToken
+     * @param tenantId required
+     * @param email required
+     * @param username can be null
+     * @return Gateway object.
+     */
+    List<UserProfile> findUser(String accessToken, String tenantId, String email, String username) throws IamAdminServicesException;
+
+    /**
+     * Update the user's profile in the Identity Server
+     * @param accessToken
+     * @param tenantId
+     * @param username
+     * @param userDetails
+     */
+    void updateUserProfile(String accessToken, String tenantId, String username, UserProfile userDetails) throws IamAdminServicesException;
+
+    /**
+     * Add the given role to the user.
+     *
+     * @param realmAdminCreds
+     * @param tenantId
+     * @param username
+     * @param roleName
+     * @return
+     * @throws IamAdminServicesException
+     */
+    @Deprecated
+    boolean addRoleToUser(PasswordCredential realmAdminCreds, String tenantId, String username, String roleName) throws IamAdminServicesException;
+
+    /**
+     * Remove the given role from the user.
+     *
+     * @param realmAdminCreds
+     * @param tenantId
+     * @param username
+     * @param roleName
+     * @return
+     * @throws IamAdminServicesException
+     */
+    @Deprecated
+    boolean removeRoleFromUser(PasswordCredential realmAdminCreds, String tenantId, String username, String roleName) throws IamAdminServicesException;
+
+    /**
+     * Get all users having the given role.
+     *
+     * @param realmAdminCreds
+     * @param tenantId
+     * @param roleName
+     * @return
+     * @throws IamAdminServicesException
+     */
+    @Deprecated
+    List<UserProfile> getUsersWithRole(PasswordCredential realmAdminCreds, String tenantId, String roleName) throws IamAdminServicesException;
+}
diff --git a/custos-services/profile-service/iam-admin-services-core/src/test/java/org/apache/custos/service/profile/iam/admin/services/core/tests/SetupNewGateway.java b/custos-services/profile-service/iam-admin-services-core/src/test/java/org/apache/custos/service/profile/iam/admin/services/core/tests/SetupNewGateway.java
new file mode 100644
index 0000000..387ed1c
--- /dev/null
+++ b/custos-services/profile-service/iam-admin-services-core/src/test/java/org/apache/custos/service/profile/iam/admin/services/core/tests/SetupNewGateway.java
@@ -0,0 +1,141 @@
+package org.apache.custos.service.profile.iam.admin.services.core.tests;
+
+import org.apache.custos.profile.models.tenant.PasswordCredential;
+import org.apache.custos.profile.models.user.UserProfile;
+import org.apache.custos.profile.models.workspace.Gateway;
+import org.apache.custos.service.profile.iam.admin.services.core.impl.TenantManagementKeycloakImpl;
+import org.apache.custos.service.profile.iam.admin.services.cpi.exception.IamAdminServicesException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SetupNewGateway {
+
+    private final static Logger logger = LoggerFactory.getLogger(SetupNewGateway.class);
+
+    public static void main(String[] args) {
+        findUser();
+//        final PasswordCredential tenantAdminCreds = createTenantAdminCreds("tenant", "admin", "admin-password");
+//        getUserRoles(tenantAdminCreds, "username");
+    }
+
+    public static void setUpGateway(){
+        Gateway testGateway = new Gateway();
+        testGateway.setGatewayId("maven.test.gateway");
+        testGateway.setGatewayName("maven test gateway");
+        testGateway.setIdentityServerUserName("mavenTest");
+        testGateway.setGatewayAdminFirstName("Maven");
+        testGateway.setGatewayAdminLastName("Test");
+        testGateway.setGatewayAdminEmail("some.man@gmail.com");
+        PasswordCredential superAdminCreds = new PasswordCredential();
+        superAdminCreds.setGatewayId(testGateway.getGatewayId());
+        superAdminCreds.setDescription("test credentials for IS admin creation");
+        superAdminCreds.setLoginUserName("airavataAdmin");
+        superAdminCreds.setPassword("Airavata@123");
+        superAdminCreds.setPortalUserName("superAdmin");
+        TenantManagementKeycloakImpl client = new TenantManagementKeycloakImpl();
+        try {
+            client.addTenant(superAdminCreds, testGateway);
+            if (!client.createTenantAdminAccount(superAdminCreds, testGateway, "Test@123")) {
+                logger.error("Admin account creation failed !!, please refer error logs for reason");
+            }
+            Gateway gatewayWithIdAndSecret = client.configureClient(superAdminCreds, testGateway);
+            System.out.println(gatewayWithIdAndSecret.getOauthClientId());
+            System.out.println(gatewayWithIdAndSecret.getOauthClientSecret());
+        } catch (IamAdminServicesException ex) {
+            logger.error("Gateway Setup Failed, reason: " + ex.getCause(), ex);
+        }
+    }
+     public static void UserRegistration(){
+         UserProfile user = new UserProfile();
+         user.setUserId("testuser");
+         user.setFirstName("test-firstname");
+         user.setLastName("test-lastname");
+         List<String> emails = new ArrayList<>();
+         emails.add("some.man@outlook.com");
+         user.setGatewayId("maven.test.gateway");
+         user.setEmails(emails);
+        PasswordCredential tenantAdminCreds = new PasswordCredential();
+         tenantAdminCreds.setGatewayId(user.getGatewayId());
+         tenantAdminCreds.setDescription("test credentials for tenant admin creation");
+         tenantAdminCreds.setLoginUserName("mavenTest");
+         tenantAdminCreds.setPassword("Test@1234");
+         tenantAdminCreds.setPortalUserName("TenantAdmin");
+
+         TenantManagementKeycloakImpl client = new TenantManagementKeycloakImpl();
+         try {
+             // FIXME: get an access token from tenant admin creds
+             String accessToken = "";
+             client.createUser(accessToken, user.getGatewayId(), user.getUserId(), user.getEmails().get(0), user.getFirstName(), user.getLastName(),"test@123");
+             client.enableUserAccount(accessToken, user.getGatewayId(), user.getUserId());
+         } catch (IamAdminServicesException e) {
+             e.printStackTrace();
+         }
+     }
+
+//     public static void resetPassword(){
+//         UserProfile user = new UserProfile();
+//         user.setUserId("testuser");
+//         List<String> emails = new ArrayList<>();
+//         emails.add("some.man@outlook.com");
+//         user.setGatewayId("maven.test.gateway");
+//         user.setEmails(emails);
+//         TenantManagementKeycloakImpl client = new TenantManagementKeycloakImpl();
+//         try {
+//             PasswordCredential tenantAdminCreds = new PasswordCredential();
+//             tenantAdminCreds.setGatewayId(user.getGatewayId());
+//             tenantAdminCreds.setDescription("test credentials for tenant admin creation");
+//             tenantAdminCreds.setLoginUserName("mavenTest");
+//             tenantAdminCreds.setPassword("Test@1234");
+//             tenantAdminCreds.setPortalUserName("TenantAdmin");
+//             client.resetUserPassword(tenantAdminCreds,user,"test@123");
+//         } catch (IamAdminServicesException e) {
+//             e.printStackTrace();
+//         }
+//     }
+
+     public static void findUser(){
+         UserProfile user = new UserProfile();
+
+         List<String> emails = new ArrayList<>();
+         emails.add("some.man@outlook.com");
+         user.setGatewayId("maven.test.gateway");
+         user.setEmails(emails);
+         TenantManagementKeycloakImpl client = new TenantManagementKeycloakImpl();
+         try {
+             PasswordCredential tenantAdminCreds = new PasswordCredential();
+             tenantAdminCreds.setGatewayId(user.getGatewayId());
+             tenantAdminCreds.setDescription("test credentials for tenant admin creation");
+             tenantAdminCreds.setLoginUserName("mavenTest");
+             tenantAdminCreds.setPassword("Test@1234");
+             tenantAdminCreds.setPortalUserName("TenantAdmin");
+             // FIXME: get an access token from tenant admin creds
+             String accessToken = "";
+             List<UserProfile> list = client.findUser(accessToken,"maven.test.gateway","some.man@outlook.com",null);
+             System.out.println(list.get(0).getUserId());
+         } catch (IamAdminServicesException e) {
+             e.printStackTrace();
+         }
+     }
+
+     public static void getUserRoles(PasswordCredential tenantAdminCreds, String username) {
+         TenantManagementKeycloakImpl keycloakClient = new TenantManagementKeycloakImpl();
+
+         try {
+             List<String> roleNames = keycloakClient.getUserRoles(tenantAdminCreds, tenantAdminCreds.getGatewayId(), username);
+             System.out.println("Roles=" + roleNames);
+         } catch (IamAdminServicesException e) {
+             e.printStackTrace();
+         }
+     }
+
+    private static PasswordCredential createTenantAdminCreds(String tenantId, String username, String password) {
+        PasswordCredential tenantAdminCreds = new PasswordCredential();
+        tenantAdminCreds.setGatewayId(tenantId);
+        tenantAdminCreds.setLoginUserName(username);
+        tenantAdminCreds.setPassword(password);
+        return tenantAdminCreds;
+    }
+}
diff --git a/custos-services/profile-service/pom.xml b/custos-services/profile-service/pom.xml
new file mode 100644
index 0000000..64056a6
--- /dev/null
+++ b/custos-services/profile-service/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>custos-services</artifactId>
+        <groupId>org.apache.custos</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>profile-service</artifactId>
+    <packaging>pom</packaging>
+    <name>profile-service</name>
+    <modules>
+        <module>iam-admin-services-core</module>
+        <module>profile-tenant-core</module>
+        <module>profile-user-core</module>
+        <module>profile-service-server</module>
+        <module>profile-service-commons</module>
+        <module>profile-service-client-sdks</module>
+        <module>profile-service-stubs</module>
+        <module>profile-service-models</module>
+    </modules>
+</project>
\ No newline at end of file
diff --git a/custos-services/profile-service/profile-service-client-sdks/java-client-samples/pom.xml b/custos-services/profile-service/profile-service-client-sdks/java-client-samples/pom.xml
new file mode 100644
index 0000000..01d0bee
--- /dev/null
+++ b/custos-services/profile-service/profile-service-client-sdks/java-client-samples/pom.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--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. -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>profile-service-client-sdks</artifactId>
+        <groupId>org.apache.custos</groupId>
+        <version>1.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <name>Profile Service Client Samples</name>
+    <artifactId>profile-service-client-samples</artifactId>
+    <packaging>jar</packaging>
+    <url>http://airavata.apache.org/</url>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.custos</groupId>
+            <artifactId>profile-service-stubs</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/custos-services/profile-service/profile-service-client-sdks/java-client-samples/src/main/java/org/apache/custos/service/profile/client/samples/GroupManagerSample.java b/custos-services/profile-service/profile-service-client-sdks/java-client-samples/src/main/java/org/apache/custos/service/profile/client/samples/GroupManagerSample.java
new file mode 100644
index 0000000..4d108e4
--- /dev/null
+++ b/custos-services/profile-service/profile-service-client-sdks/java-client-samples/src/main/java/org/apache/custos/service/profile/client/samples/GroupManagerSample.java
@@ -0,0 +1,41 @@
+package org.apache.custos.service.profile.client.samples;
+
+import org.apache.airavata.common.utils.Constants;
+import org.apache.airavata.model.security.AuthzToken;
+import org.apache.custos.service.profile.client.ProfileServiceClientFactory;
+import org.apache.custos.service.profile.groupmanager.cpi.GroupManagerService;
+import org.apache.custos.service.profile.client.util.ProfileServiceClientUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class GroupManagerSample {
+
+    private static final Logger logger = LoggerFactory.getLogger(UserProfileSample.class);
+    private static GroupManagerService.Client groupMangerClient;
+    private static String testGatewayId = "test-gateway-465";
+    private static AuthzToken authzToken = new AuthzToken("empy_token");
+
+    public static void main(String args[]) throws Exception {
+        try {
+            String profileServiceServerHost = ProfileServiceClientUtil.getProfileServiceServerHost();
+            int profileServiceServerPort = ProfileServiceClientUtil.getProfileServiceServerPort();
+
+            groupMangerClient = ProfileServiceClientFactory.createGroupManagerServiceClient(profileServiceServerHost, profileServiceServerPort);
+            Map<String, String> claimsMap = new HashMap<>();
+            claimsMap.put(Constants.GATEWAY_ID,testGatewayId);
+            authzToken.setClaimsMap(claimsMap);
+
+            //NOTE: Only these two methods can be tested as other methods require us to create a group.
+            // createGroup() needs createUser() to be executed. Currently ownerId is set from createUser()
+            // method which requires a sharingServiceClient. Hence, verifying only this method for now.
+            System.out.println("hasAdminAccess() should return [false]: "+ groupMangerClient.hasAdminAccess(authzToken,"test-group-1", "test-user-1"));
+        }
+        catch (Exception ex) {
+            ex.printStackTrace();
+            logger.error("GroupManager client-sample Exception: " + ex, ex);
+        }
+    }
+}
diff --git a/custos-services/profile-service/profile-service-client-sdks/java-client-samples/src/main/java/org/apache/custos/service/profile/client/samples/TenantProfileSample.java b/custos-services/profile-service/profile-service-client-sdks/java-client-samples/src/main/java/org/apache/custos/service/profile/client/samples/TenantProfileSample.java
new file mode 100644
index 0000000..da4ed19
--- /dev/null
+++ b/custos-services/profile-service/profile-service-client-sdks/java-client-samples/src/main/java/org/apache/custos/service/profile/client/samples/TenantProfileSample.java
@@ -0,0 +1,61 @@
+package org.apache.custos.service.profile.client.samples;
+
+import org.apache.airavata.model.security.AuthzToken;
+import org.apache.airavata.model.workspace.Gateway;
+import org.apache.airavata.model.workspace.GatewayApprovalStatus;
+import org.apache.custos.service.profile.client.ProfileServiceClientFactory;
+import org.apache.custos.service.profile.tenant.cpi.TenantProfileService;
+import org.apache.custos.service.profile.client.util.ProfileServiceClientUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * Created by goshenoy on 3/30/17.
+ */
+public class TenantProfileSample {
+    private static final Logger logger = LoggerFactory.getLogger(TenantProfileSample.class);
+    private static TenantProfileService.Client tenantProfileClient;
+    private static String testGatewayId = null;
+    private static AuthzToken authzToken = new AuthzToken("empy_token");
+
+    public static void main(String[] args) throws Exception {
+        try {
+            String profileServiceServerHost = ProfileServiceClientUtil.getProfileServiceServerHost();
+            int profileServiceServerPort = ProfileServiceClientUtil.getProfileServiceServerPort();
+
+            tenantProfileClient = ProfileServiceClientFactory.createTenantProfileServiceClient(profileServiceServerHost, profileServiceServerPort);
+
+            // test addGateway
+            testGatewayId = tenantProfileClient.addGateway(authzToken, getGateway("465"));
+            assert (testGatewayId != null) : "Gateway creation failed!";
+            System.out.println("Gateway created with gatewayId: " + testGatewayId);
+
+
+        } catch (Exception ex) {
+            logger.error("TenantProfile client-sample Exception: " + ex, ex);
+        }
+    }
+
+    private static Gateway getGateway(String gatewayId) {
+        // get random value for userId
+        int gatewayIdValue = ThreadLocalRandom.current().nextInt(1000);
+
+        if (gatewayId != null) {
+            gatewayIdValue = Integer.parseInt(gatewayId.replaceAll("test-gateway-", ""));
+        }
+
+        Gateway gateway = new Gateway();
+        gateway.setGatewayId("test-gateway-" + gatewayIdValue);
+        gateway.setGatewayApprovalStatus(GatewayApprovalStatus.APPROVED);
+        gateway.setGatewayName("test-gateway-name");
+        gateway.setDomain("test-gateway-domain");
+        gateway.setEmailAddress("test-gateway-" + gatewayIdValue + "@domain.com");
+        gateway.setGatewayURL("test-gateway-" + gatewayIdValue + ".domain.com");
+        gateway.setGatewayAdminFirstName("test-gateway-admin-fname");
+        gateway.setGatewayAdminLastName("test-gateway-admin-lname");
+        gateway.setGatewayAdminEmail("test-gateway-admin@email.domain.com");
+        return gateway;
+    }
+}
diff --git a/custos-services/profile-service/profile-service-client-sdks/java-client-samples/src/main/java/org/apache/custos/service/profile/client/samples/UserProfileSample.java b/custos-services/profile-service/profile-service-client-sdks/java-client-samples/src/main/java/org/apache/custos/service/profile/client/samples/UserProfileSample.java
new file mode 100644
index 0000000..b6d9b59
--- /dev/null
+++ b/custos-services/profile-service/profile-service-client-sdks/java-client-samples/src/main/java/org/apache/custos/service/profile/client/samples/UserProfileSample.java
@@ -0,0 +1,121 @@
+package org.apache.custos.service.profile.client.samples;
+
+import org.apache.airavata.model.security.AuthzToken;
+import org.apache.airavata.model.user.*;
+import org.apache.custos.service.profile.client.ProfileServiceClientFactory;
+import org.apache.custos.service.profile.user.cpi.UserProfileService;
+import org.apache.custos.service.profile.client.util.ProfileServiceClientUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * Created by goshenoy on 3/23/17.
+ */
+public class UserProfileSample {
+
+    private static final Logger logger = LoggerFactory.getLogger(UserProfileSample.class);
+    private static UserProfileService.Client userProfileClient;
+    private static String testUserId = null;
+    private static String testGatewayId = "test-gateway-465";
+    private static AuthzToken authzToken = new AuthzToken("empy_token");
+
+    /**
+     * Performs the following operations in sequence:
+     *  1. create new user
+     *  2. find user created
+     *  3. update created user's name
+     *  4. find all users in gateway
+     *  5. find created user by name
+     *  6. delete created user
+     *  7. check if user exists
+     * @param args
+     * @throws Exception
+     */
+    public static void main(String[] args) throws Exception {
+        try {
+            String profileServiceServerHost = ProfileServiceClientUtil.getProfileServiceServerHost();
+            int profileServiceServerPort = ProfileServiceClientUtil.getProfileServiceServerPort();
+
+            userProfileClient = ProfileServiceClientFactory.createUserProfileServiceClient(profileServiceServerHost, profileServiceServerPort);
+
+            // test add-user-profile
+            testUserId = userProfileClient.addUserProfile(authzToken, getUserProfile(null));
+            assert (testUserId != null) : "User creation failed. Null userId returned!";
+            System.out.println("User created with userId: " + testUserId);
+
+            // test find-user-profile
+            UserProfile userProfile = userProfileClient.getUserProfileById(authzToken, testUserId, testGatewayId);
+            assert (userProfile != null) : "Could not find user with userId: " + testUserId + ", and gatewayID: " + testGatewayId;
+            System.out.println("UserProfile: " + userProfile);
+
+            // test update-user-profile : update name
+            userProfile = getUserProfile(testUserId);
+            String newFName = userProfile.getFirstName().replaceAll("fname", "fname-updated");
+            userProfile.setFirstName(newFName);
+            boolean updateSuccess = userProfileClient.updateUserProfile(authzToken, userProfile);
+            assert (updateSuccess) : "User update with new firstName: [" + newFName + "], Failed!";
+            System.out.println("User update with new firstName: [" + newFName + "], Successful!");
+
+            // test get-all-userprofiles
+            List<UserProfile> userProfileList = userProfileClient.getAllUserProfilesInGateway(authzToken, testGatewayId, 0, 5);
+            assert (userProfileList != null && !userProfileList.isEmpty()) : "Failed to retrieve users for gateway!";
+            System.out.println("Printing userList retrieved..");
+            for (UserProfile userProfile1 : userProfileList) {
+                System.out.println("\t [UserProfile] userId: " + userProfile1.getUserId());
+            }
+
+            // test delete-user-profile
+            boolean deleteSuccess = userProfileClient.deleteUserProfile(authzToken, testUserId, testGatewayId);
+            assert (deleteSuccess) : "Delete user failed for userId: " + testUserId;
+            System.out.println("Successfully deleted user with userId: " + testUserId);
+
+            // test-check-user-exist
+            boolean userExists = userProfileClient.doesUserExist(authzToken, testUserId, testGatewayId);
+            assert (!userExists) : "User should not exist, but it does.";
+            System.out.println("User was deleted, hence does not exist!");
+            System.out.println("*** DONE ***");
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            logger.error("UserProfile client-sample Exception: " + ex, ex);
+        }
+    }
+
+    private static UserProfile getUserProfile(String userId) {
+        // get random value for userId
+        int userIdValue = ThreadLocalRandom.current().nextInt(1000);
+
+        if (userId != null) {
+            userIdValue = Integer.parseInt(userId.replaceAll("test-user-", ""));
+        }
+        // construct userProfile object
+        UserProfile userProfile = new UserProfile();
+        userProfile.setUserModelVersion("model-" + userIdValue);
+        userProfile.setAiravataInternalUserId("test-user-internal-" + userIdValue);
+        userProfile.setUserId("test-user-" + userIdValue);
+        userProfile.setFirstName("test-user-fname");
+        userProfile.setLastName("test-user-lname");
+        userProfile.setGatewayId(testGatewayId);
+        userProfile.addToEmails("test-user-" + userIdValue + "@domain1.com");
+        userProfile.addToEmails("test-user-" + userIdValue + "@domain2.com");
+        userProfile.setCreationTime(System.currentTimeMillis());
+        userProfile.setLastAccessTime(System.currentTimeMillis());
+        userProfile.setValidUntil(System.currentTimeMillis());
+        userProfile.setState(Status.ACTIVE);
+        userProfile.setNsfDemographics(getNSFDemographics(userIdValue));
+        return userProfile;
+    }
+
+    private static NSFDemographics getNSFDemographics(int userIdValue) {
+        // construct nsfdemographics object
+        NSFDemographics nsfDemographics = new NSFDemographics();
+        nsfDemographics.setAiravataInternalUserId("test-user-internal-" + userIdValue);
+        nsfDemographics.setGender("male");
+        nsfDemographics.setUsCitizenship(USCitizenship.US_CITIZEN);
+        nsfDemographics.addToEthnicities(ethnicity.NOT_HISPANIC_LATINO);
+        nsfDemographics.addToRaces(race.AMERICAN_INDIAN_OR_ALASKAN_NATIVE);
+        return nsfDemographics;
+    }
+}
diff --git a/custos-services/profile-service/profile-service-client-sdks/java-client-samples/src/main/java/org/apache/custos/service/profile/client/util/ProfileServiceClientUtil.java b/custos-services/profile-service/profile-service-client-sdks/java-client-samples/src/main/java/org/apache/custos/service/profile/client/util/ProfileServiceClientUtil.java
new file mode 100644
index 0000000..993e3ec
--- /dev/null
+++ b/custos-services/profile-service/profile-service-client-sdks/java-client-samples/src/main/java/org/apache/custos/service/profile/client/util/ProfileServiceClientUtil.java
@@ -0,0 +1,47 @@
+package org.apache.custos.service.profile.client.util;
+
+import java.net.URL;
+import java.util.Properties;
+
+/**
+ * Created by goshenoy on 3/23/17.
+ */
+public class ProfileServiceClientUtil {
+
+    private static final String PROFILE_SERVICE_SERVER_HOST = "profile.service.server.host";
+    private static final String PROFILE_SERVICE_SERVER_PORT = "profile.service.server.port";
+    private static final String PROFILE_CLIENT_SAMPLE_PROPERTIES = "profile-client-sample.properties";
+
+    private static Properties properties;
+    private static Exception propertyLoadException;
+
+    static {
+        loadProperties();
+    }
+
+    private static void loadProperties() {
+        URL url = ProfileServiceClientUtil.class.getClassLoader().getResource(PROFILE_CLIENT_SAMPLE_PROPERTIES);
+        try {
+            properties = new Properties();
+            properties.load(url.openStream());
+        } catch (Exception ex) {
+            propertyLoadException = ex;
+        }
+    }
+
+    public static String  getProfileServiceServerHost() throws Exception {
+        validateSuccessfullPropertyLoad();
+        return properties.getProperty(PROFILE_SERVICE_SERVER_HOST);
+    }
+
+    public static int getProfileServiceServerPort() throws Exception {
+        validateSuccessfullPropertyLoad();
+        return Integer.parseInt(properties.getProperty(PROFILE_SERVICE_SERVER_PORT));
+    }
+
+    private static void validateSuccessfullPropertyLoad() throws Exception {
+        if (propertyLoadException != null) {
+            throw new Exception(propertyLoadException.getMessage(), propertyLoadException);
+        }
+    }
+}
diff --git a/custos-services/profile-service/profile-service-client-sdks/java-client-samples/src/main/resources/profile-client-sample.properties b/custos-services/profile-service/profile-service-client-sdks/java-client-samples/src/main/resources/profile-client-sample.properties
new file mode 100644
index 0000000..a38fc41
--- /dev/null
+++ b/custos-services/profile-service/profile-service-client-sdks/java-client-samples/src/main/resources/profile-client-sample.properties
@@ -0,0 +1,29 @@
+#
+#
+# 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.
+#
+
+##################################################################################
+#
+#  This properties file provides configuration for profile-service sample client
+#
+##################################################################################
+
+profile.service.server.host=localhost
+profile.service.server.port=8962
+
diff --git a/custos-services/profile-service/profile-service-client-sdks/pom.xml b/custos-services/profile-service/profile-service-client-sdks/pom.xml
new file mode 100644
index 0000000..d3151e3
--- /dev/null
+++ b/custos-services/profile-service/profile-service-client-sdks/pom.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--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. -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>profile-service</artifactId>
+        <groupId>org.apache.custos</groupId>
+        <version>1.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <name>Profile Service Client SDKs</name>
+    <artifactId>profile-service-client-sdks</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>java-client-samples</module>
+    </modules>
+
+
+</project>
\ No newline at end of file
diff --git a/custos-services/profile-service/profile-service-commons/pom.xml b/custos-services/profile-service/profile-service-commons/pom.xml
new file mode 100644
index 0000000..184a4cf
--- /dev/null
+++ b/custos-services/profile-service/profile-service-commons/pom.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--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. -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>profile-service</artifactId>
+        <groupId>org.apache.custos</groupId>
+        <version>1.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>profile-service-commons</artifactId>
+    <name>Custos Profile Service Commons</name>
+    <description>Module to expose a profile-service-commons as a thrift service</description>
+
+    <properties>
+        <derby.version>10.11.1.1</derby.version>
+        <surefire.version>2.18.1</surefire.version>
+        <skipTests>true</skipTests>
+        <mysql.connector.version>5.1.34</mysql.connector.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>net.sf.dozer</groupId>
+            <artifactId>dozer</artifactId>
+            <version>5.4.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.openjpa</groupId>
+            <artifactId>openjpa</artifactId>
+            <version>${openjpa.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>${mysql.connector.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.derby</groupId>
+            <artifactId>derby</artifactId>
+            <version>${derby.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.derby</groupId>
+            <artifactId>derbyclient</artifactId>
+            <version>${derby.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.derby</groupId>
+            <artifactId>derbynet</artifactId>
+            <version>${derby.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.derby</groupId>
+            <artifactId>derbytools</artifactId>
+            <version>${derby.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.custos</groupId>
+            <artifactId>custos-commons</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.custos</groupId>
+            <artifactId>profile-service-models</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.openjpa</groupId>
+                <artifactId>openjpa-maven-plugin</artifactId>
+                <version>2.4.3</version>
+                <configuration>
+                    <includes>**/entities/*.class</includes>
+                    <excludes>**/entities/XML*.class</excludes>
+                    <addDefaultConstructor>true</addDefaultConstructor>
+                    <enforcePropertyRestrictions>true</enforcePropertyRestrictions>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>enhancer</id>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>enhance</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${surefire.version}</version>
+                <inherited>true</inherited>
+                <configuration>
+                    <failIfNoTests>false</failIfNoTests>
+                    <skipTests>${skipTests}</skipTests>
+                    <workingDirectory>${project.build.testOutputDirectory}</workingDirectory>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/repositories/AbstractRepository.java b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/repositories/AbstractRepository.java
new file mode 100644
index 0000000..1a778a3
--- /dev/null
+++ b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/repositories/AbstractRepository.java
@@ -0,0 +1,124 @@
+/*
+ *
+ * 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 org.apache.custos.service.profile.commons.repositories;
+
+import org.apache.custos.service.profile.commons.utils.JPAUtils;
+import org.apache.custos.service.profile.commons.utils.ObjectMapperSingleton;
+import org.dozer.Mapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.persistence.Query;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public abstract class AbstractRepository<T, E, Id> {
+    private final static Logger logger = LoggerFactory.getLogger(AbstractRepository.class);
+
+    private Class<T> thriftGenericClass;
+    private Class<E> dbEntityGenericClass;
+
+    public AbstractRepository(Class<T> thriftGenericClass, Class<E> dbEntityGenericClass) {
+        this.thriftGenericClass = thriftGenericClass;
+        this.dbEntityGenericClass = dbEntityGenericClass;
+    }
+
+    public T create(T t) {
+        return update(t);
+    }
+
+    public T update(T t) {
+        Mapper mapper = ObjectMapperSingleton.getInstance();
+        E entity = mapper.map(t, dbEntityGenericClass);
+        E persistedCopy = JPAUtils.execute(entityManager -> entityManager.merge(entity));
+        return mapper.map(persistedCopy, thriftGenericClass);
+    }
+
+    public boolean delete(Id id) {
+        JPAUtils.execute(entityManager -> {
+            E entity = entityManager.find(dbEntityGenericClass, id);
+            entityManager.remove(entity);
+            return entity;
+        });
+        return true;
+    }
+
+    public T get(Id id) {
+        E entity = JPAUtils.execute(entityManager -> entityManager
+                .find(dbEntityGenericClass, id));
+        Mapper mapper = ObjectMapperSingleton.getInstance();
+        return mapper.map(entity, thriftGenericClass);
+    }
+
+    public List<T> select(String query) {
+        List resultSet = (List) JPAUtils.execute(entityManager -> entityManager.createQuery(query).getResultList());
+        Mapper mapper = ObjectMapperSingleton.getInstance();
+        List<T> resultList = new ArrayList<>();
+        resultSet.stream().forEach(rs -> resultList.add(mapper.map(rs, thriftGenericClass)));
+        return resultList;
+    }
+
+    public List<T> select(String query, int limit, int offset) {
+        List resultSet = (List) JPAUtils.execute(entityManager -> entityManager.createQuery(query).setFirstResult(offset)
+                .setMaxResults(limit).getResultList());
+        Mapper mapper = ObjectMapperSingleton.getInstance();
+        List<T> resultList = new ArrayList<>();
+        resultSet.stream().forEach(rs -> resultList.add(mapper.map(rs, thriftGenericClass)));
+        return resultList;
+    }
+
+    public List<T> select(String query, int limit, int offset, Map<String, Object> queryParams) {
+        List resultSet = (List) JPAUtils.execute(entityManager -> {
+            Query jpaQuery = entityManager.createQuery(query);
+
+            for (Map.Entry<String, Object> entry : queryParams.entrySet()) {
+
+                jpaQuery.setParameter(entry.getKey(), entry.getValue());
+            }
+
+            return jpaQuery.setFirstResult(offset).setMaxResults(limit).getResultList();
+
+        });
+        Mapper mapper = ObjectMapperSingleton.getInstance();
+        List<T> resultList = new ArrayList<>();
+        resultSet.stream().forEach(rs -> resultList.add(mapper.map(rs, thriftGenericClass)));
+        return resultList;
+    }
+
+    public List<T> select(String query, Map<String, Object> queryParams) {
+        List resultSet = (List) JPAUtils.execute(entityManager -> {
+            Query jpaQuery = entityManager.createQuery(query);
+
+            for (Map.Entry<String, Object> entry : queryParams.entrySet()) {
+
+                jpaQuery.setParameter(entry.getKey(), entry.getValue());
+            }
+
+            return jpaQuery.getResultList();
+
+        });
+        Mapper mapper = ObjectMapperSingleton.getInstance();
+        List<T> resultList = new ArrayList<>();
+        resultSet.stream().forEach(rs -> resultList.add(mapper.map(rs, thriftGenericClass)));
+        return resultList;
+    }
+}
\ No newline at end of file
diff --git a/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/tenant/entities/GatewayEntity.java b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/tenant/entities/GatewayEntity.java
new file mode 100644
index 0000000..c3506e3
--- /dev/null
+++ b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/tenant/entities/GatewayEntity.java
@@ -0,0 +1,285 @@
+/**
+ *
+ * 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 org.apache.custos.service.profile.commons.tenant.entities;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.persistence.*;
+import java.util.UUID;
+
+@Entity
+@Table(name = "GATEWAY")
+public class GatewayEntity {
+    private final static Logger logger = LoggerFactory.getLogger(GatewayEntity.class);
+    private String custosInternalGatewayId;
+    private String gatewayId;
+    private String gatewayName;
+    private String domain;
+    private String emailAddress;
+    private String gatewayApprovalStatus;
+    private String gatewayAcronym;
+    private String gatewayUrl;
+    private String gatewayPublicAbstract;
+    private String reviewProposalDescription;
+    private String gatewayAdminFirstName;
+    private String gatewayAdminLastName;
+    private String gatewayAdminEmail;
+    private String identityServerUserName;
+    private String identityServerPasswordToken;
+    private String declinedReason;
+    private String oauthClientId;
+    private String oauthClientSecret;
+    private long requestCreationTime;
+    private String requesterUsername;
+
+    // set random value for internalGatewayId
+    public GatewayEntity() {
+        this.custosInternalGatewayId = UUID.randomUUID().toString();
+    }
+
+    @Id
+    @Column(name = "CUSTOS_INTERNAL_GATEWAY_ID")
+    public String getCustosInternalGatewayId() {
+        return custosInternalGatewayId;
+    }
+
+    public void setCustosInternalGatewayId(String custosInternalGatewayId) {
+        this.custosInternalGatewayId = custosInternalGatewayId;
+    }
+
+    @Column(name = "GATEWAY_ID")
+    public String getGatewayId() {
+        return gatewayId;
+    }
+
+    public void setGatewayId(String gatewayId) {
+        this.gatewayId = gatewayId;
+    }
+
+    @Column(name = "GATEWAY_NAME")
+    public String getGatewayName() {
+        return gatewayName;
+    }
+
+    public void setGatewayName(String gatewayName) {
+        this.gatewayName = gatewayName;
+    }
+
+    @Column(name = "GATEWAY_DOMAIN")
+    public String getDomain() {
+        return domain;
+    }
+
+    public void setDomain(String domain) {
+        this.domain = domain;
+    }
+
+    @Column(name = "EMAIL_ADDRESS")
+    public String getEmailAddress() {
+        return emailAddress;
+    }
+
+    public void setEmailAddress(String emailAddress) {
+        this.emailAddress = emailAddress;
+    }
+
+    @Column(name = "GATEWAY_APPROVAL_STATUS")
+    public String getGatewayApprovalStatus() {
+        return gatewayApprovalStatus;
+    }
+
+    public void setGatewayApprovalStatus(String gatewayApprovalStatus) {
+        this.gatewayApprovalStatus = gatewayApprovalStatus;
+    }
+
+    @Column(name = "GATEWAY_ACRONYM")
+    public String getGatewayAcronym() {
+        return gatewayAcronym;
+    }
+
+    public void setGatewayAcronym(String gatewayAcronym) {
+        this.gatewayAcronym = gatewayAcronym;
+    }
+
+    @Column(name = "GATEWAY_URL")
+    public String getGatewayUrl() {
+        return gatewayUrl;
+    }
+
+    public void setGatewayUrl(String gatewayUrl) {
+        this.gatewayUrl = gatewayUrl;
+    }
+
+    @Column(name = "GATEWAY_PUBLIC_ABSTRACT")
+    public String getGatewayPublicAbstract() {
+        return gatewayPublicAbstract;
+    }
+
+    public void setGatewayPublicAbstract(String gatewayPublicAbstract) {
+        this.gatewayPublicAbstract = gatewayPublicAbstract;
+    }
+
+    @Column(name = "GATEWAY_REVIEW_PROPOSAL_DESCRIPTION")
+    public String getReviewProposalDescription() {
+        return reviewProposalDescription;
+    }
+
+    public void setReviewProposalDescription(String reviewProposalDescription) {
+        this.reviewProposalDescription = reviewProposalDescription;
+    }
+
+    @Column(name = "GATEWAY_ADMIN_FIRST_NAME")
+    public String getGatewayAdminFirstName() {
+        return gatewayAdminFirstName;
+    }
+
+    public void setGatewayAdminFirstName(String gatewayAdminFirstName) {
+        this.gatewayAdminFirstName = gatewayAdminFirstName;
+    }
+
+    @Column(name = "GATEWAY_ADMIN_LAST_NAME")
+    public String getGatewayAdminLastName() {
+        return gatewayAdminLastName;
+    }
+
+    public void setGatewayAdminLastName(String gatewayAdminLastName) {
+        this.gatewayAdminLastName = gatewayAdminLastName;
+    }
+
+    @Column(name = "GATEWAY_ADMIN_EMAIL")
+    public String getGatewayAdminEmail() {
+        return gatewayAdminEmail;
+    }
+
+    public void setGatewayAdminEmail(String gatewayAdminEmail) {
+        this.gatewayAdminEmail = gatewayAdminEmail;
+    }
+
+    @Column(name = "IDENTITY_SERVER_USERNAME")
+    public String getIdentityServerUserName() {
+        return identityServerUserName;
+    }
+
+    public void setIdentityServerUserName(String identityServerUserName) {
+        this.identityServerUserName = identityServerUserName;
+    }
+
+    @Column(name = "IDENTITY_SERVER_PASSWORD_TOKEN")
+    public String getIdentityServerPasswordToken() {
+        return identityServerPasswordToken;
+    }
+
+    public void setIdentityServerPasswordToken(String identityServerPasswordToken) {
+        this.identityServerPasswordToken = identityServerPasswordToken;
+    }
+
+    @Column(name = "REQUESTER_USERNAME")
+    public String getRequesterUsername() {
+        return requesterUsername;
+    }
+
+    public void setRequesterUsername(String requesterUsername) {
+        this.requesterUsername = requesterUsername;
+    }
+
+    @Column(name = "DECLINED_REASON")
+    public String getDeclinedReason() {
+        return declinedReason;
+    }
+
+    public void setDeclinedReason(String declinedReason) {
+        this.declinedReason = declinedReason;
+    }
+
+    @Column(name = "OAUTH_CLIENT_ID")
+    public String getOauthClientId() {
+        return oauthClientId;
+    }
+
+    public void setOauthClientId(String oauthClientId) {
+        this.oauthClientId = oauthClientId;
+    }
+
+    @Column(name = "REQUEST_CREATION_TIME")
+    public long getRequestCreationTime() {
+        return requestCreationTime;
+    }
+
+    public void setRequestCreationTime(long requestCreationTime) {
+        this.requestCreationTime = requestCreationTime;
+    }
+
+    @Column(name = "OAUTH_CLIENT_SECRET")
+    public String getOauthClientSecret() {
+        return oauthClientSecret;
+    }
+
+    public void setOauthClientSecret(String oauthClientSecret) {
+        this.oauthClientSecret = oauthClientSecret;
+    }
+
+    @PrePersist
+    void createdAt() {
+        this.requestCreationTime = System.currentTimeMillis();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof GatewayEntity)) {
+            return false;
+        }
+        GatewayEntity gwy = (GatewayEntity) obj;
+        return getCustosInternalGatewayId().equals(gwy.getCustosInternalGatewayId());
+    }
+
+    @Override
+    public String toString() {
+        return "GatewayEntity{" +
+                "custosInternalGatewayId='" + custosInternalGatewayId + '\'' +
+                ", gatewayId='" + gatewayId + '\'' +
+                ", gatewayName='" + gatewayName + '\'' +
+                ", domain='" + domain + '\'' +
+                ", emailAddress='" + emailAddress + '\'' +
+                ", gatewayApprovalStatus='" + gatewayApprovalStatus + '\'' +
+                ", gatewayAcronym='" + gatewayAcronym + '\'' +
+                ", gatewayUrl='" + gatewayUrl + '\'' +
+                ", gatewayPublicAbstract='" + gatewayPublicAbstract + '\'' +
+                ", reviewProposalDescription='" + reviewProposalDescription + '\'' +
+                ", gatewayAdminFirstName='" + gatewayAdminFirstName + '\'' +
+                ", gatewayAdminLastName='" + gatewayAdminLastName + '\'' +
+                ", gatewayAdminEmail='" + gatewayAdminEmail + '\'' +
+                ", identityServerUserName='" + identityServerUserName + '\'' +
+                ", identityServerPasswordToken='" + identityServerPasswordToken + '\'' +
+                ", declinedReason='" + declinedReason + '\'' +
+                ", oauthClientId='" + oauthClientId + '\'' +
+                ", oauthClientSecret='" + oauthClientSecret + '\'' +
+                ", requestCreationTime=" + requestCreationTime +
+                ", requesterUsername='" + requesterUsername + '\'' +
+                '}';
+    }
+}
diff --git a/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/user/entities/CustomizedDashboardEntity.java b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/user/entities/CustomizedDashboardEntity.java
new file mode 100644
index 0000000..1ee3845
--- /dev/null
+++ b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/user/entities/CustomizedDashboardEntity.java
@@ -0,0 +1,325 @@
+/*
+ *
+ * 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 org.apache.custos.service.profile.commons.user.entities;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name = "CUSTOMIZED_DASHBOARD")
+public class CustomizedDashboardEntity {
+
+    private String custosInternalUserId;
+    private String experimentId;
+    private String name;
+    private String description;
+    private String project;
+    private String owner;
+    private String application;
+    private String computeResource;
+    private String jobName;
+    private String jobId;
+    private String jobStatus;
+    private String jobCreationTime;
+    private String notificationsTo;
+    private String workingDir;
+    private String jobDescription;
+    private String creationTime;
+    private String lastModifiedTime;
+    private String wallTime;
+    private String cpuCount;
+    private String nodeCount;
+    private String queue;
+    private String inputs;
+    private String outputs;
+    private String storageDir;
+    private String errors;
+
+    private UserProfileEntity userProfileEntity;
+
+    @Id
+    @Column(name = "AIRAVATA_INTERNAL_USER_ID")
+    public String getCustosInternalUserId() {
+        return custosInternalUserId;
+    }
+
+    public void setCustosInternalUserId(String custosInternalUserId) {
+        this.custosInternalUserId = custosInternalUserId;
+    }
+
+    @Column(name = "ENABLED_EXPERIMENT_ID")
+    public String getExperimentId() {
+        return experimentId;
+    }
+
+    public void setExperimentId(String experimentId) {
+        this.experimentId = experimentId;
+    }
+
+    @Column(name = "ENABLED_NAME")
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @Column(name = "ENABLED_DESCRIPTION")
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    @Column(name = "ENABLED_PROJECT")
+    public String getProject() {
+        return project;
+    }
+
+    public void setProject(String project) {
+        this.project = project;
+    }
+
+    @Column(name = "ENABLED_OWNER")
+    public String getOwner() {
+        return owner;
+    }
+
+    public void setOwner(String owner) {
+        this.owner = owner;
+    }
+
+    @Column(name = "ENABLED_APPLICATION")
+    public String getApplication() {
+        return application;
+    }
+
+    public void setApplication(String application) {
+        this.application = application;
+    }
+
+    @Column(name = "ENABLED_COMPUTE_RESOURCE")
+    public String getComputeResource() {
+        return computeResource;
+    }
+
+    public void setComputeResource(String computeResource) {
+        this.computeResource = computeResource;
+    }
+
+    @Column(name = "ENABLED_JOB_NAME")
+    public String getJobName() {
+        return jobName;
+    }
+
+    public void setJobName(String jobName) {
+        this.jobName = jobName;
+    }
+
+    @Column(name = "ENABLED_JOB_ID")
+    public String getJobId() {
+        return jobId;
+    }
+
+    public void setJobId(String jobId) {
+        this.jobId = jobId;
+    }
+
+    @Column(name = "ENABLED_JOB_STATUS")
+    public String getJobStatus() {
+        return jobStatus;
+    }
+
+    public void setJobStatus(String jobStatus) {
+        this.jobStatus = jobStatus;
+    }
+
+    @Column(name = "ENABLED_JOB_CREATION_TIME")
+    public String getJobCreationTime() {
+        return jobCreationTime;
+    }
+
+    public void setJobCreationTime(String jobCreationTime) {
+        this.jobCreationTime = jobCreationTime;
+    }
+
+    @Column(name = "ENABLED_NOTIFICATIONS_TO")
+    public String getNotificationsTo() {
+        return notificationsTo;
+    }
+
+    public void setNotificationsTo(String notificationsTo) {
+        this.notificationsTo = notificationsTo;
+    }
+
+    @Column(name = "ENABLED_WORKING_DIR")
+    public String getWorkingDir() {
+        return workingDir;
+    }
+
+    public void setWorkingDir(String workingDir) {
+        this.workingDir = workingDir;
+    }
+
+    @Column(name = "ENABLED_JOB_DESCRIPTION")
+    public String getJobDescription() {
+        return jobDescription;
+    }
+
+    public void setJobDescription(String jobDescription) {
+        this.jobDescription = jobDescription;
+    }
+
+    @Column(name = "ENABLED_CREATION_TIME")
+    public String getCreationTime() {
+        return creationTime;
+    }
+
+    public void setCreationTime(String creationTime) {
+        this.creationTime = creationTime;
+    }
+
+    @Column(name = "ENABLED_LAST_MODIFIED_TIME")
+    public String getLastModifiedTime() {
+        return lastModifiedTime;
+    }
+
+    public void setLastModifiedTime(String lastModifiedTime) {
+        this.lastModifiedTime = lastModifiedTime;
+    }
+
+    @Column(name = "ENABLED_WALL_TIME")
+    public String getWallTime() {
+        return wallTime;
+    }
+
+    public void setWallTime(String wallTime) {
+        this.wallTime = wallTime;
+    }
+
+    @Column(name = "ENABLED_CPU_COUNT")
+    public String getCpuCount() {
+        return cpuCount;
+    }
+
+    public void setCpuCount(String cpuCount) {
+        this.cpuCount = cpuCount;
+    }
+
+    @Column(name = "ENABLED_NODE_COUNT")
+    public String getNodeCount() {
+        return nodeCount;
+    }
+
+    public void setNodeCount(String nodeCount) {
+        this.nodeCount = nodeCount;
+    }
+
+    @Column(name = "ENABLED_QUEUE")
+    public String getQueue() {
+        return queue;
+    }
+
+    public void setQueue(String queue) {
+        this.queue = queue;
+    }
+
+    @Column(name = "ENABLED_INPUTS")
+    public String getInputs() {
+        return inputs;
+    }
+
+    public void setInputs(String inputs) {
+        this.inputs = inputs;
+    }
+
+    @Column(name = "ENABLED_OUTPUTS")
+    public String getOutputs() {
+        return outputs;
+    }
+
+    public void setOutputs(String outputs) {
+        this.outputs = outputs;
+    }
+
+    @Column(name = "ENABLED_STORAGE_DIR")
+    public String getStorageDir() {
+        return storageDir;
+    }
+
+    public void setStorageDir(String storageDir) {
+        this.storageDir = storageDir;
+    }
+
+    @Column(name = "ENABLED_ERRORS")
+    public String getErrors() {
+        return errors;
+    }
+
+    public void setErrors(String errors) {
+        this.errors = errors;
+    }
+
+    @OneToOne(targetEntity = UserProfileEntity.class, cascade = CascadeType.ALL)
+    @PrimaryKeyJoinColumn(name = "AIRAVATA_INTERNAL_USER_ID", referencedColumnName = "AIRAVATA_INTERNAL_USER_ID")
+    public UserProfileEntity getUserProfileEntity() {
+        return userProfileEntity;
+    }
+
+    public void setUserProfileEntity(UserProfileEntity userProfileEntity) {
+        this.userProfileEntity = userProfileEntity;
+    }
+
+    @Override
+    public String toString() {
+        return "CustomizedDashboardEntity{" +
+                "custosInternalUserId='" + custosInternalUserId + '\'' +
+                ", experimentId='" + experimentId + '\'' +
+                ", name='" + name + '\'' +
+                ", description='" + description + '\'' +
+                ", project='" + project + '\'' +
+                ", owner='" + owner + '\'' +
+                ", application='" + application + '\'' +
+                ", computeResource='" + computeResource + '\'' +
+                ", jobName='" + jobName + '\'' +
+                ", jobId='" + jobId + '\'' +
+                ", jobStatus='" + jobStatus + '\'' +
+                ", jobCreationTime='" + jobCreationTime + '\'' +
+                ", notificationsTo='" + notificationsTo + '\'' +
+                ", workingDir='" + workingDir + '\'' +
+                ", jobDescription='" + jobDescription + '\'' +
+                ", creationTime='" + creationTime + '\'' +
+                ", lastModifiedTime='" + lastModifiedTime + '\'' +
+                ", wallTime='" + wallTime + '\'' +
+                ", cpuCount='" + cpuCount + '\'' +
+                ", nodeCount='" + nodeCount + '\'' +
+                ", queue='" + queue + '\'' +
+                ", inputs='" + inputs + '\'' +
+                ", outputs='" + outputs + '\'' +
+                ", storageDir='" + storageDir + '\'' +
+                ", errors='" + errors + '\'' +
+                '}';
+    }
+}
diff --git a/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/user/entities/NSFDemographicsEntity.java b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/user/entities/NSFDemographicsEntity.java
new file mode 100644
index 0000000..f336444
--- /dev/null
+++ b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/user/entities/NSFDemographicsEntity.java
@@ -0,0 +1,108 @@
+/*
+ *
+ * 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 org.apache.custos.service.profile.commons.user.entities;
+
+import javax.persistence.*;
+import java.util.List;
+
+@Entity
+@Table(name = "NSF_DEMOGRAPHIC")
+public class NSFDemographicsEntity {
+    private String custosInternalUserId;
+    private String gender;
+    private List<String> ethnicities;
+    private List<String> races;
+    private List<String> disabilities;
+    private UserProfileEntity userProfile;
+
+    @Id
+    @Column(name = "CUSTOS_INTERNAL_USER_ID")
+    public String getCustosInternalUserId() {
+        return custosInternalUserId;
+    }
+
+    public void setCustosInternalUserId(String userId) {
+        this.custosInternalUserId = userId;
+    }
+
+    @Column(name = "GENDER")
+    public String getGender() {
+        return gender;
+    }
+
+    public void setGender(String gender) {
+        this.gender = gender;
+    }
+
+    @ElementCollection
+    @CollectionTable(name="NSF_DEMOGRAPHIC_ETHNICITY", joinColumns = @JoinColumn(name="AIRAVATA_INTERNAL_USER_ID"))
+    @Column(name = "ETHNICITY")
+    public List<String> getEthnicities() {
+        return ethnicities;
+    }
+
+    public void setEthnicities(List<String> ethnicities) {
+        this.ethnicities = ethnicities;
+    }
+
+    @ElementCollection
+    @CollectionTable(name="NSF_DEMOGRAPHIC_RACE", joinColumns = @JoinColumn(name="AIRAVATA_INTERNAL_USER_ID"))
+    @Column(name = "RACE")
+    public List<String> getRaces() {
+        return races;
+    }
+
+    public void setRaces(List<String> races) {
+        this.races = races;
+    }
+
+    @ElementCollection
+    @CollectionTable(name="NSF_DEMOGRAPHIC_DISABILITY", joinColumns = @JoinColumn(name="AIRAVATA_INTERNAL_USER_ID"))
+    @Column(name = "DISABILITY")
+    public List<String> getDisabilities() {
+        return disabilities;
+    }
+
+    public void setDisabilities(List<String> disabilities) {
+        this.disabilities = disabilities;
+    }
+
+    @OneToOne(targetEntity = UserProfileEntity.class, cascade = CascadeType.ALL)
+    @PrimaryKeyJoinColumn(name = "AIRAVATA_INTERNAL_USER_ID", referencedColumnName = "AIRAVATA_INTERNAL_USER_ID")
+    public UserProfileEntity getUserProfile() {
+        return userProfile;
+    }
+
+    public void setUserProfile(UserProfileEntity userProfile) {
+        this.userProfile = userProfile;
+    }
+
+    @Override
+    public String toString() {
+        return "NSFDemographicsEntity{" +
+                "custosInternalUserId='" + custosInternalUserId + '\'' +
+                ", gender='" + gender + '\'' +
+                ", ethnicities=" + ethnicities +
+                ", races=" + races +
+                ", disabilities=" + disabilities +
+                '}';
+    }
+}
diff --git a/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/user/entities/UserProfileEntity.java b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/user/entities/UserProfileEntity.java
new file mode 100644
index 0000000..c95f2c0
--- /dev/null
+++ b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/user/entities/UserProfileEntity.java
@@ -0,0 +1,345 @@
+/*
+ *
+ * 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 org.apache.custos.service.profile.commons.user.entities;
+
+import javax.persistence.*;
+import java.util.Date;
+import java.util.List;
+
+@Entity
+@Table(name="USER_PROFILE")
+public class UserProfileEntity {
+    private String custosInternalUserId;
+    private String userId;
+    private String gatewayId;
+    private String userModelVersion;
+    private String firstName;
+    private String lastName;
+    private String middleName;
+    private String namePrefix;
+    private String nameSuffix;
+    private String orcidId;
+    private String country;
+    private String homeOrganization;
+    private String orginationAffiliation;
+    private Date creationTime;
+    private Date lastAccessTime;
+    private Date validUntil;
+    private String state;
+    private String comments;
+    private List<String> labeledURI;
+    private String gpgKey;
+    private String timeZone;
+
+    private List<String> nationality;
+    private List<String> emails;
+    private List<String> phones;
+    private NSFDemographicsEntity nsfDemographics;
+    private CustomizedDashboardEntity customizedDashboardEntity;
+
+    @Id
+    @Column(name = "AIRAVATA_INTERNAL_USER_ID")
+    public String getCustosInternalUserId() {
+        return custosInternalUserId;
+    }
+
+    public void setCustosInternalUserId(String id) {
+        this.custosInternalUserId = id;
+    }
+
+    @Column(name = "USER_ID")
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    @Column(name = "GATEWAY_ID")
+    public String getGatewayId() {
+        return gatewayId;
+    }
+
+    public void setGatewayId(String gatewayId) {
+        this.gatewayId = gatewayId;
+    }
+
+    @Column(name = "USER_MODEL_VERSION")
+    public String getUserModelVersion() {
+        return userModelVersion;
+    }
+
+    public void setUserModelVersion(String userModelVersion) {
+        this.userModelVersion = userModelVersion;
+    }
+
+    @ElementCollection(fetch = FetchType.EAGER)
+    @CollectionTable(name="USER_PROFILE_EMAIL", joinColumns = @JoinColumn(name="AIRAVATA_INTERNAL_USER_ID"))
+    @Column(name = "EMAIL")
+    public List<String> getEmails() {
+        return emails;
+    }
+
+    public void setEmails(List<String> emails) {
+        this.emails = emails;
+    }
+
+    @Column(name = "FIRST_NAME")
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public void setFirstName(String firstName) {
+        this.firstName = firstName;
+    }
+
+    @Column(name = "LAST_NAME")
+    public String getLastName() {
+        return lastName;
+    }
+
+    public void setLastName(String lastName) {
+        this.lastName = lastName;
+    }
+
+    @Column(name = "MIDDLE_NAME")
+    public String getMiddleName() {
+        return middleName;
+    }
+
+    public void setMiddleName(String middleName) {
+        this.middleName = middleName;
+    }
+
+    @Column(name = "NAME_PREFIX")
+    public String getNamePrefix() {
+        return namePrefix;
+    }
+
+    public void setNamePrefix(String namePrefix) {
+        this.namePrefix = namePrefix;
+    }
+
+    @Column(name = "NAME_SUFFIX")
+    public String getNameSuffix() {
+        return nameSuffix;
+    }
+
+    public void setNameSuffix(String nameSuffix) {
+        this.nameSuffix = nameSuffix;
+    }
+
+    @Column(name = "ORCID_ID")
+    public String getOrcidId() {
+        return orcidId;
+    }
+
+    public void setOrcidId(String orcidId) {
+        this.orcidId = orcidId;
+    }
+
+    @ElementCollection(fetch = FetchType.EAGER)
+    @CollectionTable(name="USER_PROFILE_PHONE", joinColumns = @JoinColumn(name="AIRAVATA_INTERNAL_USER_ID"))
+    @Column(name = "PHONE")
+    public List<String> getPhones() {
+        return phones;
+    }
+
+    public void setPhones(List<String> phones) {
+        this.phones = phones;
+    }
+
+    @Column(name = "COUNTRY")
+    public String getCountry() {
+        return country;
+    }
+
+    public void setCountry(String country) {
+        this.country = country;
+    }
+
+    @ElementCollection(fetch = FetchType.EAGER)
+    @CollectionTable(name="USER_PROFILE_NATIONALITY", joinColumns = @JoinColumn(name="AIRAVATA_INTERNAL_USER_ID"))
+    @Column(name = "NATIONALITY")
+    public List<String> getNationality() {
+        return nationality;
+    }
+
+    public void setNationality(List<String> nationality) {
+        this.nationality = nationality;
+    }
+
+    @Column(name = "HOME_ORGANIZATION")
+    public String getHomeOrganization() {
+        return homeOrganization;
+    }
+
+    public void setHomeOrganization(String homeOrganization) {
+        this.homeOrganization = homeOrganization;
+    }
+
+    @Column(name = "ORIGINATION_AFFILIATION")
+    public String getOrginationAffiliation() {
+        return orginationAffiliation;
+    }
+
+    public void setOrginationAffiliation(String orginationAffiliation) {
+        this.orginationAffiliation = orginationAffiliation;
+    }
+
+    @Column(name="CREATION_TIME")
+    public Date getCreationTime() {
+        return creationTime;
+    }
+
+    private void setCreationTime(Date creationTime) {
+        this.creationTime = creationTime;
+    }
+
+    @Column(name = "LAST_ACCESS_TIME")
+    public Date getLastAccessTime() {
+        return lastAccessTime;
+    }
+
+    private void setLastAccessTime(Date lastAccessTime) {
+        this.lastAccessTime = lastAccessTime;
+    }
+
+    @Column(name = "VALID_UNTIL")
+    public Date getValidUntil() {
+        return validUntil;
+    }
+
+    public void setValidUntil(Date validUntil) {
+        this.validUntil = validUntil;
+    }
+
+    @Column(name = "STATE")
+    public String getState() {
+        return state;
+    }
+
+    public void setState(String state) {
+        this.state = state;
+    }
+
+    @Lob
+    @Column(name = "COMMENTS")
+    public String getComments() {
+        return comments;
+    }
+
+    public void setComments(String comments) {
+        this.comments = comments;
+    }
+
+    @ElementCollection(fetch = FetchType.EAGER)
+    @CollectionTable(name="USER_PROFILE_LABELED_URI", joinColumns = @JoinColumn(name="AIRAVATA_INTERNAL_USER_ID"))
+    @Column(name = "LABELED_URI")
+    public List<String> getLabeledURI() {
+        return labeledURI;
+    }
+
+    public void setLabeledURI(List<String> labeledURI) {
+        this.labeledURI = labeledURI;
+    }
+
+    @Lob
+    @Column(name = "GPG_KEY")
+    public String getGpgKey() {
+        return gpgKey;
+    }
+
+    public void setGpgKey(String gpgKey) {
+        this.gpgKey = gpgKey;
+    }
+
+    @Column(name = "TIME_ZONE")
+    public String getTimeZone() {
+        return timeZone;
+    }
+
+    public void setTimeZone(String timeZone) {
+        this.timeZone = timeZone;
+    }
+
+    @OneToOne(targetEntity = NSFDemographicsEntity.class, cascade = CascadeType.ALL,
+            mappedBy = "userProfile", fetch = FetchType.EAGER)
+    public NSFDemographicsEntity getNsfDemographics() {
+        return nsfDemographics;
+    }
+
+    public void setNsfDemographics(NSFDemographicsEntity nsfDemographics) {
+        this.nsfDemographics = nsfDemographics;
+    }
+
+    @OneToOne(targetEntity = CustomizedDashboardEntity.class, cascade = CascadeType.ALL,
+            mappedBy = "userProfileEntity", fetch = FetchType.EAGER)
+    public CustomizedDashboardEntity getCustomizedDashboardEntity() {
+        return customizedDashboardEntity;
+    }
+
+    public void setCustomizedDashboardEntity(CustomizedDashboardEntity customizedDashboardEntity) {
+        this.customizedDashboardEntity = customizedDashboardEntity;
+    }
+
+    @PrePersist
+    void createdAt() {
+        this.creationTime = this.lastAccessTime = new Date();
+    }
+
+    @PreUpdate
+    void updatedAt() {
+        this.lastAccessTime = new Date();
+    }
+
+    @Override
+    public String toString() {
+        return "UserProfileEntity{" +
+                "custosInternalUserId='" + custosInternalUserId + '\'' +
+                ", userId='" + userId + '\'' +
+                ", gatewayId='" + gatewayId + '\'' +
+                ", userModelVersion='" + userModelVersion + '\'' +
+                ", firstName='" + firstName + '\'' +
+                ", lastName='" + lastName + '\'' +
+                ", middleName='" + middleName + '\'' +
+                ", namePrefix='" + namePrefix + '\'' +
+                ", nameSuffix='" + nameSuffix + '\'' +
+                ", orcidId='" + orcidId + '\'' +
+                ", country='" + country + '\'' +
+                ", homeOrganization='" + homeOrganization + '\'' +
+                ", orginationAffiliation='" + orginationAffiliation + '\'' +
+                ", creationTime=" + creationTime +
+                ", lastAccessTime=" + lastAccessTime +
+                ", validUntil=" + validUntil +
+                ", state='" + state + '\'' +
+                ", comments='" + comments + '\'' +
+                ", labeledURI=" + labeledURI +
+                ", gpgKey='" + gpgKey + '\'' +
+                ", timeZone='" + timeZone + '\'' +
+                ", nationality=" + nationality +
+                ", emails=" + emails +
+                ", phones=" + phones +
+                ", nsfDemographics=" + nsfDemographics +
+                '}';
+    }
+}
diff --git a/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/Committer.java b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/Committer.java
new file mode 100644
index 0000000..aa2dc58
--- /dev/null
+++ b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/Committer.java
@@ -0,0 +1,27 @@
+/*
+ *
+ * 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 org.apache.custos.service.profile.commons.utils;
+
+@FunctionalInterface
+public interface Committer<T, R>  {
+
+    R commit(T t);
+}
\ No newline at end of file
diff --git a/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/JPAConstants.java b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/JPAConstants.java
new file mode 100644
index 0000000..f029df0
--- /dev/null
+++ b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/JPAConstants.java
@@ -0,0 +1,34 @@
+/*
+ *
+ * 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 org.apache.custos.service.profile.commons.utils;
+
+public class JPAConstants {
+	public static final String KEY_JDBC_URL = "profile.service.jdbc.url";
+	public static final String KEY_JDBC_USER = "profile.service.jdbc.user";
+	public static final String KEY_JDBC_PASSWORD = "profile.service.jdbc.password";
+	public static final String KEY_JDBC_DRIVER = "profile.service.jdbc.driver";
+
+	// TODO: is this needed?
+	public static final String KEY_DERBY_START_ENABLE = "profile.service.start.derby.server.mode";
+	public static final String VALIDATION_QUERY = "profile.service.validationQuery";
+	public static final String JPA_CACHE_SIZE = "profile.service.jpa.cache.size";
+	public static final String ENABLE_CACHING = "profile.service.cache.enable";
+}
diff --git a/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/JPAUtils.java b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/JPAUtils.java
new file mode 100644
index 0000000..2cae126
--- /dev/null
+++ b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/JPAUtils.java
@@ -0,0 +1,53 @@
+/*
+ *
+ * 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 org.apache.custos.service.profile.commons.utils;
+
+import org.apache.custos.commons.utils.JDBCConfig;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+public class JPAUtils {
+    private static final String PERSISTENCE_UNIT_NAME = "profile_service";
+    private static final JDBCConfig JDBC_CONFIG = new ProfileServiceJDBCConfig();
+    private static final EntityManagerFactory factory = org.apache.custos.commons.utils.JPAUtils.getEntityManagerFactory(PERSISTENCE_UNIT_NAME, JDBC_CONFIG);
+
+    public static EntityManager getEntityManager() {
+        return factory.createEntityManager();
+    }
+
+    public static <R> R execute(Committer<EntityManager, R> committer){
+        EntityManager entityManager = JPAUtils.getEntityManager();
+        try {
+            entityManager.getTransaction().begin();
+            R r = committer.commit(entityManager);
+            entityManager.getTransaction().commit();
+            return  r;
+        }finally {
+            if (entityManager != null && entityManager.isOpen()) {
+                if (entityManager.getTransaction().isActive()) {
+                    entityManager.getTransaction().rollback();
+                }
+                entityManager.close();
+            }
+        }
+    }
+}
diff --git a/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/ObjectMapperSingleton.java b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/ObjectMapperSingleton.java
new file mode 100644
index 0000000..e5cd0f1
--- /dev/null
+++ b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/ObjectMapperSingleton.java
@@ -0,0 +1,39 @@
+/**
+ *
+ * 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 org.apache.custos.service.profile.commons.utils;
+
+import org.dozer.DozerBeanMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ObjectMapperSingleton extends DozerBeanMapper{
+    private final static Logger logger = LoggerFactory.getLogger(ObjectMapperSingleton.class);
+
+    private static ObjectMapperSingleton instance;
+
+    private ObjectMapperSingleton(){}
+
+    public static ObjectMapperSingleton getInstance(){
+        if(instance == null)
+            instance = new ObjectMapperSingleton();
+        return instance;
+    }
+}
\ No newline at end of file
diff --git a/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/ProfileServiceJDBCConfig.java b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/ProfileServiceJDBCConfig.java
new file mode 100644
index 0000000..fe2db70
--- /dev/null
+++ b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/ProfileServiceJDBCConfig.java
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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 org.apache.custos.service.profile.commons.utils;
+
+import org.apache.custos.commons.utils.JDBCConfig;
+
+public class ProfileServiceJDBCConfig implements JDBCConfig {
+
+    @Override
+    public String getURL() {
+        return Utils.getJDBCURL();
+    }
+
+    @Override
+    public String getDriver() {
+        return Utils.getJDBCDriver();
+    }
+
+    @Override
+    public String getUser() {
+        return Utils.getJDBCUser();
+    }
+
+    @Override
+    public String getPassword() {
+        return Utils.getJDBCPassword();
+    }
+
+    @Override
+    public String getValidationQuery() {
+        return Utils.getValidationQuery();
+    }
+}
diff --git a/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/QueryConstants.java b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/QueryConstants.java
new file mode 100644
index 0000000..6b3da31
--- /dev/null
+++ b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/QueryConstants.java
@@ -0,0 +1,33 @@
+package org.apache.custos.service.profile.commons.utils;
+
+import org.apache.custos.profile.models.user.UserProfile;
+import org.apache.custos.profile.models.workspace.Gateway;
+
+/**
+ * Created by goshenoy on 03/08/2017.
+ */
+public class QueryConstants {
+
+
+    public static final String FIND_USER_PROFILE_BY_USER_ID = "SELECT u FROM UserProfileEntity u " +
+            "where u.userId LIKE :" + UserProfile._Fields.USER_ID.getFieldName() + " " +
+            "AND u.gatewayId LIKE :" + UserProfile._Fields.GATEWAY_ID.getFieldName() + "";
+
+    public static final String FIND_ALL_USER_PROFILES_BY_GATEWAY_ID = "SELECT u FROM UserProfileEntity u " +
+            "where u.gatewayId LIKE :" + UserProfile._Fields.GATEWAY_ID.getFieldName() + "";
+
+    public static final String FIND_GATEWAY_BY_INTERNAL_ID = "SELECT g FROM GatewayEntity g " +
+            "where g.airavataInternalGatewayId LIKE :" + Gateway._Fields.AIRAVATA_INTERNAL_GATEWAY_ID.getFieldName();
+
+    public static final String FIND_DUPLICATE_GATEWAY = "SELECT g FROM GatewayEntity g " +
+            "where g.gatewayApprovalStatus IN :" + Gateway._Fields.GATEWAY_APPROVAL_STATUS.getFieldName() + " " +
+            "and (g.gatewayId LIKE :" + Gateway._Fields.GATEWAY_ID.getFieldName() + " " +
+            "     or g.gatewayName LIKE :" + Gateway._Fields.GATEWAY_NAME.getFieldName() + " " +
+            "     or g.gatewayUrl LIKE :" + Gateway._Fields.GATEWAY_URL.getFieldName() + " " +
+            "    )";
+
+    public static final String GET_ALL_GATEWAYS = "SELECT g FROM GatewayEntity g";
+
+    public static final String GET_USER_GATEWAYS = "SELECT g from GatewayEntity g " +
+            "where g.requesterUsername LIKE :" + Gateway._Fields.REQUESTER_USERNAME.getFieldName() + "";
+}
diff --git a/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/Utils.java b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/Utils.java
new file mode 100644
index 0000000..78033cc
--- /dev/null
+++ b/custos-services/profile-service/profile-service-commons/src/main/java/org/apache/custos/service/profile/commons/utils/Utils.java
@@ -0,0 +1,122 @@
+/*
+ *
+ * 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 org.apache.custos.service.profile.commons.utils;
+
+import org.apache.custos.commons.exceptions.ApplicationSettingsException;
+import org.apache.custos.commons.utils.ServerSettings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URI;
+
+
+public class Utils {
+    private final static Logger logger = LoggerFactory.getLogger(Utils.class);
+
+    public static String getJDBCURL(){
+    	try {
+            return ServerSettings.getSetting(JPAConstants.KEY_JDBC_URL);
+		} catch (ApplicationSettingsException e) {
+            logger.error(e.getMessage(), e);
+            return null;
+        }
+    }
+
+    public static String getHost(){
+        try{
+            String jdbcURL = getJDBCURL();
+            String cleanURI = jdbcURL.substring(5);
+            URI uri = URI.create(cleanURI);
+            return uri.getHost();
+        } catch (Exception e) {
+            logger.error(e.getMessage(), e);
+            return null;
+        }
+    }
+
+    public static int getPort(){
+        try{
+            String jdbcURL = getJDBCURL();
+            String cleanURI = jdbcURL.substring(5);
+            URI uri = URI.create(cleanURI);
+            return uri.getPort();
+        } catch (Exception e) {
+            logger.error(e.getMessage(), e);
+            return -1;
+        }
+    }
+
+    public static int getJPACacheSize (){
+        try {
+            String cache = ServerSettings.getSetting(JPAConstants.JPA_CACHE_SIZE, "5000");
+            return Integer.parseInt(cache);
+        }catch (Exception e){
+            logger.error(e.getMessage(), e);
+            return -1;
+        }
+    }
+
+    public static String isCachingEnabled (){
+        try {
+            return ServerSettings.getSetting(JPAConstants.ENABLE_CACHING, "true");
+        }catch (Exception e){
+            logger.error(e.getMessage(), e);
+            return "true";
+        }
+    }
+
+    public static String getJDBCUser(){
+    	try {
+		    return ServerSettings.getSetting(JPAConstants.KEY_JDBC_USER);
+		} catch (ApplicationSettingsException e) {
+            logger.error(e.getMessage(), e);
+            return null;
+		}
+    }
+
+    public static String getValidationQuery(){
+    	try {
+            return ServerSettings.getSetting(JPAConstants.VALIDATION_QUERY);
+		} catch (ApplicationSettingsException e) {
+            logger.error(e.getMessage(), e);
+            return null;
+		}
+    }
+
+    public static String getJDBCPassword(){
+    	try {
+            return ServerSettings.getSetting(JPAConstants.KEY_JDBC_PASSWORD);
+		} catch (ApplicationSettingsException e) {
+            logger.error(e.getMessage(), e);
+            return null;
+		}
+
+    }
+
+    public static String getJDBCDriver(){
+    	try {
+            return ServerSettings.getSetting(JPAConstants.KEY_JDBC_DRIVER);
+		} catch (ApplicationSettingsException e) {
+            logger.error(e.getMessage(), e);
+            return null;
+		}
+    }
+}
diff --git a/custos-services/profile-service/profile-service-commons/src/main/resources/META-INF/persistence.xml b/custos-services/profile-service/profile-service-commons/src/main/resources/META-INF/persistence.xml
new file mode 100644
index 0000000..9f20353
--- /dev/null
+++ b/custos-services/profile-service/profile-service-commons/src/main/resources/META-INF/persistence.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--*
+ *
+ * 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.
+ *
+* -->
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
+    <persistence-unit name="profile_service">
+        <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
+        <class>org.apache.custos.service.profile.commons.user.entities.UserProfileEntity</class>
+        <class>org.apache.custos.service.profile.commons.user.entities.NSFDemographicsEntity</class>
+        <class>org.apache.custos.service.profile.commons.user.entities.CustomizedDashboardEntity</class>
+        <class>org.apache.custos.service.profile.commons.tenant.entities.GatewayEntity</class>
+        <exclude-unlisted-classes>true</exclude-unlisted-classes>
+
+        <properties>
+            <property name="openjpa.jdbc.MappingDefaults"
+                      value="ForeignKeyDeleteAction=cascade, JoinForeignKeyDeleteAction=cascade" />
+        </properties>
+    </persistence-unit>
+</persistence>
diff --git a/custos-services/profile-service/profile-service-models/pom.xml b/custos-services/profile-service/profile-service-models/pom.xml
new file mode 100644
index 0000000..dcae7be
--- /dev/null
+++ b/custos-services/profile-service/profile-service-models/pom.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>profile-service</artifactId>
+        <groupId>org.apache.custos</groupId>
+        <version>1.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>profile-service-models</artifactId>
+</project>
\ No newline at end of file
diff --git a/custos-services/profile-service/profile-service-models/src/main/java/org/apache/custos/profile/models/tenant/PasswordCredential.java b/custos-services/profile-service/profile-service-models/src/main/java/org/apache/custos/profile/models/tenant/PasswordCredential.java
new file mode 100644
index 0000000..7a225c7
--- /dev/null
+++ b/custos-services/profile-service/profile-service-models/src/main/java/org/apache/custos/profile/models/tenant/PasswordCredential.java
@@ -0,0 +1,996 @@
+/**
+ * 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.
+ */
+
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+package org.apache.custos.profile.models.tenant;
+
+@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)")
+public class PasswordCredential implements org.apache.thrift.TBase<PasswordCredential, PasswordCredential._Fields>, java.io.Serializable, Cloneable, Comparable<PasswordCredential> {
+  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("PasswordCredential");
+
+  private static final org.apache.thrift.protocol.TField GATEWAY_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("gatewayId", org.apache.thrift.protocol.TType.STRING, (short)1);
+  private static final org.apache.thrift.protocol.TField PORTAL_USER_NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("portalUserName", org.apache.thrift.protocol.TType.STRING, (short)2);
+  private static final org.apache.thrift.protocol.TField LOGIN_USER_NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("loginUserName", org.apache.thrift.protocol.TType.STRING, (short)3);
+  private static final org.apache.thrift.protocol.TField PASSWORD_FIELD_DESC = new org.apache.thrift.protocol.TField("password", org.apache.thrift.protocol.TType.STRING, (short)4);
+  private static final org.apache.thrift.protocol.TField DESCRIPTION_FIELD_DESC = new org.apache.thrift.protocol.TField("description", org.apache.thrift.protocol.TType.STRING, (short)5);
+  private static final org.apache.thrift.protocol.TField PERSISTED_TIME_FIELD_DESC = new org.apache.thrift.protocol.TField("persistedTime", org.apache.thrift.protocol.TType.I64, (short)6);
+  private static final org.apache.thrift.protocol.TField TOKEN_FIELD_DESC = new org.apache.thrift.protocol.TField("token", org.apache.thrift.protocol.TType.STRING, (short)7);
+
+  private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new PasswordCredentialStandardSchemeFactory();
+  private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new PasswordCredentialTupleSchemeFactory();
+
+  private String gatewayId; // required
+  private String portalUserName; // required
+  private String loginUserName; // required
+  private String password; // required
+  private String description; // optional
+  private long persistedTime; // optional
+  private String token; // optional
+
+  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+  public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+    GATEWAY_ID((short)1, "gatewayId"),
+    PORTAL_USER_NAME((short)2, "portalUserName"),
+    LOGIN_USER_NAME((short)3, "loginUserName"),
+    PASSWORD((short)4, "password"),
+    DESCRIPTION((short)5, "description"),
+    PERSISTED_TIME((short)6, "persistedTime"),
+    TOKEN((short)7, "token");
+
+    private static final java.util.Map<String, _Fields> byName = new java.util.HashMap<String, _Fields>();
+
+    static {
+      for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
+        byName.put(field.getFieldName(), field);
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, or null if its not found.
+     */
+    public static _Fields findByThriftId(int fieldId) {
+      switch(fieldId) {
+        case 1: // GATEWAY_ID
+          return GATEWAY_ID;
+        case 2: // PORTAL_USER_NAME
+          return PORTAL_USER_NAME;
+        case 3: // LOGIN_USER_NAME
+          return LOGIN_USER_NAME;
+        case 4: // PASSWORD
+          return PASSWORD;
+        case 5: // DESCRIPTION
+          return DESCRIPTION;
+        case 6: // PERSISTED_TIME
+          return PERSISTED_TIME;
+        case 7: // TOKEN
+          return TOKEN;
+        default:
+          return null;
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, throwing an exception
+     * if it is not found.
+     */
+    public static _Fields findByThriftIdOrThrow(int fieldId) {
+      _Fields fields = findByThriftId(fieldId);
+      if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+      return fields;
+    }
+
+    /**
+     * Find the _Fields constant that matches name, or null if its not found.
+     */
+    public static _Fields findByName(String name) {
+      return byName.get(name);
+    }
+
+    private final short _thriftId;
+    private final String _fieldName;
+
+    _Fields(short thriftId, String fieldName) {
+      _thriftId = thriftId;
+      _fieldName = fieldName;
+    }
+
+    public short getThriftFieldId() {
+      return _thriftId;
+    }
+
+    public String getFieldName() {
+      return _fieldName;
+    }
+  }
+
+  // isset id assignments
+  private static final int __PERSISTEDTIME_ISSET_ID = 0;
+  private byte __isset_bitfield = 0;
+  private static final _Fields optionals[] = {_Fields.DESCRIPTION, _Fields.PERSISTED_TIME, _Fields.TOKEN};
+  public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+  static {
+    java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+    tmpMap.put(_Fields.GATEWAY_ID, new org.apache.thrift.meta_data.FieldMetaData("gatewayId", org.apache.thrift.TFieldRequirementType.REQUIRED,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.PORTAL_USER_NAME, new org.apache.thrift.meta_data.FieldMetaData("portalUserName", org.apache.thrift.TFieldRequirementType.REQUIRED,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.LOGIN_USER_NAME, new org.apache.thrift.meta_data.FieldMetaData("loginUserName", org.apache.thrift.TFieldRequirementType.REQUIRED,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.PASSWORD, new org.apache.thrift.meta_data.FieldMetaData("password", org.apache.thrift.TFieldRequirementType.REQUIRED,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.DESCRIPTION, new org.apache.thrift.meta_data.FieldMetaData("description", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.PERSISTED_TIME, new org.apache.thrift.meta_data.FieldMetaData("persistedTime", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I64)));
+    tmpMap.put(_Fields.TOKEN, new org.apache.thrift.meta_data.FieldMetaData("token", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
+    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(PasswordCredential.class, metaDataMap);
+  }
+
+  public PasswordCredential() {
+  }
+
+  public PasswordCredential(
+    String gatewayId,
+    String portalUserName,
+    String loginUserName,
+    String password)
+  {
+    this();
+    this.gatewayId = gatewayId;
+    this.portalUserName = portalUserName;
+    this.loginUserName = loginUserName;
+    this.password = password;
+  }
+
+  /**
+   * Performs a deep copy on <i>other</i>.
+   */
+  public PasswordCredential(PasswordCredential other) {
+    __isset_bitfield = other.__isset_bitfield;
+    if (other.isSetGatewayId()) {
+      this.gatewayId = other.gatewayId;
+    }
+    if (other.isSetPortalUserName()) {
+      this.portalUserName = other.portalUserName;
+    }
+    if (other.isSetLoginUserName()) {
+      this.loginUserName = other.loginUserName;
+    }
+    if (other.isSetPassword()) {
+      this.password = other.password;
+    }
+    if (other.isSetDescription()) {
+      this.description = other.description;
+    }
+    this.persistedTime = other.persistedTime;
+    if (other.isSetToken()) {
+      this.token = other.token;
+    }
+  }
+
+  public PasswordCredential deepCopy() {
+    return new PasswordCredential(this);
+  }
+
+  @Override
+  public void clear() {
+    this.gatewayId = null;
+    this.portalUserName = null;
+    this.loginUserName = null;
+    this.password = null;
+    this.description = null;
+    setPersistedTimeIsSet(false);
+    this.persistedTime = 0;
+    this.token = null;
+  }
+
+  public String getGatewayId() {
+    return this.gatewayId;
+  }
+
+  public void setGatewayId(String gatewayId) {
+    this.gatewayId = gatewayId;
+  }
+
+  public void unsetGatewayId() {
+    this.gatewayId = null;
+  }
+
+  /** Returns true if field gatewayId is set (has been assigned a value) and false otherwise */
+  public boolean isSetGatewayId() {
+    return this.gatewayId != null;
+  }
+
+  public void setGatewayIdIsSet(boolean value) {
+    if (!value) {
+      this.gatewayId = null;
+    }
+  }
+
+  public String getPortalUserName() {
+    return this.portalUserName;
+  }
+
+  public void setPortalUserName(String portalUserName) {
+    this.portalUserName = portalUserName;
+  }
+
+  public void unsetPortalUserName() {
+    this.portalUserName = null;
+  }
+
+  /** Returns true if field portalUserName is set (has been assigned a value) and false otherwise */
+  public boolean isSetPortalUserName() {
+    return this.portalUserName != null;
+  }
+
+  public void setPortalUserNameIsSet(boolean value) {
+    if (!value) {
+      this.portalUserName = null;
+    }
+  }
+
+  public String getLoginUserName() {
+    return this.loginUserName;
+  }
+
+  public void setLoginUserName(String loginUserName) {
+    this.loginUserName = loginUserName;
+  }
+
+  public void unsetLoginUserName() {
+    this.loginUserName = null;
+  }
+
+  /** Returns true if field loginUserName is set (has been assigned a value) and false otherwise */
+  public boolean isSetLoginUserName() {
+    return this.loginUserName != null;
+  }
+
+  public void setLoginUserNameIsSet(boolean value) {
+    if (!value) {
+      this.loginUserName = null;
+    }
+  }
+
+  public String getPassword() {
+    return this.password;
+  }
+
+  public void setPassword(String password) {
+    this.password = password;
+  }
+
+  public void unsetPassword() {
+    this.password = null;
+  }
+
+  /** Returns true if field password is set (has been assigned a value) and false otherwise */
+  public boolean isSetPassword() {
+    return this.password != null;
+  }
+
+  public void setPasswordIsSet(boolean value) {
+    if (!value) {
+      this.password = null;
+    }
+  }
+
+  public String getDescription() {
+    return this.description;
+  }
+
+  public void setDescription(String description) {
+    this.description = description;
+  }
+
+  public void unsetDescription() {
+    this.description = null;
+  }
+
+  /** Returns true if field description is set (has been assigned a value) and false otherwise */
+  public boolean isSetDescription() {
+    return this.description != null;
+  }
+
+  public void setDescriptionIsSet(boolean value) {
+    if (!value) {
+      this.description = null;
+    }
+  }
+
+  public long getPersistedTime() {
+    return this.persistedTime;
+  }
+
+  public void setPersistedTime(long persistedTime) {
+    this.persistedTime = persistedTime;
+    setPersistedTimeIsSet(true);
+  }
+
+  public void unsetPersistedTime() {
+    __isset_bitfield = org.apache.thrift.EncodingUtils.clearBit(__isset_bitfield, __PERSISTEDTIME_ISSET_ID);
+  }
+
+  /** Returns true if field persistedTime is set (has been assigned a value) and false otherwise */
+  public boolean isSetPersistedTime() {
+    return org.apache.thrift.EncodingUtils.testBit(__isset_bitfield, __PERSISTEDTIME_ISSET_ID);
+  }
+
+  public void setPersistedTimeIsSet(boolean value) {
+    __isset_bitfield = org.apache.thrift.EncodingUtils.setBit(__isset_bitfield, __PERSISTEDTIME_ISSET_ID, value);
+  }
+
+  public String getToken() {
+    return this.token;
+  }
+
+  public void setToken(String token) {
+    this.token = token;
+  }
+
+  public void unsetToken() {
+    this.token = null;
+  }
+
+  /** Returns true if field token is set (has been assigned a value) and false otherwise */
+  public boolean isSetToken() {
+    return this.token != null;
+  }
+
+  public void setTokenIsSet(boolean value) {
+    if (!value) {
+      this.token = null;
+    }
+  }
+
+  public void setFieldValue(_Fields field, Object value) {
+    switch (field) {
+    case GATEWAY_ID:
+      if (value == null) {
+        unsetGatewayId();
+      } else {
+        setGatewayId((String)value);
+      }
+      break;
+
+    case PORTAL_USER_NAME:
+      if (value == null) {
+        unsetPortalUserName();
+      } else {
+        setPortalUserName((String)value);
+      }
+      break;
+
+    case LOGIN_USER_NAME:
+      if (value == null) {
+        unsetLoginUserName();
+      } else {
+        setLoginUserName((String)value);
+      }
+      break;
+
+    case PASSWORD:
+      if (value == null) {
+        unsetPassword();
+      } else {
+        setPassword((String)value);
+      }
+      break;
+
+    case DESCRIPTION:
+      if (value == null) {
+        unsetDescription();
+      } else {
+        setDescription((String)value);
+      }
+      break;
+
+    case PERSISTED_TIME:
+      if (value == null) {
+        unsetPersistedTime();
+      } else {
+        setPersistedTime((Long)value);
+      }
+      break;
+
+    case TOKEN:
+      if (value == null) {
+        unsetToken();
+      } else {
+        setToken((String)value);
+      }
+      break;
+
+    }
+  }
+
+  public Object getFieldValue(_Fields field) {
+    switch (field) {
+    case GATEWAY_ID:
+      return getGatewayId();
+
+    case PORTAL_USER_NAME:
+      return getPortalUserName();
+
+    case LOGIN_USER_NAME:
+      return getLoginUserName();
+
+    case PASSWORD:
+      return getPassword();
+
+    case DESCRIPTION:
+      return getDescription();
+
+    case PERSISTED_TIME:
+      return getPersistedTime();
+
+    case TOKEN:
+      return getToken();
+
+    }
+    throw new IllegalStateException();
+  }
+
+  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+  public boolean isSet(_Fields field) {
+    if (field == null) {
+      throw new IllegalArgumentException();
+    }
+
+    switch (field) {
+    case GATEWAY_ID:
+      return isSetGatewayId();
+    case PORTAL_USER_NAME:
+      return isSetPortalUserName();
+    case LOGIN_USER_NAME:
+      return isSetLoginUserName();
+    case PASSWORD:
+      return isSetPassword();
+    case DESCRIPTION:
+      return isSetDescription();
+    case PERSISTED_TIME:
+      return isSetPersistedTime();
+    case TOKEN:
+      return isSetToken();
+    }
+    throw new IllegalStateException();
+  }
+
+  @Override
+  public boolean equals(Object that) {
+    if (that == null)
+      return false;
+    if (that instanceof PasswordCredential)
+      return this.equals((PasswordCredential)that);
+    return false;
+  }
+
+  public boolean equals(PasswordCredential that) {
+    if (that == null)
+      return false;
+    if (this == that)
+      return true;
+
+    boolean this_present_gatewayId = true && this.isSetGatewayId();
+    boolean that_present_gatewayId = true && that.isSetGatewayId();
+    if (this_present_gatewayId || that_present_gatewayId) {
+      if (!(this_present_gatewayId && that_present_gatewayId))
+        return false;
+      if (!this.gatewayId.equals(that.gatewayId))
+        return false;
+    }
+
+    boolean this_present_portalUserName = true && this.isSetPortalUserName();
+    boolean that_present_portalUserName = true && that.isSetPortalUserName();
+    if (this_present_portalUserName || that_present_portalUserName) {
+      if (!(this_present_portalUserName && that_present_portalUserName))
+        return false;
+      if (!this.portalUserName.equals(that.portalUserName))
+        return false;
+    }
+
+    boolean this_present_loginUserName = true && this.isSetLoginUserName();
+    boolean that_present_loginUserName = true && that.isSetLoginUserName();
+    if (this_present_loginUserName || that_present_loginUserName) {
+      if (!(this_present_loginUserName && that_present_loginUserName))
+        return false;
+      if (!this.loginUserName.equals(that.loginUserName))
+        return false;
+    }
+
+    boolean this_present_password = true && this.isSetPassword();
+    boolean that_present_password = true && that.isSetPassword();
+    if (this_present_password || that_present_password) {
+      if (!(this_present_password && that_present_password))
+        return false;
+      if (!this.password.equals(that.password))
+        return false;
+    }
+
+    boolean this_present_description = true && this.isSetDescription();
+    boolean that_present_description = true && that.isSetDescription();
+    if (this_present_description || that_present_description) {
+      if (!(this_present_description && that_present_description))
+        return false;
+      if (!this.description.equals(that.description))
+        return false;
+    }
+
+    boolean this_present_persistedTime = true && this.isSetPersistedTime();
+    boolean that_present_persistedTime = true && that.isSetPersistedTime();
+    if (this_present_persistedTime || that_present_persistedTime) {
+      if (!(this_present_persistedTime && that_present_persistedTime))
+        return false;
+      if (this.persistedTime != that.persistedTime)
+        return false;
+    }
+
+    boolean this_present_token = true && this.isSetToken();
+    boolean that_present_token = true && that.isSetToken();
+    if (this_present_token || that_present_token) {
+      if (!(this_present_token && that_present_token))
+        return false;
+      if (!this.token.equals(that.token))
+        return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int hashCode = 1;
+
+    hashCode = hashCode * 8191 + ((isSetGatewayId()) ? 131071 : 524287);
+    if (isSetGatewayId())
+      hashCode = hashCode * 8191 + gatewayId.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetPortalUserName()) ? 131071 : 524287);
+    if (isSetPortalUserName())
+      hashCode = hashCode * 8191 + portalUserName.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetLoginUserName()) ? 131071 : 524287);
+    if (isSetLoginUserName())
+      hashCode = hashCode * 8191 + loginUserName.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetPassword()) ? 131071 : 524287);
+    if (isSetPassword())
+      hashCode = hashCode * 8191 + password.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetDescription()) ? 131071 : 524287);
+    if (isSetDescription())
+      hashCode = hashCode * 8191 + description.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetPersistedTime()) ? 131071 : 524287);
+    if (isSetPersistedTime())
+      hashCode = hashCode * 8191 + org.apache.thrift.TBaseHelper.hashCode(persistedTime);
+
+    hashCode = hashCode * 8191 + ((isSetToken()) ? 131071 : 524287);
+    if (isSetToken())
+      hashCode = hashCode * 8191 + token.hashCode();
+
+    return hashCode;
+  }
+
+  @Override
+  public int compareTo(PasswordCredential other) {
+    if (!getClass().equals(other.getClass())) {
+      return getClass().getName().compareTo(other.getClass().getName());
+    }
+
+    int lastComparison = 0;
+
+    lastComparison = Boolean.valueOf(isSetGatewayId()).compareTo(other.isSetGatewayId());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetGatewayId()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.gatewayId, other.gatewayId);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetPortalUserName()).compareTo(other.isSetPortalUserName());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetPortalUserName()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.portalUserName, other.portalUserName);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetLoginUserName()).compareTo(other.isSetLoginUserName());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetLoginUserName()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.loginUserName, other.loginUserName);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetPassword()).compareTo(other.isSetPassword());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetPassword()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.password, other.password);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetDescription()).compareTo(other.isSetDescription());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetDescription()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.description, other.description);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetPersistedTime()).compareTo(other.isSetPersistedTime());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetPersistedTime()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.persistedTime, other.persistedTime);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetToken()).compareTo(other.isSetToken());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetToken()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.token, other.token);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    return 0;
+  }
+
+  public _Fields fieldForId(int fieldId) {
+    return _Fields.findByThriftId(fieldId);
+  }
+
+  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+    scheme(iprot).read(iprot, this);
+  }
+
+  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+    scheme(oprot).write(oprot, this);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("PasswordCredential(");
+    boolean first = true;
+
+    sb.append("gatewayId:");
+    if (this.gatewayId == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.gatewayId);
+    }
+    first = false;
+    if (!first) sb.append(", ");
+    sb.append("portalUserName:");
+    if (this.portalUserName == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.portalUserName);
+    }
+    first = false;
+    if (!first) sb.append(", ");
+    sb.append("loginUserName:");
+    if (this.loginUserName == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.loginUserName);
+    }
+    first = false;
+    if (!first) sb.append(", ");
+    sb.append("password:");
+    if (this.password == null) {
+      sb.append("null");
+    } else {
+      sb.append(this.password);
+    }
+    first = false;
+    if (isSetDescription()) {
+      if (!first) sb.append(", ");
+      sb.append("description:");
+      if (this.description == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.description);
+      }
+      first = false;
+    }
+    if (isSetPersistedTime()) {
+      if (!first) sb.append(", ");
+      sb.append("persistedTime:");
+      sb.append(this.persistedTime);
+      first = false;
+    }
+    if (isSetToken()) {
+      if (!first) sb.append(", ");
+      sb.append("token:");
+      if (this.token == null) {
+        sb.append("null");
+      } else {
+        sb.append(this.token);
+      }
+      first = false;
+    }
+    sb.append(")");
+    return sb.toString();
+  }
+
+  public void validate() throws org.apache.thrift.TException {
+    // check for required fields
+    if (!isSetGatewayId()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'gatewayId' is unset! Struct:" + toString());
+    }
+
+    if (!isSetPortalUserName()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'portalUserName' is unset! Struct:" + toString());
+    }
+
+    if (!isSetLoginUserName()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'loginUserName' is unset! Struct:" + toString());
+    }
+
+    if (!isSetPassword()) {
+      throw new org.apache.thrift.protocol.TProtocolException("Required field 'password' is unset! Struct:" + toString());
+    }
+
+    // check for sub-struct validity
+  }
+
+  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+    try {
+      write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+    try {
+      // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+      __isset_bitfield = 0;
+      read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+    } catch (org.apache.thrift.TException te) {
+      throw new java.io.IOException(te);
+    }
+  }
+
+  private static class PasswordCredentialStandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
+    public PasswordCredentialStandardScheme getScheme() {
+      return new PasswordCredentialStandardScheme();
+    }
+  }
+
+  private static class PasswordCredentialStandardScheme extends org.apache.thrift.scheme.StandardScheme<PasswordCredential> {
+
+    public void read(org.apache.thrift.protocol.TProtocol iprot, PasswordCredential struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TField schemeField;
+      iprot.readStructBegin();
+      while (true)
+      {
+        schemeField = iprot.readFieldBegin();
+        if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 
+          break;
+        }
+        switch (schemeField.id) {
+          case 1: // GATEWAY_ID
+            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+              struct.gatewayId = iprot.readString();
+              struct.setGatewayIdIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          case 2: // PORTAL_USER_NAME
+            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+              struct.portalUserName = iprot.readString();
+              struct.setPortalUserNameIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          case 3: // LOGIN_USER_NAME
+            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+              struct.loginUserName = iprot.readString();
+              struct.setLoginUserNameIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          case 4: // PASSWORD
+            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+              struct.password = iprot.readString();
+              struct.setPasswordIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          case 5: // DESCRIPTION
+            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+              struct.description = iprot.readString();
+              struct.setDescriptionIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          case 6: // PERSISTED_TIME
+            if (schemeField.type == org.apache.thrift.protocol.TType.I64) {
+              struct.persistedTime = iprot.readI64();
+              struct.setPersistedTimeIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          case 7: // TOKEN
+            if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+              struct.token = iprot.readString();
+              struct.setTokenIsSet(true);
+            } else { 
+              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+            }
+            break;
+          default:
+            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+        }
+        iprot.readFieldEnd();
+      }
+      iprot.readStructEnd();
+      struct.validate();
+    }
+
+    public void write(org.apache.thrift.protocol.TProtocol oprot, PasswordCredential struct) throws org.apache.thrift.TException {
+      struct.validate();
+
+      oprot.writeStructBegin(STRUCT_DESC);
+      if (struct.gatewayId != null) {
+        oprot.writeFieldBegin(GATEWAY_ID_FIELD_DESC);
+        oprot.writeString(struct.gatewayId);
+        oprot.writeFieldEnd();
+      }
+      if (struct.portalUserName != null) {
+        oprot.writeFieldBegin(PORTAL_USER_NAME_FIELD_DESC);
+        oprot.writeString(struct.portalUserName);
+        oprot.writeFieldEnd();
+      }
+      if (struct.loginUserName != null) {
+        oprot.writeFieldBegin(LOGIN_USER_NAME_FIELD_DESC);
+        oprot.writeString(struct.loginUserName);
+        oprot.writeFieldEnd();
+      }
+      if (struct.password != null) {
+        oprot.writeFieldBegin(PASSWORD_FIELD_DESC);
+        oprot.writeString(struct.password);
+        oprot.writeFieldEnd();
+      }
+      if (struct.description != null) {
+        if (struct.isSetDescription()) {
+          oprot.writeFieldBegin(DESCRIPTION_FIELD_DESC);
+          oprot.writeString(struct.description);
+          oprot.writeFieldEnd();
+        }
+      }
+      if (struct.isSetPersistedTime()) {
+        oprot.writeFieldBegin(PERSISTED_TIME_FIELD_DESC);
+        oprot.writeI64(struct.persistedTime);
+        oprot.writeFieldEnd();
+      }
+      if (struct.token != null) {
+        if (struct.isSetToken()) {
+          oprot.writeFieldBegin(TOKEN_FIELD_DESC);
+          oprot.writeString(struct.token);
+          oprot.writeFieldEnd();
+        }
+      }
+      oprot.writeFieldStop();
+      oprot.writeStructEnd();
+    }
+
+  }
+
+  private static class PasswordCredentialTupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {
+    public PasswordCredentialTupleScheme getScheme() {
+      return new PasswordCredentialTupleScheme();
+    }
+  }
+
+  private static class PasswordCredentialTupleScheme extends org.apache.thrift.scheme.TupleScheme<PasswordCredential> {
+
+    @Override
+    public void write(org.apache.thrift.protocol.TProtocol prot, PasswordCredential struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TTupleProtocol oprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
+      oprot.writeString(struct.gatewayId);
+      oprot.writeString(struct.portalUserName);
+      oprot.writeString(struct.loginUserName);
+      oprot.writeString(struct.password);
+      java.util.BitSet optionals = new java.util.BitSet();
+      if (struct.isSetDescription()) {
+        optionals.set(0);
+      }
+      if (struct.isSetPersistedTime()) {
+        optionals.set(1);
+      }
+      if (struct.isSetToken()) {
+        optionals.set(2);
+      }
+      oprot.writeBitSet(optionals, 3);
+      if (struct.isSetDescription()) {
+        oprot.writeString(struct.description);
+      }
+      if (struct.isSetPersistedTime()) {
+        oprot.writeI64(struct.persistedTime);
+      }
+      if (struct.isSetToken()) {
+        oprot.writeString(struct.token);
+      }
+    }
+
+    @Override
+    public void read(org.apache.thrift.protocol.TProtocol prot, PasswordCredential struct) throws org.apache.thrift.TException {
+      org.apache.thrift.protocol.TTupleProtocol iprot = (org.apache.thrift.protocol.TTupleProtocol) prot;
+      struct.gatewayId = iprot.readString();
+      struct.setGatewayIdIsSet(true);
+      struct.portalUserName = iprot.readString();
+      struct.setPortalUserNameIsSet(true);
+      struct.loginUserName = iprot.readString();
+      struct.setLoginUserNameIsSet(true);
+      struct.password = iprot.readString();
+      struct.setPasswordIsSet(true);
+      java.util.BitSet incoming = iprot.readBitSet(3);
+      if (incoming.get(0)) {
+        struct.description = iprot.readString();
+        struct.setDescriptionIsSet(true);
+      }
+      if (incoming.get(1)) {
+        struct.persistedTime = iprot.readI64();
+        struct.setPersistedTimeIsSet(true);
+      }
+      if (incoming.get(2)) {
+        struct.token = iprot.readString();
+        struct.setTokenIsSet(true);
+      }
+    }
+  }
+
+  private static <S extends org.apache.thrift.scheme.IScheme> S scheme(org.apache.thrift.protocol.TProtocol proto) {
+    return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) ? STANDARD_SCHEME_FACTORY : TUPLE_SCHEME_FACTORY).getScheme();
+  }
+}
+
diff --git a/custos-services/profile-service/profile-service-models/src/main/java/org/apache/custos/profile/models/tenant/Tenant.java b/custos-services/profile-service/profile-service-models/src/main/java/org/apache/custos/profile/models/tenant/Tenant.java
new file mode 100644
index 0000000..68b6bfd
--- /dev/null
+++ b/custos-services/profile-service/profile-service-models/src/main/java/org/apache/custos/profile/models/tenant/Tenant.java
@@ -0,0 +1,1543 @@
+/**
+ * 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.
+ */
+
+/**
+ * Autogenerated by Thrift Compiler (0.10.0)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ *  @generated
+ */
+package org.apache.custos.profile.models.tenant;
+
+@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
+@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.10.0)")
+public class Tenant implements org.apache.thrift.TBase<Tenant, Tenant._Fields>, java.io.Serializable, Cloneable, Comparable<Tenant> {
+  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("Tenant");
+
+  private static final org.apache.thrift.protocol.TField TENANT_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("tenantId", org.apache.thrift.protocol.TType.STRING, (short)1);
+  private static final org.apache.thrift.protocol.TField TENANT_APPROVAL_STATUS_FIELD_DESC = new org.apache.thrift.protocol.TField("tenantApprovalStatus", org.apache.thrift.protocol.TType.I32, (short)2);
+  private static final org.apache.thrift.protocol.TField TENANT_NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("tenantName", org.apache.thrift.protocol.TType.STRING, (short)3);
+  private static final org.apache.thrift.protocol.TField DOMAIN_FIELD_DESC = new org.apache.thrift.protocol.TField("domain", org.apache.thrift.protocol.TType.STRING, (short)4);
+  private static final org.apache.thrift.protocol.TField EMAIL_ADDRESS_FIELD_DESC = new org.apache.thrift.protocol.TField("emailAddress", org.apache.thrift.protocol.TType.STRING, (short)5);
+  private static final org.apache.thrift.protocol.TField TENANT_ACRONYM_FIELD_DESC = new org.apache.thrift.protocol.TField("tenantAcronym", org.apache.thrift.protocol.TType.STRING, (short)6);
+  private static final org.apache.thrift.protocol.TField TENANT_URL_FIELD_DESC = new org.apache.thrift.protocol.TField("tenantURL", org.apache.thrift.protocol.TType.STRING, (short)7);
+  private static final org.apache.thrift.protocol.TField TENANT_PUBLIC_ABSTRACT_FIELD_DESC = new org.apache.thrift.protocol.TField("tenantPublicAbstract", org.apache.thrift.protocol.TType.STRING, (short)8);
+  private static final org.apache.thrift.protocol.TField REVIEW_PROPOSAL_DESCRIPTION_FIELD_DESC = new org.apache.thrift.protocol.TField("reviewProposalDescription", org.apache.thrift.protocol.TType.STRING, (short)9);
+  private static final org.apache.thrift.protocol.TField DECLINED_REASON_FIELD_DESC = new org.apache.thrift.protocol.TField("declinedReason", org.apache.thrift.protocol.TType.STRING, (short)15);
+  private static final org.apache.thrift.protocol.TField REQUEST_CREATION_TIME_FIELD_DESC = new org.apache.thrift.protocol.TField("requestCreationTime", org.apache.thrift.protocol.TType.I64, (short)18);
+  private static final org.apache.thrift.protocol.TField REQUESTER_USERNAME_FIELD_DESC = new org.apache.thrift.protocol.TField("requesterUsername", org.apache.thrift.protocol.TType.STRING, (short)19);
+
+  private static final org.apache.thrift.scheme.SchemeFactory STANDARD_SCHEME_FACTORY = new TenantStandardSchemeFactory();
+  private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new TenantTupleSchemeFactory();
+
+  private String tenantId; // required
+  private TenantApprovalStatus tenantApprovalStatus; // required
+  private String tenantName; // optional
+  private String domain; // optional
+  private String emailAddress; // optional
+  private String tenantAcronym; // optional
+  private String tenantURL; // optional
+  private String tenantPublicAbstract; // optional
+  private String reviewProposalDescription; // optional
+  private String declinedReason; // optional
+  private long requestCreationTime; // optional
+  private String requesterUsername; // optional
+
+  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+  public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+    TENANT_ID((short)1, "tenantId"),
+    /**
+     *
+     * @see TenantApprovalStatus
+     */
+    TENANT_APPROVAL_STATUS((short)2, "tenantApprovalStatus"),
+    TENANT_NAME((short)3, "tenantName"),
+    DOMAIN((short)4, "domain"),
+    EMAIL_ADDRESS((short)5, "emailAddress"),
+    TENANT_ACRONYM((short)6, "tenantAcronym"),
+    TENANT_URL((short)7, "tenantURL"),
+    TENANT_PUBLIC_ABSTRACT((short)8, "tenantPublicAbstract"),
+    REVIEW_PROPOSAL_DESCRIPTION((short)9, "reviewProposalDescription"),
+    DECLINED_REASON((short)15, "declinedReason"),
+    REQUEST_CREATION_TIME((short)18, "requestCreationTime"),
+    REQUESTER_USERNAME((short)19, "requesterUsername");
+
+    private static final java.util.Map<String, _Fields> byName = new java.util.HashMap<String, _Fields>();
+
+    static {
+      for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {
+        byName.put(field.getFieldName(), field);
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, or null if its not found.
+     */
+    public static _Fields findByThriftId(int fieldId) {
+      switch(fieldId) {
+        case 1: // TENANT_ID
+          return TENANT_ID;
+        case 2: // TENANT_APPROVAL_STATUS
+          return TENANT_APPROVAL_STATUS;
+        case 3: // TENANT_NAME
+          return TENANT_NAME;
+        case 4: // DOMAIN
+          return DOMAIN;
+        case 5: // EMAIL_ADDRESS
+          return EMAIL_ADDRESS;
+        case 6: // TENANT_ACRONYM
+          return TENANT_ACRONYM;
+        case 7: // TENANT_URL
+          return TENANT_URL;
+        case 8: // TENANT_PUBLIC_ABSTRACT
+          return TENANT_PUBLIC_ABSTRACT;
+        case 9: // REVIEW_PROPOSAL_DESCRIPTION
+          return REVIEW_PROPOSAL_DESCRIPTION;
+        case 15: // DECLINED_REASON
+          return DECLINED_REASON;
+        case 18: // REQUEST_CREATION_TIME
+          return REQUEST_CREATION_TIME;
+        case 19: // REQUESTER_USERNAME
+          return REQUESTER_USERNAME;
+        default:
+          return null;
+      }
+    }
+
+    /**
+     * Find the _Fields constant that matches fieldId, throwing an exception
+     * if it is not found.
+     */
+    public static _Fields findByThriftIdOrThrow(int fieldId) {
+      _Fields fields = findByThriftId(fieldId);
+      if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+      return fields;
+    }
+
+    /**
+     * Find the _Fields constant that matches name, or null if its not found.
+     */
+    public static _Fields findByName(String name) {
+      return byName.get(name);
+    }
+
+    private final short _thriftId;
+    private final String _fieldName;
+
+    _Fields(short thriftId, String fieldName) {
+      _thriftId = thriftId;
+      _fieldName = fieldName;
+    }
+
+    public short getThriftFieldId() {
+      return _thriftId;
+    }
+
+    public String getFieldName() {
+      return _fieldName;
+    }
+  }
+
+  // isset id assignments
+  private static final int __REQUESTCREATIONTIME_ISSET_ID = 0;
+  private byte __isset_bitfield = 0;
+  private static final _Fields optionals[] = {_Fields.TENANT_NAME, _Fields.DOMAIN, _Fields.EMAIL_ADDRESS, _Fields.TENANT_ACRONYM, _Fields.TENANT_URL, _Fields.TENANT_PUBLIC_ABSTRACT, _Fields.REVIEW_PROPOSAL_DESCRIPTION, _Fields.DECLINED_REASON, _Fields.REQUEST_CREATION_TIME, _Fields.REQUESTER_USERNAME};
+  public static final java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+  static {
+    java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+    tmpMap.put(_Fields.TENANT_ID, new org.apache.thrift.meta_data.FieldMetaData("tenantId", org.apache.thrift.TFieldRequirementType.REQUIRED,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.TENANT_APPROVAL_STATUS, new org.apache.thrift.meta_data.FieldMetaData("tenantApprovalStatus", org.apache.thrift.TFieldRequirementType.REQUIRED,
+        new org.apache.thrift.meta_data.EnumMetaData(org.apache.thrift.protocol.TType.ENUM, TenantApprovalStatus.class)));
+    tmpMap.put(_Fields.TENANT_NAME, new org.apache.thrift.meta_data.FieldMetaData("tenantName", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.DOMAIN, new org.apache.thrift.meta_data.FieldMetaData("domain", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.EMAIL_ADDRESS, new org.apache.thrift.meta_data.FieldMetaData("emailAddress", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.TENANT_ACRONYM, new org.apache.thrift.meta_data.FieldMetaData("tenantAcronym", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.TENANT_URL, new org.apache.thrift.meta_data.FieldMetaData("tenantURL", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.TENANT_PUBLIC_ABSTRACT, new org.apache.thrift.meta_data.FieldMetaData("tenantPublicAbstract", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.REVIEW_PROPOSAL_DESCRIPTION, new org.apache.thrift.meta_data.FieldMetaData("reviewProposalDescription", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.DECLINED_REASON, new org.apache.thrift.meta_data.FieldMetaData("declinedReason", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    tmpMap.put(_Fields.REQUEST_CREATION_TIME, new org.apache.thrift.meta_data.FieldMetaData("requestCreationTime", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I64)));
+    tmpMap.put(_Fields.REQUESTER_USERNAME, new org.apache.thrift.meta_data.FieldMetaData("requesterUsername", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+    metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);
+    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(Tenant.class, metaDataMap);
+  }
+
+  public Tenant() {
+  }
+
+  public Tenant(
+    String tenantId,
+    TenantApprovalStatus tenantApprovalStatus)
+  {
+    this();
+    this.tenantId = tenantId;
+    this.tenantApprovalStatus = tenantApprovalStatus;
+  }
+
+  /**
+   * Performs a deep copy on <i>other</i>.
+   */
+  public Tenant(Tenant other) {
+    __isset_bitfield = other.__isset_bitfield;
+    if (other.isSetTenantId()) {
+      this.tenantId = other.tenantId;
+    }
+    if (other.isSetTenantApprovalStatus()) {
+      this.tenantApprovalStatus = other.tenantApprovalStatus;
+    }
+    if (other.isSetTenantName()) {
+      this.tenantName = other.tenantName;
+    }
+    if (other.isSetDomain()) {
+      this.domain = other.domain;
+    }
+    if (other.isSetEmailAddress()) {
+      this.emailAddress = other.emailAddress;
+    }
+    if (other.isSetTenantAcronym()) {
+      this.tenantAcronym = other.tenantAcronym;
+    }
+    if (other.isSetTenantURL()) {
+      this.tenantURL = other.tenantURL;
+    }
+    if (other.isSetTenantPublicAbstract()) {
+      this.tenantPublicAbstract = other.tenantPublicAbstract;
+    }
+    if (other.isSetReviewProposalDescription()) {
+      this.reviewProposalDescription = other.reviewProposalDescription;
+    }
+    if (other.isSetDeclinedReason()) {
+      this.declinedReason = other.declinedReason;
+    }
+    this.requestCreationTime = other.requestCreationTime;
+    if (other.isSetRequesterUsername()) {
+      this.requesterUsername = other.requesterUsername;
+    }
+  }
+
+  public Tenant deepCopy() {
+    return new Tenant(this);
+  }
+
+  @Override
+  public void clear() {
+    this.tenantId = null;
+    this.tenantApprovalStatus = null;
+    this.tenantName = null;
+    this.domain = null;
+    this.emailAddress = null;
+    this.tenantAcronym = null;
+    this.tenantURL = null;
+    this.tenantPublicAbstract = null;
+    this.reviewProposalDescription = null;
+    this.declinedReason = null;
+    setRequestCreationTimeIsSet(false);
+    this.requestCreationTime = 0;
+    this.requesterUsername = null;
+  }
+
+  public String getTenantId() {
+    return this.tenantId;
+  }
+
+  public void setTenantId(String tenantId) {
+    this.tenantId = tenantId;
+  }
+
+  public void unsetTenantId() {
+    this.tenantId = null;
+  }
+
+  /** Returns true if field tenantId is set (has been assigned a value) and false otherwise */
+  public boolean isSetTenantId() {
+    return this.tenantId != null;
+  }
+
+  public void setTenantIdIsSet(boolean value) {
+    if (!value) {
+      this.tenantId = null;
+    }
+  }
+
+  /**
+   *
+   * @see TenantApprovalStatus
+   */
+  public TenantApprovalStatus getTenantApprovalStatus() {
+    return this.tenantApprovalStatus;
+  }
+
+  /**
+   *
+   * @see TenantApprovalStatus
+   */
+  public void setTenantApprovalStatus(TenantApprovalStatus tenantApprovalStatus) {
+    this.tenantApprovalStatus = tenantApprovalStatus;
+  }
+
+  public void unsetTenantApprovalStatus() {
+    this.tenantApprovalStatus = null;
+  }
+
+  /** Returns true if field tenantApprovalStatus is set (has been assigned a value) and false otherwise */
+  public boolean isSetTenantApprovalStatus() {
+    return this.tenantApprovalStatus != null;
+  }
+
+  public void setTenantApprovalStatusIsSet(boolean value) {
+    if (!value) {
+      this.tenantApprovalStatus = null;
+    }
+  }
+
+  public String getTenantName() {
+    return this.tenantName;
+  }
+
+  public void setTenantName(String tenantName) {
+    this.tenantName = tenantName;
+  }
+
+  public void unsetTenantName() {
+    this.tenantName = null;
+  }
+
+  /** Returns true if field tenantName is set (has been assigned a value) and false otherwise */
+  public boolean isSetTenantName() {
+    return this.tenantName != null;
+  }
+
+  public void setTenantNameIsSet(boolean value) {
+    if (!value) {
+      this.tenantName = null;
+    }
+  }
+
+  public String getDomain() {
+    return this.domain;
+  }
+
+  public void setDomain(String domain) {
+    this.domain = domain;
+  }
+
+  public void unsetDomain() {
+    this.domain = null;
+  }
+
+  /** Returns true if field domain is set (has been assigned a value) and false otherwise */
+  public boolean isSetDomain() {
+    return this.domain != null;
+  }
+
+  public void setDomainIsSet(boolean value) {
+    if (!value) {
+      this.domain = null;
+    }
+  }
+
+  public String getEmailAddress() {
+    return this.emailAddress;
+  }
+
+  public void setEmailAddress(String emailAddress) {
+    this.emailAddress = emailAddress;
+  }
+
+  public void unsetEmailAddress() {
+    this.emailAddress = null;
+  }
+
+  /** Returns true if field emailAddress is set (has been assigned a value) and false otherwise */
+  public boolean isSetEmailAddress() {
+    return this.emailAddress != null;
+  }
+
+  public void setEmailAddressIsSet(boolean value) {
+    if (!value) {
+      this.emailAddress = null;
+    }
+  }
+
+  public String getTenantAcronym() {
+    return this.tenantAcronym;
+  }
+
+  public void setTenantAcronym(String tenantAcronym) {
+    this.tenantAcronym = tenantAcronym;
+  }
+
+  public void unsetTenantAcronym() {
+    this.tenantAcronym = null;
+  }
+
+  /** Returns true if field tenantAcronym is set (has been assigned a value) and false otherwise */
+  public boolean isSetTenantAcronym() {
+    return this.tenantAcronym != null;
+  }
+
+  public void setTenantAcronymIsSet(boolean value) {
+    if (!value) {
+      this.tenantAcronym = null;
+    }
+  }
+
+  public String getTenantURL() {
+    return this.tenantURL;
+  }
+
+  public void setTenantURL(String tenantURL) {
+    this.tenantURL = tenantURL;
+  }
+
+  public void unsetTenantURL() {
+    this.tenantURL = null;
+  }
+
+  /** Returns true if field tenantURL is set (has been assigned a value) and false otherwise */
+  public boolean isSetTenantURL() {
+    return this.tenantURL != null;
+  }
+
+  public void setTenantURLIsSet(boolean value) {
+    if (!value) {
+      this.tenantURL = null;
+    }
+  }
+
+  public String getTenantPublicAbstract() {
+    return this.tenantPublicAbstract;
+  }
+
+  public void setTenantPublicAbstract(String tenantPublicAbstract) {
+    this.tenantPublicAbstract = tenantPublicAbstract;
+  }
+
+  public void unsetTenantPublicAbstract() {
+    this.tenantPublicAbstract = null;
+  }
+
+  /** Returns true if field tenantPublicAbstract is set (has been assigned a value) and false otherwise */
+  public boolean isSetTenantPublicAbstract() {
+    return this.tenantPublicAbstract != null;
+  }
+
+  public void setTenantPublicAbstractIsSet(boolean value) {
+    if (!value) {
+      this.tenantPublicAbstract = null;
+    }
+  }
+
+  public String getReviewProposalDescription() {
+    return this.reviewProposalDescription;
+  }
+
+  public void setReviewProposalDescription(String reviewProposalDescription) {
+    this.reviewProposalDescription = reviewProposalDescription;
+  }
+
+  public void unsetReviewProposalDescription() {
+    this.reviewProposalDescription = null;
+  }
+
+  /** Returns true if field reviewProposalDescription is set (has been assigned a value) and false otherwise */
+  public boolean isSetReviewProposalDescription() {
+    return this.reviewProposalDescription != null;
+  }
+
+  public void setReviewProposalDescriptionIsSet(boolean value) {
+    if (!value) {
+      this.reviewProposalDescription = null;
+    }
+  }
+
+  public String getDeclinedReason() {
+    return this.declinedReason;
+  }
+
+  public void setDeclinedReason(String declinedReason) {
+    this.declinedReason = declinedReason;
+  }
+
+  public void unsetDeclinedReason() {
+    this.declinedReason = null;
+  }
+
+  /** Returns true if field declinedReason is set (has been assigned a value) and false otherwise */
+  public boolean isSetDeclinedReason() {
+    return this.declinedReason != null;
+  }
+
+  public void setDeclinedReasonIsSet(boolean value) {
+    if (!value) {
+      this.declinedReason = null;
+    }
+  }
+
+  public long getRequestCreationTime() {
+    return this.requestCreationTime;
+  }
+
+  public void setRequestCreationTime(long requestCreationTime) {
+    this.requestCreationTime = requestCreationTime;
+    setRequestCreationTimeIsSet(true);
+  }
+
+  public void unsetRequestCreationTime() {
+    __isset_bitfield = org.apache.thrift.EncodingUtils.clearBit(__isset_bitfield, __REQUESTCREATIONTIME_ISSET_ID);
+  }
+
+  /** Returns true if field requestCreationTime is set (has been assigned a value) and false otherwise */
+  public boolean isSetRequestCreationTime() {
+    return org.apache.thrift.EncodingUtils.testBit(__isset_bitfield, __REQUESTCREATIONTIME_ISSET_ID);
+  }
+
+  public void setRequestCreationTimeIsSet(boolean value) {
+    __isset_bitfield = org.apache.thrift.EncodingUtils.setBit(__isset_bitfield, __REQUESTCREATIONTIME_ISSET_ID, value);
+  }
+
+  public String getRequesterUsername() {
+    return this.requesterUsername;
+  }
+
+  public void setRequesterUsername(String requesterUsername) {
+    this.requesterUsername = requesterUsername;
+  }
+
+  public void unsetRequesterUsername() {
+    this.requesterUsername = null;
+  }
+
+  /** Returns true if field requesterUsername is set (has been assigned a value) and false otherwise */
+  public boolean isSetRequesterUsername() {
+    return this.requesterUsername != null;
+  }
+
+  public void setRequesterUsernameIsSet(boolean value) {
+    if (!value) {
+      this.requesterUsername = null;
+    }
+  }
+
+  public void setFieldValue(_Fields field, Object value) {
+    switch (field) {
+    case TENANT_ID:
+      if (value == null) {
+        unsetTenantId();
+      } else {
+        setTenantId((String)value);
+      }
+      break;
+
+    case TENANT_APPROVAL_STATUS:
+      if (value == null) {
+        unsetTenantApprovalStatus();
+      } else {
+        setTenantApprovalStatus((TenantApprovalStatus)value);
+      }
+      break;
+
+    case TENANT_NAME:
+      if (value == null) {
+        unsetTenantName();
+      } else {
+        setTenantName((String)value);
+      }
+      break;
+
+    case DOMAIN:
+      if (value == null) {
+        unsetDomain();
+      } else {
+        setDomain((String)value);
+      }
+      break;
+
+    case EMAIL_ADDRESS:
+      if (value == null) {
+        unsetEmailAddress();
+      } else {
+        setEmailAddress((String)value);
+      }
+      break;
+
+    case TENANT_ACRONYM:
+      if (value == null) {
+        unsetTenantAcronym();
+      } else {
+        setTenantAcronym((String)value);
+      }
+      break;
+
+    case TENANT_URL:
+      if (value == null) {
+        unsetTenantURL();
+      } else {
+        setTenantURL((String)value);
+      }
+      break;
+
+    case TENANT_PUBLIC_ABSTRACT:
+      if (value == null) {
+        unsetTenantPublicAbstract();
+      } else {
+        setTenantPublicAbstract((String)value);
+      }
+      break;
+
+    case REVIEW_PROPOSAL_DESCRIPTION:
+      if (value == null) {
+        unsetReviewProposalDescription();
+      } else {
+        setReviewProposalDescription((String)value);
+      }
+      break;
+
+    case DECLINED_REASON:
+      if (value == null) {
+        unsetDeclinedReason();
+      } else {
+        setDeclinedReason((String)value);
+      }
+      break;
+
+    case REQUEST_CREATION_TIME:
+      if (value == null) {
+        unsetRequestCreationTime();
+      } else {
+        setRequestCreationTime((Long)value);
+      }
+      break;
+
+    case REQUESTER_USERNAME:
+      if (value == null) {
+        unsetRequesterUsername();
+      } else {
+        setRequesterUsername((String)value);
+      }
+      break;
+
+    }
+  }
+
+  public Object getFieldValue(_Fields field) {
+    switch (field) {
+    case TENANT_ID:
+      return getTenantId();
+
+    case TENANT_APPROVAL_STATUS:
+      return getTenantApprovalStatus();
+
+    case TENANT_NAME:
+      return getTenantName();
+
+    case DOMAIN:
+      return getDomain();
+
+    case EMAIL_ADDRESS:
+      return getEmailAddress();
+
+    case TENANT_ACRONYM:
+      return getTenantAcronym();
+
+    case TENANT_URL:
+      return getTenantURL();
+
+    case TENANT_PUBLIC_ABSTRACT:
+      return getTenantPublicAbstract();
+
+    case REVIEW_PROPOSAL_DESCRIPTION:
+      return getReviewProposalDescription();
+
+    case DECLINED_REASON:
+      return getDeclinedReason();
+
+    case REQUEST_CREATION_TIME:
+      return getRequestCreationTime();
+
+    case REQUESTER_USERNAME:
+      return getRequesterUsername();
+
+    }
+    throw new IllegalStateException();
+  }
+
+  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+  public boolean isSet(_Fields field) {
+    if (field == null) {
+      throw new IllegalArgumentException();
+    }
+
+    switch (field) {
+    case TENANT_ID:
+      return isSetTenantId();
+    case TENANT_APPROVAL_STATUS:
+      return isSetTenantApprovalStatus();
+    case TENANT_NAME:
+      return isSetTenantName();
+    case DOMAIN:
+      return isSetDomain();
+    case EMAIL_ADDRESS:
+      return isSetEmailAddress();
+    case TENANT_ACRONYM:
+      return isSetTenantAcronym();
+    case TENANT_URL:
+      return isSetTenantURL();
+    case TENANT_PUBLIC_ABSTRACT:
+      return isSetTenantPublicAbstract();
+    case REVIEW_PROPOSAL_DESCRIPTION:
+      return isSetReviewProposalDescription();
+    case DECLINED_REASON:
+      return isSetDeclinedReason();
+    case REQUEST_CREATION_TIME:
+      return isSetRequestCreationTime();
+    case REQUESTER_USERNAME:
+      return isSetRequesterUsername();
+    }
+    throw new IllegalStateException();
+  }
+
+  @Override
+  public boolean equals(Object that) {
+    if (that == null)
+      return false;
+    if (that instanceof Tenant)
+      return this.equals((Tenant)that);
+    return false;
+  }
+
+  public boolean equals(Tenant that) {
+    if (that == null)
+      return false;
+    if (this == that)
+      return true;
+
+    boolean this_present_tenantId = true && this.isSetTenantId();
+    boolean that_present_tenantId = true && that.isSetTenantId();
+    if (this_present_tenantId || that_present_tenantId) {
+      if (!(this_present_tenantId && that_present_tenantId))
+        return false;
+      if (!this.tenantId.equals(that.tenantId))
+        return false;
+    }
+
+    boolean this_present_tenantApprovalStatus = true && this.isSetTenantApprovalStatus();
+    boolean that_present_tenantApprovalStatus = true && that.isSetTenantApprovalStatus();
+    if (this_present_tenantApprovalStatus || that_present_tenantApprovalStatus) {
+      if (!(this_present_tenantApprovalStatus && that_present_tenantApprovalStatus))
+        return false;
+      if (!this.tenantApprovalStatus.equals(that.tenantApprovalStatus))
+        return false;
+    }
+
+    boolean this_present_tenantName = true && this.isSetTenantName();
+    boolean that_present_tenantName = true && that.isSetTenantName();
+    if (this_present_tenantName || that_present_tenantName) {
+      if (!(this_present_tenantName && that_present_tenantName))
+        return false;
+      if (!this.tenantName.equals(that.tenantName))
+        return false;
+    }
+
+    boolean this_present_domain = true && this.isSetDomain();
+    boolean that_present_domain = true && that.isSetDomain();
+    if (this_present_domain || that_present_domain) {
+      if (!(this_present_domain && that_present_domain))
+        return false;
+      if (!this.domain.equals(that.domain))
+        return false;
+    }
+
+    boolean this_present_emailAddress = true && this.isSetEmailAddress();
+    boolean that_present_emailAddress = true && that.isSetEmailAddress();
+    if (this_present_emailAddress || that_present_emailAddress) {
+      if (!(this_present_emailAddress && that_present_emailAddress))
+        return false;
+      if (!this.emailAddress.equals(that.emailAddress))
+        return false;
+    }
+
+    boolean this_present_tenantAcronym = true && this.isSetTenantAcronym();
+    boolean that_present_tenantAcronym = true && that.isSetTenantAcronym();
+    if (this_present_tenantAcronym || that_present_tenantAcronym) {
+      if (!(this_present_tenantAcronym && that_present_tenantAcronym))
+        return false;
+      if (!this.tenantAcronym.equals(that.tenantAcronym))
+        return false;
+    }
+
+    boolean this_present_tenantURL = true && this.isSetTenantURL();
+    boolean that_present_tenantURL = true && that.isSetTenantURL();
+    if (this_present_tenantURL || that_present_tenantURL) {
+      if (!(this_present_tenantURL && that_present_tenantURL))
+        return false;
+      if (!this.tenantURL.equals(that.tenantURL))
+        return false;
+    }
+
+    boolean this_present_tenantPublicAbstract = true && this.isSetTenantPublicAbstract();
+    boolean that_present_tenantPublicAbstract = true && that.isSetTenantPublicAbstract();
+    if (this_present_tenantPublicAbstract || that_present_tenantPublicAbstract) {
+      if (!(this_present_tenantPublicAbstract && that_present_tenantPublicAbstract))
+        return false;
+      if (!this.tenantPublicAbstract.equals(that.tenantPublicAbstract))
+        return false;
+    }
+
+    boolean this_present_reviewProposalDescription = true && this.isSetReviewProposalDescription();
+    boolean that_present_reviewProposalDescription = true && that.isSetReviewProposalDescription();
+    if (this_present_reviewProposalDescription || that_present_reviewProposalDescription) {
+      if (!(this_present_reviewProposalDescription && that_present_reviewProposalDescription))
+        return false;
+      if (!this.reviewProposalDescription.equals(that.reviewProposalDescription))
+        return false;
+    }
+
+    boolean this_present_declinedReason = true && this.isSetDeclinedReason();
+    boolean that_present_declinedReason = true && that.isSetDeclinedReason();
+    if (this_present_declinedReason || that_present_declinedReason) {
+      if (!(this_present_declinedReason && that_present_declinedReason))
+        return false;
+      if (!this.declinedReason.equals(that.declinedReason))
+        return false;
+    }
+
+    boolean this_present_requestCreationTime = true && this.isSetRequestCreationTime();
+    boolean that_present_requestCreationTime = true && that.isSetRequestCreationTime();
+    if (this_present_requestCreationTime || that_present_requestCreationTime) {
+      if (!(this_present_requestCreationTime && that_present_requestCreationTime))
+        return false;
+      if (this.requestCreationTime != that.requestCreationTime)
+        return false;
+    }
+
+    boolean this_present_requesterUsername = true && this.isSetRequesterUsername();
+    boolean that_present_requesterUsername = true && that.isSetRequesterUsername();
+    if (this_present_requesterUsername || that_present_requesterUsername) {
+      if (!(this_present_requesterUsername && that_present_requesterUsername))
+        return false;
+      if (!this.requesterUsername.equals(that.requesterUsername))
+        return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int hashCode = 1;
+
+    hashCode = hashCode * 8191 + ((isSetTenantId()) ? 131071 : 524287);
+    if (isSetTenantId())
+      hashCode = hashCode * 8191 + tenantId.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetTenantApprovalStatus()) ? 131071 : 524287);
+    if (isSetTenantApprovalStatus())
+      hashCode = hashCode * 8191 + tenantApprovalStatus.getValue();
+
+    hashCode = hashCode * 8191 + ((isSetTenantName()) ? 131071 : 524287);
+    if (isSetTenantName())
+      hashCode = hashCode * 8191 + tenantName.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetDomain()) ? 131071 : 524287);
+    if (isSetDomain())
+      hashCode = hashCode * 8191 + domain.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetEmailAddress()) ? 131071 : 524287);
+    if (isSetEmailAddress())
+      hashCode = hashCode * 8191 + emailAddress.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetTenantAcronym()) ? 131071 : 524287);
+    if (isSetTenantAcronym())
+      hashCode = hashCode * 8191 + tenantAcronym.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetTenantURL()) ? 131071 : 524287);
+    if (isSetTenantURL())
+      hashCode = hashCode * 8191 + tenantURL.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetTenantPublicAbstract()) ? 131071 : 524287);
+    if (isSetTenantPublicAbstract())
+      hashCode = hashCode * 8191 + tenantPublicAbstract.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetReviewProposalDescription()) ? 131071 : 524287);
+    if (isSetReviewProposalDescription())
+      hashCode = hashCode * 8191 + reviewProposalDescription.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetDeclinedReason()) ? 131071 : 524287);
+    if (isSetDeclinedReason())
+      hashCode = hashCode * 8191 + declinedReason.hashCode();
+
+    hashCode = hashCode * 8191 + ((isSetRequestCreationTime()) ? 131071 : 524287);
+    if (isSetRequestCreationTime())
+      hashCode = hashCode * 8191 + org.apache.thrift.TBaseHelper.hashCode(requestCreationTime);
+
+    hashCode = hashCode * 8191 + ((isSetRequesterUsername()) ? 131071 : 524287);
+    if (isSetRequesterUsername())
+      hashCode = hashCode * 8191 + requesterUsername.hashCode();
+
+    return hashCode;
+  }
+
+  @Override
+  public int compareTo(Tenant other) {
+    if (!getClass().equals(other.getClass())) {
+      return getClass().getName().compareTo(other.getClass().getName());
+    }
+
+    int lastComparison = 0;
+
+    lastComparison = Boolean.valueOf(isSetTenantId()).compareTo(other.isSetTenantId());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetTenantId()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.tenantId, other.tenantId);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetTenantApprovalStatus()).compareTo(other.isSetTenantApprovalStatus());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetTenantApprovalStatus()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.tenantApprovalStatus, other.tenantApprovalStatus);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetTenantName()).compareTo(other.isSetTenantName());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetTenantName()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.tenantName, other.tenantName);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetDomain()).compareTo(other.isSetDomain());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetDomain()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.domain, other.domain);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetEmailAddress()).compareTo(other.isSetEmailAddress());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetEmailAddress()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.emailAddress, other.emailAddress);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetTenantAcronym()).compareTo(other.isSetTenantAcronym());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetTenantAcronym()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.tenantAcronym, other.tenantAcronym);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetTenantURL()).compareTo(other.isSetTenantURL());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetTenantURL()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.tenantURL, other.tenantURL);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetTenantPublicAbstract()).compareTo(other.isSetTenantPublicAbstract());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetTenantPublicAbstract()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.tenantPublicAbstract, other.tenantPublicAbstract);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetReviewProposalDescription()).compareTo(other.isSetReviewProposalDescription());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetReviewProposalDescription()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.reviewProposalDescription, other.reviewProposalDescription);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetDeclinedReason()).compareTo(other.isSetDeclinedReason());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetDeclinedReason()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.declinedReason, other.declinedReason);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetRequestCreationTime()).compareTo(other.isSetRequestCreationTime());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetRequestCreationTime()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.requestCreationTime, other.requestCreationTime);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    lastComparison = Boolean.valueOf(isSetRequesterUsername()).compareTo(other.isSetRequesterUsername());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetRequesterUsername()) {
+      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.requesterUsername, other.requesterUsername);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
+    return 0;
+  }
+
+  public _Fields fieldForId(int fieldId) {
+    return _Fields.findByThriftId(fieldId);
+  }
+
+  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+    scheme(iprot).read(iprot, this);
+  }
+
+  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+    scheme(oprot).write(oprot, this);
+  }
+
... 73877 lines suppressed ...