###
# Licensed Materials - Property of IBM* and/or HCL**
# (c) Copyright IBM Corporation 2014, 2015, 2017. All Rights Reserved.
# (c) Copyright HCL Technologies Ltd. 2018. All Rights Reserved.
#
# U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
# GSA ADP Schedule Contract with IBM Corp.
#
# * Trademark of International Business Machines
# ** Trademark of HCL Technologies Limited

from org.codehaus.jettison.json import JSONObject, JSONArray
import sys;
from utilities import Util
from Property import Property
from WASConfLog import Log
from KeyStore import KeyStore
from KeyManager import KeyManager
from TrustManager import TrustManager
from SSLConfig import SSLConfig
from SSLConfigGroup import SSLConfigGroup
from KeySet import KeySet
from SSLConfigRef import SSLConfigRef
from KeySetGroup import KeySetGroup
from JAASConfiguration import JAASConfiguration
from AuthMechanism import AuthMechanism
from JAASAuthData import JAASAuthData
from Certificate import Certificate
from CACertificate import CACertificate
from LDAPUserRegistry import LDAPUserRegistry
from LocalOSUserRegistry import LocalOSUserRegistry
from CustomUserRegistry import CustomUserRegistry
from WIMUserRegistry import WIMUserRegistry
from UserRegistryRef import UserRegistryRef
from TrustedAuthenticationRealm import TrustedAuthenticationRealm
from WSNotification import WSNotification
from WSSchedule import WSSchedule
from WSCertificateExpirationMonitor import WSCertificateExpirationMonitor
from WSSecurityScannerMonitor import WSSecurityScannerMonitor
from DynamicSSLConfigSelection import DynamicSSLConfigSelection

__name_att__ = None;

def _export(parentid, parentrespath, name = ""):
  objid = Util.getid("/Cell:/Security:/");
  scopeName = Util.getSecurityScopename(parentid);
  Log.debug("Found security scopename %(scname)s for objid %(objid)s" % { 'scname': scopeName, 'objid': parentid });
  Util.pushPathElement('Security')


  if parentrespath == "/":
    parentrespath = "";
  respath = "%(parentrespath)s/%(name)s" % { 'parentrespath':parentrespath, 'name':name }
  if not respath.startswith("/"):
    respath = "/" + respath;

  exportedObject = JSONObject();
  exportedObject.put("name", name);
  exportedObject.put("path", respath);
  exportedObject.put("teamMappings", JSONArray());
  exportedObject.put("inheritTeam", "true");
  exportedObject.put("description", "Discovered WebSphereSecurity");
  exportedObject.put("roleName", "WebSphereSecurity");

  roleProperties = JSONObject();

  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.security.allowbasicauth", objid, "allowBasicAuth","Security");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.security.uselocalsecurityserver", objid, "useLocalSecurityServer","Security");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.security.usedomainqualifiedusernames", objid, "useDomainQualifiedUserNames","Security");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.security.enabled", objid, "enabled","Security");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.security.cachetimeout", objid, "cacheTimeout","Security");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.security.enforcefinegrainedjcasecurity", objid, "enforceFineGrainedJCASecurity","Security");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.security.enablejava2secruntimefiltering", objid, "enableJava2SecRuntimeFiltering","Security");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.security.enforcejava2security", objid, "enforceJava2Security","Security");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.security.allowallpermissionforapplication", objid, "allowAllPermissionForApplication","Security");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.security.appenabled", objid, "appEnabled","Security");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.security.dynamicallyupdatesslconfig", objid, "dynamicallyUpdateSSLConfig","Security");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.security.activeprotocol", objid, "activeProtocol","Security");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.security.internalserverid", objid, "internalServerId","Security");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.security.issuepermissionwarning", objid, "issuePermissionWarning","Security");
  roleProperties.put("websphere.security.scopename", scopeName);
  exportedObject.put("roleProperties", roleProperties);
  result = { 'object': exportedObject, 'respath':respath }
  extraObjects = [];
  typeFolders = {};

  #only export properties and AuthMechanisms to the cell scope
  if isCellScope(scopeName):
    extraObjects = Property.exportProperties(objid, respath, extraObjects, typeFolders, 'properties',"Security","PropertyAttrs");
    extraObjects = Property.exportProperties(objid, respath, extraObjects, typeFolders, 'additionalSecAttrs',"Security","AdditionalSecAttrs");
    extraObjects = Property.exportProperties(objid, respath, extraObjects, typeFolders, 'webAuthAttrs',"Security","WebAuthAttrs");
    extraObjects = AuthMechanism.exportAuthMechanisms(objid, respath, extraObjects, typeFolders, 'authMechanisms', "Security", "AuthMechanism");

  applicationLoginConfig = Util.getOptionalAttribute(objid, 'applicationLoginConfig', 'Security');
  applicationLoginConfig = filterForScope(applicationLoginConfig, scopeName, 'JAASConfiguration', None);
  if applicationLoginConfig is not None and len(applicationLoginConfig) > 0:
    returndict = Util.createTypeFolder(respath, "ApplicationLoginConfig", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
      Util.addFromExport(extraObjects, returndict['object']);
    Util.addAllFromExport(extraObjects, JAASConfiguration._export(applicationLoginConfig, currespath, "JAASConfiguration"));

  systemLoginConfig = Util.getOptionalAttribute(objid, 'systemLoginConfig', 'Security');
  systemLoginConfig = filterForScope(systemLoginConfig, scopeName, 'JAASConfiguration', None);
  if systemLoginConfig is not None and len(systemLoginConfig) > 0:
    returndict = Util.createTypeFolder(respath, "SystemLoginConfig", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
      Util.addFromExport(extraObjects, returndict['object']);
    Util.addAllFromExport(extraObjects, JAASConfiguration._export(systemLoginConfig, currespath, "JAASConfiguration"));

  i = 0;
  keyStores = Util.parseConfigIdListAttribute(objid, 'keyStores', "Security");
  keyStores = filterForScope(keyStores, scopeName, 'KeyStore');
  for keyStore in keyStores:
    if len(keyStore) > 0:
      returndict = Util.createTypeFolder(respath, "KeyStore", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, KeyStore._export(keyStore, currespath, "KeyStore%s" % i));
      i = i + 1;

  i = 0;
  keyManagers = Util.parseConfigIdListAttribute(objid, 'keyManagers', "Security");
  keyManagers = filterForScope(keyManagers, scopeName, 'KeyManager');
  for keyManager in keyManagers:
    if len(keyManager) > 0:
      returndict = Util.createTypeFolder(respath, "KeyManager", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, KeyManager._export(keyManager, currespath, "KeyManager%s" % i));
      i = i + 1;

  i = 0;
  trustManagers = Util.parseConfigIdListAttribute(objid, 'trustManagers', "Security");
  trustManagers = filterForScope(trustManagers, scopeName, 'TrustManager');
  for trustManager in trustManagers:
    if len(trustManager) > 0:
      returndict = Util.createTypeFolder(respath, "TrustManager", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, TrustManager._export(trustManager, currespath, "TrustManager%s" % i));
      i = i + 1;

  i = 0;
  repertoires = Util.parseConfigIdListAttribute(objid, 'repertoire', "Security");
  repertoires = filterForScope(repertoires, scopeName, 'SSLConfig');
  for repertoire in repertoires:
    if len(repertoire) > 0:
      returndict = Util.createTypeFolder(respath, "SSLConfig", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, SSLConfig._export(repertoire, currespath, "SSLConfig%s" % i));
      i = i + 1;

  i = 0;
  sslConfigGroups = Util.parseConfigIdListAttribute(objid, 'sslConfigGroups', "Security");
  sslConfigGroups = filterForScope(sslConfigGroups, scopeName, 'SSLConfigGroup');
  for sslConfigGroup in sslConfigGroups:
    if len(sslConfigGroup) > 0:
      returndict = Util.createTypeFolder(respath, "SSLConfigGroup", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, SSLConfigGroup._export(sslConfigGroup, currespath, "SSLConfigGroup%s" % i));
      i = i + 1;

  i = 0;
  keySets = Util.parseConfigIdListAttribute(objid, 'keySets', "Security");
  keySets = filterForScope(keySets, scopeName, 'KeySet');
  for keySet in keySets:
    if len(keySet) > 0:
      returndict = Util.createTypeFolder(respath, "KeySet", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, KeySet._export(keySet, currespath, "KeySet%s" % i));
      i = i + 1;

  defaultSSLSettings = Util.getOptionalAttribute(objid, 'defaultSSLSettings', 'Security');
  defaultSSLSettings = filterForScope(defaultSSLSettings, scopeName, 'SSLConfig', None);#sure enough this is only at the cell level i don't care to try to handle another way
  if defaultSSLSettings is not None and len(defaultSSLSettings) > 0:
    returndict = Util.createTypeFolder(respath, "SSLConfigRef", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
      Util.addFromExport(extraObjects, returndict['object']);
    Util.addAllFromExport(extraObjects, SSLConfigRef._export(defaultSSLSettings, currespath, "DefaultSSLSettings"));

  wsCertificateExpirationMonitor = Util.getOptionalAttribute(objid, 'wsCertificateExpirationMonitor', 'Security');
  wsCertificateExpirationMonitor = filterForScope(wsCertificateExpirationMonitor, scopeName, 'WSCertificateExpirationMonitor', None);#sure enough this is only at the cell level i don't care to try to handle another way
  if wsCertificateExpirationMonitor is not None and len(wsCertificateExpirationMonitor) > 0:
    returndict = Util.createTypeFolder(respath, "WSCertificateExpirationMonitor", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
      Util.addFromExport(extraObjects, returndict['object']);
    Util.addAllFromExport(extraObjects, WSCertificateExpirationMonitor._export(wsCertificateExpirationMonitor, currespath, "WSCertificateExpirationMonitor"));

  wsSecurityScannerMonitor = Util.getOptionalAttribute(objid, 'wsSecurityScannerMonitor', 'Security');
  wsSecurityScannerMonitor = filterForScope(wsSecurityScannerMonitor, scopeName, 'WSSecurityScannerMonitor', None);
  if wsSecurityScannerMonitor is not None and len(wsSecurityScannerMonitor) > 0:
    returndict = Util.createTypeFolder(respath, "WSSecurityScannerMonitor", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
      Util.addFromExport(extraObjects, returndict['object']);
    Util.addAllFromExport(extraObjects, WSSecurityScannerMonitor._export(wsSecurityScannerMonitor, currespath, "WSSecurityScannerMonitor"));

  i = 0;
  keySetGroups = Util.parseConfigIdListAttribute(objid, 'keySetGroups', "Security");
  keySetGroups = filterForScope(keySetGroups, scopeName, 'KeySetGroup');
  for keySetGroup in keySetGroups:
    if len(keySetGroup) > 0:
      returndict = Util.createTypeFolder(respath, "KeySetGroup", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, KeySetGroup._export(keySetGroup, currespath, "KeySetGroup%s" % i));
      i = i + 1;

  i = 0;
  cai = 0;
  certificates = Util.parseConfigIdListAttribute(objid, 'certificates',"Security");
  certificates = filterForScope(certificates, scopeName, 'Certificate', None); #this probably really needs to look at its keystore ref to determine its management scope
  #TODO - don't always leave at the cell scope
  for certificate in certificates:
    if len(certificate) > 0:
      returndict = Util.createTypeFolder(respath, "Certificate", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      if certificate.find("#Certificate_") != -1:
        Util.addAllFromExport(extraObjects, Certificate._export(certificate, currespath, "Certificate%s" % i));
        i = i + 1;
      elif certificate.find("#CACertificate_") != -1:
        Util.addAllFromExport(extraObjects, CACertificate._export(certificate, currespath, "CACertificate%s" % i));
        cai = cai + 1;

  i = 0;
  jaasAuthDatas = Util.parseConfigIdListAttribute(objid, 'authDataEntries', "Security");
  jaasAuthDatas = filterForScope(jaasAuthDatas, scopeName, 'JAASAuthData', None);#cell only config... which really kinda sucks
  for jaasAuthData in jaasAuthDatas:
    if len(jaasAuthData) > 0:
      returndict = Util.createTypeFolder(respath, "JAASAuthData", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, JAASAuthData._export(jaasAuthData, currespath, Util.getRequiredAttribute(jaasAuthData, 'alias', 'JAASAuthData').replace("/","-")));
      i = i + 1;

  i = 0;
  wsNotifications = Util.parseConfigIdListAttribute(objid, 'wsNotifications', "Security");
  wsNotifications = filterForScope(wsNotifications, scopeName, 'WSNotification', None);#cell only config... which really kinda sucks
  for wsNotification in wsNotifications:
    if len(wsNotification) > 0:
      returndict = Util.createTypeFolder(respath, "WSNotification", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, WSNotification._export(wsNotification, currespath, "wsNotification%s" % i));
      i = i + 1;

  i = 0;
  wsSchedules = Util.parseConfigIdListAttribute(objid, 'wsSchedules', "Security");
  wsSchedules = filterForScope(wsSchedules, scopeName, 'WSSchedule', None);#cell only config... which really kinda sucks
  for wsSchedule in wsSchedules:
    if len(wsSchedule) > 0:
      returndict = Util.createTypeFolder(respath, "WSSchedule", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, WSSchedule._export(wsSchedule, currespath, "wsSchedule%s" % i));
      i = i + 1;

  i = 0;
  ldapUserRegistries = LDAPUserRegistry.getLDAPUserRegistry(objid);
  ldapUserRegistries = filterForScope(ldapUserRegistries, scopeName, 'LDAPUserRegistry', None); #cell level
  for ldapUserRegistry in ldapUserRegistries:
    if len(ldapUserRegistry) > 0:
      returndict = Util.createTypeFolder(respath, "LDAPUserRegistry", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, LDAPUserRegistry._export(ldapUserRegistry, currespath, "LDAP User Registry%s" % i));
      i = i + 1;

  i = 0;
  localOSUserRegistries = LocalOSUserRegistry.getLocalOSUserRegistry(objid);
  localOSUserRegistries = filterForScope(localOSUserRegistries, scopeName, 'LocalOSUserRegistry', None);
  for localOSUserRegistry in localOSUserRegistries:
    if len(localOSUserRegistry) > 0:
      returndict = Util.createTypeFolder(respath, "LocalOSUserRegistry", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, LocalOSUserRegistry._export(localOSUserRegistry, currespath, "Local OS User Registry%s" % i));
      i = i + 1;

  i = 0;
  customUserRegistries = CustomUserRegistry.getCustomUserRegistry(objid);
  customUserRegistries = filterForScope(customUserRegistries, scopeName, 'CustomUserRegistry', None);
  for customUserRegistry in customUserRegistries:
    if customUserRegistry is not None and len(customUserRegistry) > 0:
      returndict = Util.createTypeFolder(respath, "CustomUserRegistry", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, CustomUserRegistry._export(customUserRegistry, currespath, "Custom User Registry%s" % i));
      i = i + 1;

  i = 0;
  wimUserRegistries = WIMUserRegistry.getWIMUserRegistry(objid);
  wimUserRegistries = filterForScope(wimUserRegistries, scopeName, 'WIMUserRegistry', None);
  for wimUserRegistry in wimUserRegistries:
    if wimUserRegistry is not None and len(wimUserRegistry) > 0:
      returndict = Util.createTypeFolder(respath, "WIMUserRegistry", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, WIMUserRegistry._export(wimUserRegistry, currespath, "WIM User Registry%s" % i));
      i = i + 1;

  activeUserRegistry = Util.getOptionalAttribute(objid, 'activeUserRegistry', 'Security');
  activeUserRegistry = filterForScope(activeUserRegistry, scopeName, 'UserRegistry', None);#this is relying on the earlier return for the case that attName is none to identify as cell scoped.
  if activeUserRegistry is not None and len(activeUserRegistry) > 0:
    returndict = Util.createTypeFolder(respath, "UserRegistryRef", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
      Util.addFromExport(extraObjects, returndict['object']);
    type = "";
    if activeUserRegistry.find("#LDAPUserRegistry_") != -1:
      type = "LDAPUserRegistry";
    elif activeUserRegistry.find("#LocalOSUserRegistry") != -1:
      type = "LocalOSUserRegistry";
    elif activeUserRegistry.find("#CustomUserRegistry_") != -1:
      type = "CustomUserRegistry";
    elif activeUserRegistry.find("#WIMUserRegistry_") != -1:
      type = "WIMUserRegistry";
    #realm = "";
    realm = Util.getOptionalAttribute(activeUserRegistry, 'realm', "UserRegistry");
    registryName = type;
    if realm is not None and len(realm) > 0:
      registryName = registryName + " - " + realm;

    Util.addAllFromExport(extraObjects, UserRegistryRef._export(activeUserRegistry, currespath, type, realm, registryName));

  inbound = Util.getOptionalAttribute(objid, 'inboundTrustedAuthenticationRealm',"Security");
  inbound = filterForScope(inbound, scopeName, 'TrustedAuthenticationRealm', None);
  if inbound is not None and len(inbound) > 0:
    returndict = Util.createTypeFolder(respath, "TrustedAuthenticationRealm", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
      Util.addFromExport(extraObjects, returndict['object']);
    Util.addAllFromExport(extraObjects, TrustedAuthenticationRealm._export(inbound, currespath, "inboundTrustedAuthenticationRealm"));

  outbound = Util.getOptionalAttribute(objid, 'outboundTrustedAuthenticationRealm',"Security");
  outbound = filterForScope(outbound, scopeName, 'TrustedAuthenticationRealm', None);
  if outbound is not None and len(outbound) > 0:
    returndict = Util.createTypeFolder(respath, "TrustedAuthenticationRealm", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
      Util.addFromExport(extraObjects, returndict['object']);
    Util.addAllFromExport(extraObjects, TrustedAuthenticationRealm._export(outbound, currespath, "outboundTrustedAuthenticationRealm"));

  dynamicSSLConfigSelections = Util.parseConfigIdListAttribute(objid, 'dynamicSSLConfigSelections', "Security");
  dynamicSSLConfigSelections = filterForScope(dynamicSSLConfigSelections, scopeName, 'DynamicSSLConfigSelection', None);
  for dynamicSSLConfigSelection in dynamicSSLConfigSelections:
    if len(dynamicSSLConfigSelection) > 0:
      returndict = Util.createTypeFolder(respath, "DynamicSSLConfigSelection", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      dynamicSSLConfigSelectionName = Util.getRequiredAttribute(dynamicSSLConfigSelection, "name", "DynamicSSLConfigSelection");
      Util.addAllFromExport(extraObjects, DynamicSSLConfigSelection._export(dynamicSSLConfigSelection, currespath, dynamicSSLConfigSelectionName));

  if len(extraObjects) != 0:
    result['extraObjects'] = extraObjects;
  Util.popPathElement('Security');
  return result;

def update(parentid, jsonobject):
  objid = Util.getid("/Cell:/Security:/");
  scopeName = Util.getSecurityScopename(parentid);
  Log.debug("Found security scopename %(scname)s for objid %(objid)s" % { 'scname': scopeName, 'objid': parentid });
  Util.pushPathElement('Security')
  if not jsonobject.has("roleProperties"):
    raise Exception("Security resource has no role properties!");

  roleProperties = jsonobject.getJSONObject("roleProperties");

  atts = [];
  tempScopeName = roleProperties.optString("websphere.security.scopename", None);
  if tempScopeName is None:
    scopeName = None;
  elif tempScopeName != scopeName:
    raise Exception("Scope names do not match for Security Object. Expected: '%(exp)s' Actual: '%(act)s'." % { 'act': tempScopeName, 'exp': scopeName});

  Log.debug("Final security scopename %(scname)s for objid %(objid)s" % { 'scname': scopeName, 'objid': parentid });

  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.security.allowbasicauth", None), "allowBasicAuth","Security");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.security.uselocalsecurityserver", None), "useLocalSecurityServer","Security");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.security.usedomainqualifiedusernames", None), "useDomainQualifiedUserNames","Security");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.security.enabled", None), "enabled","Security");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.security.cachetimeout", None), "cacheTimeout","Security");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.security.enforcefinegrainedjcasecurity", None), "enforceFineGrainedJCASecurity","Security");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.security.enablejava2secruntimefiltering", None), "enableJava2SecRuntimeFiltering","Security");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.security.enforcejava2security", None), "enforceJava2Security","Security");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.security.allowallpermissionforapplication", None), "allowAllPermissionForApplication","Security");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.security.appenabled", None), "appEnabled","Security");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.security.dynamicallyupdatesslconfig", None), "dynamicallyUpdateSSLConfig","Security");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.security.activeprotocol", None), "activeProtocol","Security");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.security.internalserverid", None), "internalServerId","Security");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.security.issuepermissionwarning", None), "issuePermissionWarning","Security");
  if (isCellScope(scopeName)):
    if len(atts) != 0:
      print "Modifying Security with attributes:"
      for prop in atts:
        print "%(name)s = %(value)s" % { 'name': prop[0], 'value': prop[1] };

      Util.modify(objid, atts);
    else:
      print "Security configuration up to date.";
  else:
    print "Not updating main security object from non cell scope";

  # we can't remove properties if we are using scoped security management
  if scopeName is None:
    Property.removeProperties(objid, 'properties',"Security");
    Property.removeProperties(objid, 'additionalSecAttrs',"Security");
    Property.removeProperties(objid, 'webAuthAttrs',"Security");
    # AuthMechanism.removeAuthMechanisms(objid, 'authMechanisms',"Security");
    #TODO AuthMechanism - WHAT DAMMIT WHAT!!!! I dont think there is any thing here todo
    # i am of the opinion that we don't need to remove any of the old stuff(lets see what happens eh?)

  # Cannot delete KeyStores.  We can only update them because we are corrupting the password
  # field when we try to create them.
  # keyStores = Util.parseConfigIdListAttribute(objid, 'keyStores', "Security");
  # for keyStore in keyStores:
  #   Util.remove(keyStore);

  keyManagers = Util.parseConfigIdListAttribute(objid, 'keyManagers', "Security");
  keyManagers = filterForScope(keyManagers, scopeName, 'KeyManager');
  for keyManager in keyManagers:
    Util.remove(keyManager);

  trustManagers = Util.parseConfigIdListAttribute(objid, 'trustManagers', "Security");
  trustManagers = filterForScope(trustManagers, scopeName, 'TrustManager');
  for trustManager in trustManagers:
    Util.remove(trustManager);

  # Can't delete all SSLConfigs because server-level SSLConfigs depend on them for reference
  # However, let's get a list of existing SSLConfigs to later determine if any need to be removed
  # (if they don't exist in our config data)
  sslConfigsBeforeApply = [];
  repertoires = Util.parseConfigIdListAttribute(objid, 'repertoire', "Security");
  repertoires = filterForScope(repertoires, scopeName, 'SSLConfig');
  for repertoire in repertoires:
    # SSLConfig object identifier is in format [alias, scopeName]
    identifier = SSLConfig.getSSLConfigIdentifier(repertoire);
    sslConfigsBeforeApply.append(identifier)

  sslConfigGroups = Util.parseConfigIdListAttribute(objid, 'sslConfigGroups', "Security");
  sslConfigGroups = filterForScope(sslConfigGroups, scopeName, 'SSLConfigGroup');
  for sslConfigGroup in sslConfigGroups:
    Util.remove(sslConfigGroup);

  wsNotifications = Util.parseConfigIdListAttribute(objid, 'wsNotifications', "Security");
  wsNotifications = filterForScope(wsNotifications, scopeName, 'WSNotification', None);
  for wsNotification in wsNotifications:
    Util.remove(wsNotification);

  wsSchedules = Util.parseConfigIdListAttribute(objid, 'wsSchedules', "Security");
  wsSchedules = filterForScope(wsSchedules, scopeName, 'WSSchedule', None);
  for wsSchedule in wsSchedules:
    Util.remove(wsSchedule);

  # Cannot delete KeySets.  We can only update them because we are corrupting the password
  # field when we try to create them.
  #keySets = Util.parseConfigIdListAttribute(objid, 'keySets', "Security");
  #for keySet in keySets:
  #  Util.remove(keySet);

  # Cannot delete KeySetGroups. We can only update them because of potential broken references (see WI 145398)
  #keySetGroups = Util.parseConfigIdListAttribute(objid, 'keySetGroups', "Security");
  #keySetGroups = filterForScope(keySetGroups, scopeName, 'KeySetGroup');
  #for keySetGroup in keySetGroups:
  #  Util.remove(keySetGroup);

  if isCellScope(scopeName):
    Util.unsetAttribute(objid, "defaultSSLSettings", "Security");
    Util.unsetAttribute(objid, "wsCertificateExpirationMonitor", "Security");
    Util.unsetAttribute(objid, "wsSecurityScannerMonitor", "Security");

  jaasAuthDatas = Util.parseConfigIdListAttribute(objid, 'authDataEntries', "Security");
  jaasAuthDatas = filterForScope(jaasAuthDatas, scopeName, 'JAASAuthData', None);#cell only config... which really kinda sucks
  for jaasAuthData in jaasAuthDatas:
    if len(jaasAuthData) > 0:
      Util.remove(jaasAuthData);

  certificates = Util.parseConfigIdListAttribute(objid, 'certificates',"Security");
  certificates = filterForScope(certificates, scopeName, 'Certificate', None); #this probably really needs to look at its keystore ref to determine its management scope
  #TODO - don't always leave at the cell scope
  for certificate in certificates:
    if len(certificate) > 0:
      if certificate.find("#CACertificate_") != -1:
        Util.remove(certificate);

  inbound = Util.getOptionalAttribute(objid, 'inboundTrustedAuthenticationRealm',"Security");
  inbound = filterForScope(inbound, scopeName, 'TrustedAuthenticationRealm', None);
  if inbound is not None and len(inbound) > 0:
    Util.remove(inbound);

  outbound = Util.getOptionalAttribute(objid, 'outboundTrustedAuthenticationRealm',"Security");
  outbound = filterForScope(outbound, scopeName, 'TrustedAuthenticationRealm', None);
  if outbound is not None and len(outbound) > 0:
    Util.remove(outbound);

  dynamicSSLConfigSelections = Util.parseConfigIdListAttribute(objid, 'dynamicSSLConfigSelections', "Security");
  dynamicSSLConfigSelections = filterForScope(dynamicSSLConfigSelections, scopeName, 'DynamicSSLConfigSelection', None);
  for dynamicSSLConfigSelection in dynamicSSLConfigSelections:
    if len(dynamicSSLConfigSelection) > 0:
      Util.remove(dynamicSSLConfigSelection);

  # Must create Certificates, TrustManagers, KeyStores and KeyManagers first so that references can be created later.
  if jsonobject.has('children'):
    for curjsonobject in Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children')):
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereTrustManager":
        TrustManager.create(objid, curjsonobject);
      elif currole == "WebSphereKeyStore":
        keyStoreToUpdate = KeyStore.find(objid, curjsonobject);
        if keyStoreToUpdate is not None and len(keyStoreToUpdate) > 0:
          KeyStore.update(keyStoreToUpdate, curjsonobject);
        else:
          KeyStore.create(objid, curjsonobject);
      elif currole == "WebSphereKeyManager":
        KeyManager.create(objid, curjsonobject);
      elif currole == "WebSphereCertificate":
        certificateToUpdate = Certificate.find(objid, curjsonobject);
        if certificateToUpdate is not None or len(certificateToUpdate) > 0:
          Certificate.update(certificateToUpdate, curjsonobject);


  # Must create SSLConfigs and KeySets next so that references can be created later.
  modifiedSSLConfigs = [];
  if jsonobject.has('children'):
    for curjsonobject in Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children')):
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereSSLConfig":
        modified = SSLConfig._doImport(objid, curjsonobject, "repertoire");
        # keep a list of existing SSLConfigs that were updated.
        # we'll use this to determine if any SSLConfigs need to be deleted.
        if modified is not None:
          modifiedIdentifier = SSLConfig.getSSLConfigIdentifier(modified);
          modifiedSSLConfigs.append(modifiedIdentifier);
      elif currole == "WebSphereKeySet":
        keySetToUpdate = KeySet.find(objid, curjsonobject);
        if keySetToUpdate is not None or len(keySetToUpdate) > 0:
          KeySet.update(keySetToUpdate, curjsonobject);
        else:
          KeySet.create(objid, curjsonobject);

  # compare the initial list of SSLConfigs to the list of SSLConfigs we modified.
  # delete any SSLConfigs we did not modify (they must not exist in config data)
  for sslConfigBeforeApply in sslConfigsBeforeApply:
    if sslConfigBeforeApply not in modifiedSSLConfigs:
      sslConfigObjId = SSLConfig.getSSLConfigObjIdFromIdentifier(sslConfigBeforeApply);
      Util.remove(sslConfigObjId);

  # Must create WSNotification next so that references can be created later.
  if jsonobject.has('children'):
    for curjsonobject in Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children')):
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereWSNotification":
        WSNotification.create(objid, curjsonobject);

  # Must create WSSchedule next so that references can be created later.
  if jsonobject.has('children'):
    for curjsonobject in Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children')):
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereWSSchedule":
        WSSchedule.create(objid, curjsonobject);

  # Must create KeySetGroups next so that references can be created later.
  if jsonobject.has('children'):
    for curjsonobject in Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children')):
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereKeySetGroup":
        # try to update the KeySetGroup if it exists (see WI 145398). if it doesn't, create it.
        keySetGroupToUpdate = KeySetGroup.find(objid, curjsonobject, scopeName);
        if keySetGroupToUpdate is not None:
          KeySetGroup.update(keySetGroupToUpdate, curjsonobject);
        else:
          KeySetGroup.create(objid, curjsonobject);

  # Must create User Registries so that references can be created later
  if jsonobject.has('children'):
    for curjsonobject in Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children')):
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereLDAPUserRegistry":
        LDAPUserRegistry.update(objid, curjsonobject);
      elif currole == "WebSphereLocalOSUserRegistry":
        LocalOSUserRegistry.update(objid, curjsonobject);
      elif currole == "WebSphereCustomUserRegistry":
        CustomUserRegistry.update(objid, curjsonobject);
      elif currole == "WebSphereWIMUserRegistry":
        WIMUserRegistry.update(objid, curjsonobject);

  properties = {};# a map of attName to list of properties to update(dont just delete them all)
  if jsonobject.has('children'):
    for curjsonobject in Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children')):
      currole = curjsonobject.getString('roleName');
      attName = None;
      currpath = curjsonobject.getString('path');
      lastSlashIndex = currpath.rindex('/');
      nextToLastSlashIndex = currpath.rindex('/', 0, lastSlashIndex - 1);
      foldername = currpath[nextToLastSlashIndex+1:lastSlashIndex];
      if (foldername.find(Util.getTypeFoldername('PropertyAttrs')) > -1):
        attName = 'properties';
      elif (foldername.find(Util.getTypeFoldername('AdditionalSecAttrs')) > -1):
        attName = 'additionalSecAttrs';
      elif (foldername.find(Util.getTypeFoldername('WebAuthAttrs')) > -1):
        attName = 'webAuthAttrs';
      elif (foldername.find(Util.getTypeFoldername('ApplicationLoginConfig')) > -1):
        attName = 'applicationLoginConfig';
      elif (foldername.find(Util.getTypeFoldername('SystemLoginConfig')) > -1):
        attName = 'systemLoginConfig';

      if currole == "WebSphereJAASConfiguration":
        loginConfigObject = Util.getOptionalAttribute(objid, attName, "Security");
        if loginConfigObject is not None and len(loginConfigObject) > 0:
          JAASConfiguration.update(loginConfigObject, curjsonobject, attName);
        else:
          JAASConfiguration.create(objid, curjsonobject, attName);

      if Property.isPropertyRole(currole):
        if not properties.has_key(attName):
          properties[attName] = [];
        properties[attName].append(curjsonobject);
        continue;

      authObject = AuthMechanism.updateObjIfRole(objid, curjsonobject, currole, "Security");
      if (authObject == 1):
        continue;

      if currole == "WebSphereSSLConfigGroup":
        SSLConfigGroup.create(objid, curjsonobject);
      elif currole == "WebSphereSSLConfigRef":
        SSLConfigRef.create(objid, curjsonobject, "defaultSSLSettings");
      elif currole == "WebSphereJAASAuthData":
        JAASAuthData.create(objid, curjsonobject);
      elif currole == "WebSphereCACertificate":
        CACertificate.create(objid, curjsonobject);
      elif currole == "WebSphereUserRegistryRef":
        UserRegistryRef.doImport(objid, curjsonobject);
      elif currole == "WebSphereWSCertificateExpirationMonitor":
        WSCertificateExpirationMonitor.create(objid, curjsonobject);
      elif currole == "WebSphereWSSecurityScannerMonitor":
        WSSecurityScannerMonitor.create(objid, curjsonobject);
      elif currole == "WebSphereDynamicSSLConfigSelection":
        DynamicSSLConfigSelection.create(objid, curjsonobject);
      elif (currole == "WebSphereTrustedAuthenticationRealm") and (curjsonobject.getString("name") == "inboundTrustedAuthenticationRealm"):
        TrustedAuthenticationRealm.create(objid, curjsonobject, 'inboundTrustedAuthenticationRealm');
      elif (currole == "WebSphereTrustedAuthenticationRealm") and (curjsonobject.getString("name") == "outboundTrustedAuthenticationRealm"):
        TrustedAuthenticationRealm.create(objid, curjsonobject, 'outboundTrustedAuthenticationRealm');

  for x in properties.keys():
    Property.updateProperties(objid, properties[x], x, 'Security', 0);
  Util.popPathElement('Security');

"""list of types that will be put in specific scopes instead of at the cell level only"""
__dissectedTypes__ = [
  'TrustManager',
  'KeyManager',
  'KeyStore',
  'SSLConfig',
  'SSLConfigGroup',
  'KeySet',
  'KeySetGroup',
  'CAClient'
];

def filterForScope(objidorlist, scopeName, typeName, attName = 'managementScope'):
  if isinstance(objidorlist, [].__class__):
    return filterListForScope(objidorlist, scopeName, typeName, attName);
  else:
    return filterObjidForScope(objidorlist, scopeName, typeName, attName);

def filterObjidForScope(objid, scopeName, typeName, attName = 'managementScope'):
  result = None;
  if attName is None:
    #attName none means it is at the cell scope
    if scopeName is None or isCellScope(scopeName):
      return objid;
    else:
      return None;

  if scopeName is not None:
    if typeName in __dissectedTypes__:
      if scopesMatch(objid, scopeName, typeName, attName):
        result = objid;
    elif isCellScope(scopeName):
      result = objid;
    #else pass
  else:#if scopename is none, we are importing from an old export, hand it back
    result = objid;
  return result;

def filterListForScope(objidlist, scopeName, typeName, attName = 'managementScope'):
  result = [];
  if attName is None:
    #attName none means it is at the cell scope
    if scopeName is None or isCellScope(scopeName):
      return objidlist;
    else:
      return [];

  if scopeName is not None:
    if typeName in __dissectedTypes__:
      for objid in objidlist:
        if scopesMatch(objid, scopeName, typeName, attName):
          result.append(objid);
        #else pass
    elif isCellScope(scopeName):#only add to the cell level config
      result.extend(objidlist);
    else:#not in dissected, has scope, scope not cell. give nothing
      pass;
  else:#scope is None. this should only be possible on importing an old export(where the property is not set). return everything.
    result.extend(objidlist);

  return result;

def scopesMatch(objid, scopeName, typeName, attName):
  manScopeObj = Util.getRequiredAttribute(objid, attName, typeName);
  curScope = Util.getRequiredAttribute(manScopeObj, 'scopeName', 'ManagementScope');
  if curScope != scopeName:
    return 0;
  else:
    return 1;

def isCellScope(scopeName):
  return scopeName.rfind(":") == len("(cell)");

def doImport(containmentpath, roleName, jsonobject):
  objid = Util.getid(containmentpath);
  if objid == None or len(objid) == 0:
    index = containmentpath.rindex('/',0,len(containmentpath)-2)+1;
    parentconpath = containmentpath[0:index];
    parentid = Util.getid(parentconpath);
    if parentid == None or len(parentid) == 0:
      raise Exception("Parent does not exist to create security on.");
    objid = create(parentid, jsonobject);
  else:
    update(objid,jsonobject);
  return objid;

def doImportPartial(containmentpath, roleName, jsonobject):
  return doImport(containmentpath, roleName, jsonobject);
