from org.codehaus.jettison.json import JSONObject, JSONArray
import AdminTask;  # @UnresolvedImport
from CoreGroupMapping import CoreGroupMapping
from CustomService import CustomService
from Component import Component
from Service import Service
from ProcessDef import ProcessDef
from JavaProcessDef import JavaProcessDef
from NamedProcessDef import NamedProcessDef
from NamedJavaProcessDef import NamedJavaProcessDef
from StreamRedirect import StreamRedirect
from Audit import Audit
from PMIModule import PMIModule
from ProxySettings import ProxySettings
from StateManageable import StateManageable
from ProxyVirtualHostConfig import ProxyVirtualHostConfig
from WASConfLog import Log;
from Security import Security
from ServerEntry import ServerEntry
from SIBService import SIBService
from PMEServerExtension import PMEServerExtension
from utilities import Util
from com.ibm.ws.scripting import ScriptingException

__name_att__ = "websphere.server"

def getProcessDefObjIds(objid):
  procDefs = Util.parseConfigIdListAttribute(objid, "processDefinitions","Server");
  return procDefs;

def export(objid, parentcontainmentpath, parentrespath, dynamicClusterServerTemplate = 0):
  name = Util.getRequiredAttribute(objid, "name", 'Server');

  containmentpath = "%(parentconpath)sServer:%(name)s/" % {'parentconpath':parentcontainmentpath, 'name':name }
  if not containmentpath.startswith("/"):
    containmentpath = "/" + containmentpath;

  dict = _export(objid, parentrespath, containmentpath, dynamicClusterServerTemplate);
  dict['conpath'] = containmentpath;
  return dict

def _export(objid, parentrespath, containmentpath, dynamicClusterServerTemplate = 0):
  Util.pushPathElement('Server')

  name = Util.getRequiredAttribute(objid, "name", 'Server');

  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");
  if dynamicClusterServerTemplate == 1:
    exportedObject.put("description", "Discovered WebSphereDynamicClusterServerTemplate");
    exportedObject.put("roleName", "WebSphereDynamicClusterServerTemplate");
  else:
    exportedObject.put("description", "Discovered WebSphereServer");
    exportedObject.put("roleName", "WebSphereServer");

  roleProperties = JSONObject();

  if int(Util.getVersion().split(".", 1)[0]) >= 8:
    Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.server.adjustport", objid, "adjustPort","Server");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.server.changegroupafterstartup", objid, "changeGroupAfterStartup","Server");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.server.modelid", objid, "modelId","Server");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.server.shortname", objid, "shortName","Server");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.server.uniqueid", objid, "uniqueId","Server");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.server.servertype", objid, "serverType","Server");
  serverType = AdminConfig.showAttribute(objid, "serverType");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.server.developmentmode", objid, "developmentMode","Server");
  # The provisionComponents attribute is not always present for a Server configuration object so we need to handle the exception that
  # occurs when it is not present.  We think the issue may be introduced during migration from WebSphere 6 to WebSphere 7.
  try:
    Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.server.provisioncomponents", objid, "provisionComponents","Server");
  except ScriptingException, msg:
    Log.debug("Util.addAttributeToJsonIfNotNone failure: %s" % msg);
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.server.parallelstartenabled", objid, "parallelStartEnabled","Server");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.server.clustername", objid, "clusterName","Server");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.server.changeuserafterstartup", objid, "changeUserAfterStartup","Server");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.server", objid, "name","Server");
  # add a flag to show if this server is a member of a dynamic cluster
  isDynamicClusterMember = "false"
  if dynamicClusterServerTemplate == 0:
    clusterName = Util.getRequiredAttribute(objid, "clusterName", 'Server');
    if clusterName is not None and clusterName != "":
      if Util.isValidType("DynamicCluster"):
        dcContainmentPath = "/DynamicCluster:%s/" % clusterName
        dc = Util.getid(dcContainmentPath);
        if dc is not None and len(dc) > 0:
          isDynamicClusterMember = "true"
  Util.addPathPropertyToJson(roleProperties, "isdynamicclustermember", isDynamicClusterMember)

  exportedObject.put("roleProperties", roleProperties);
  result = { 'object': exportedObject, 'respath':respath }
  extraObjects = [];
  typeFolders = {};
  extraObjects = Component.exportComponents(objid, respath, extraObjects, typeFolders, 'components', "Server");
  extraObjects = Service.exportServices(objid, respath, extraObjects, typeFolders, 'services', "Server");

  i = 0;
  customServices = Util.parseConfigIdListAttribute(objid, 'customServices',"Server");
  for customService in customServices:
    if len(customService) > 0:
      returndict = Util.createTypeFolder(respath, "CustomService", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, CustomService._export(customService, currespath, "CustomService%s" % i));
      i = i + 1;

  procs = getProcessDefObjIds(objid);
  i = 0;
  if procs is not None and len(procs) > 0:
    for procid in procs:
      if len(procid) > 0:
        if procid.find("#ProcessDef_") > 0:
          returndict = Util.createTypeFolder(respath, "ProcessDef", typeFolders);
          currespath = returndict['path'];
          if returndict.has_key('object'):
            Util.addFromExport(extraObjects, returndict['object']);
          Util.addAllFromExport(extraObjects, ProcessDef._export(procid, currespath, 'ProcessDef%s' % i));
          i = i + 1;
        elif procid.find("#JavaProcessDef_") > 0:
          returndict = Util.createTypeFolder(respath, "JavaProcessDef", typeFolders);
          currespath = returndict['path'];
          if returndict.has_key('object'):
            Util.addFromExport(extraObjects, returndict['object']);
          Util.addAllFromExport(extraObjects, JavaProcessDef._export(procid, currespath, 'JavaProcessDef%s' % i));
          i = i + 1;
        elif procid.find("#NamedProcessDef_") > 0:
          returndict = Util.createTypeFolder(respath, "NamedProcessDef", typeFolders);
          currespath = returndict['path'];
          if returndict.has_key('object'):
            Util.addFromExport(extraObjects, returndict['object']);
          Util.addAllFromExport(extraObjects, NamedProcessDef._export(procid, currespath, Util.getRequiredAttribute(procid, "name", 'Server')));
          i = i + 1;
        elif procid.find("#NamedJavaProcessDef_") > 0:
          returndict = Util.createTypeFolder(respath, "NamedJavaProcessDef", typeFolders);
          currespath = returndict['path'];
          if returndict.has_key('object'):
            Util.addFromExport(extraObjects, returndict['object']);
          Util.addAllFromExport(extraObjects, NamedJavaProcessDef._export(procid, currespath, Util.getRequiredAttribute(procid, "name", 'Server')));
          i = i + 1;

  errorStreamRedirect = Util.getRequiredAttribute(objid, 'errorStreamRedirect',"Server");
  if errorStreamRedirect is not None and len(errorStreamRedirect) > 0:
    returndict = Util.createTypeFolder(respath, "StreamRedirect", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
      Util.addFromExport(extraObjects, returndict['object']);
    Util.addAllFromExport(extraObjects, StreamRedirect._export(errorStreamRedirect, currespath, "ErrorStreamRedirect"));

  outputStreamRedirect = Util.getRequiredAttribute(objid, 'outputStreamRedirect',"Server");
  if outputStreamRedirect is not None and len(outputStreamRedirect) > 0:
    returndict = Util.createTypeFolder(respath, "StreamRedirect", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
      Util.addFromExport(extraObjects, returndict['object']);
    Util.addAllFromExport(extraObjects, StreamRedirect._export(outputStreamRedirect, currespath, "OutputStreamRedirect"));

  i = 0;
  auditConPath = "%(cur)sAudit:/" % { 'cur':containmentpath }
  audits = Util.getid(auditConPath, ['Audit']);
  if audits is not None and len(audits) > 0:
    auditList = audits.splitlines();
    for audit in auditList:
      if len(audit) > 0:
        returndict = Util.createTypeFolder(respath, "Audit", typeFolders);
        currespath = returndict['path'];
        if returndict.has_key('object'):
          Util.addFromExport(extraObjects, returndict['object']);
        Util.addAllFromExport(extraObjects, Audit._export(audit, currespath, "Audit%s" % i));
        i = i + 1;

  i = 0;
  sibServiceConPath = "%(cur)sSIBService:/" % { 'cur':containmentpath }
  sibServices = Util.getid(sibServiceConPath, ['SIBService']);
  if sibServices is not None and len(sibServices) > 0:
    sibServiceList = sibServices.splitlines();
    for sibService in sibServiceList:
      if len(sibService) > 0:
        returndict = Util.createTypeFolder(respath, "SIBService", typeFolders);
        currespath = returndict['path'];
        if returndict.has_key('object'):
          Util.addFromExport(extraObjects, returndict['object']);
        Util.addAllFromExport(extraObjects, SIBService._export(sibService, currespath, "SIBService%s" % i));
        i = i + 1;

  i = 0;
  pmeServerExtensionConPath = "%(cur)sPMEServerExtension:/" % { 'cur':containmentpath }
  pmeServerExtensions = Util.getid(pmeServerExtensionConPath, ['PMEServerExtension']);
  if pmeServerExtensions is not None and len(pmeServerExtensions) > 0:
    pmeServerExtensionList = pmeServerExtensions.splitlines();
    for pmeServerExtension in pmeServerExtensionList:
      if len(pmeServerExtension) > 0:
        returndict = Util.createTypeFolder(respath, "PMEServerExtension", typeFolders);
        currespath = returndict['path'];
        if returndict.has_key('object'):
          Util.addFromExport(extraObjects, returndict['object']);
        Util.addAllFromExport(extraObjects, PMEServerExtension._export(pmeServerExtension, currespath, "PMEServerExtension%s" % i));
        i = i + 1;

  #should only have one of these
  topPMIModule = PMIModule.getTopPMIModule(objid);
  if topPMIModule is not None and len(topPMIModule) > 0:
    returndict = Util.createTypeFolder(respath, "PMIModule", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
    pmiModuleName = Util.getOptionalAttribute(topPMIModule[0], "moduleName", "PMIModule");
    if pmiModuleName == None or len(pmiModuleName) == 0:
      pmiModuleName = "PMI Module";
    Util.addAllFromExport(extraObjects, PMIModule._export(topPMIModule[0], currespath,  pmiModuleName));

  proxyVirtualHostConfig = ProxyVirtualHostConfig.getProxyVirtualHostConfig(objid);
  if proxyVirtualHostConfig is not None and len(proxyVirtualHostConfig) > 0:
    returndict = Util.createTypeFolder(respath, "ProxyVirtualHostConfig", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
    Util.addAllFromExport(extraObjects, ProxyVirtualHostConfig._export(proxyVirtualHostConfig, currespath, "Proxy Virtual Host Configs"));

  proxySettings = ProxySettings.getProxySettings(objid);
  if proxySettings is not None and len(proxySettings) > 0:
    returndict = Util.createTypeFolder(respath, "ProxySettings", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
      Util.addFromExport(extraObjects, returndict['object']);
    Util.addAllFromExport(extraObjects, ProxySettings._export(proxySettings, currespath, "Proxy Settings"));

  stateManagement = Util.getRequiredAttribute(objid, 'stateManagement',"Server");
  if stateManagement is not None and len(stateManagement) > 0:
    returndict = Util.createTypeFolder(respath, "StateManageable", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
      Util.addFromExport(extraObjects, returndict['object']);
    Util.addAllFromExport(extraObjects, StateManageable._export(stateManagement, currespath, "StateManageable"));

  if serverType != "GENERIC_SERVER":
    Util.addAllFromExport(extraObjects, CoreGroupMapping._export(objid, respath, dynamicClusterServerTemplate));

  secfolderretdict = Util.createTypeFolder(respath, "Security", typeFolders);
  secresfolpath = secfolderretdict['path'];
  if secfolderretdict.has_key('object'):
    Util.addFromExport(extraObjects, secfolderretdict['object']);
  Util.addAllFromExport(extraObjects, Security._export(objid, secresfolpath, "Security"));

  serverEntry = getServerEntry(objid);
  if serverEntry is not None and len(serverEntry) > 0:
    returndict = Util.createTypeFolder(respath, "ServerEntry", typeFolders);
    currespath = returndict['path'];
    if returndict.has_key('object'):
      Util.addFromExport(extraObjects, returndict['object']);
    Util.addAllFromExport(extraObjects, ServerEntry._export(serverEntry, currespath, "ServerEntry"));

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

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

def doImport(containmentpath, roleName, jsonobject):
  if not jsonobject.has("roleProperties"):
    raise Exception("Server resource has no role properties!");

  roleProperties = jsonobject.getJSONObject("roleProperties");
  if not roleProperties.has("websphere.server"):
    raise Exception("Resource role properties does not contain websphere.server!");

  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 Server on.");
    objid = create(parentid, jsonobject, containmentpath);
  else:
    update(objid,jsonobject, containmentpath);
  return objid;



def create(parentid, jsonobject, containmentpath):
  Util.pushPathElement('Server')
  if not jsonobject.has("roleProperties"):
    raise Exception("Server resource has no role properties!");

  roleProperties = jsonobject.getJSONObject("roleProperties");

  if not roleProperties.has("websphere.server"):
    raise Exception("Resource role properties does not contain websphere.server!");

  # On Demand Routers are a Server object of type ONDEMAND_ROUTER
  # they must be created using the AdminTask.createOnDemandRouter command
  # we first create one with the default ODR template
  # next, we run Server.update to update the On Demand Router properties from config data
  serverType = roleProperties.optString("websphere.server.servertype", None)
  if serverType == "ONDEMAND_ROUTER":
    nodeName = Util.getNodeNameFromObjID(parentid);
    name = roleProperties.optString("websphere.server", None)
    params = "[-name " + name + " -genUniquePorts true ]"
    Log.logMsg("Creating an On Demand Router on node " + nodeName + " with params " + params, Log.LogLevelDebug);
    odr = AdminTask.createOnDemandRouter(nodeName, params)
    Util.popPathElement('Server');
    # now, update the ODR we just created
    update(odr, jsonobject, containmentpath)
    return odr;
  elif serverType == "WEB_SERVER":
    nodeName = Util.getNodeNameFromObjID(parentid);
    name = roleProperties.optString("websphere.server", None)
    params =  "[-name %(name)s ]" % {'name':name}
    webServer = AdminTask.createWebServer(nodeName, params)
    Util.popPathElement('Server')
    update(webServer, jsonobject, containmentpath)

    return webServer
  # Generic Servers are a Server object of type GENERIC_SERVER.
  # They must be created using the AdminTask.createGenericServer command
  # we first create one with the default generic server template
  # next, we run Server.update to update the generic server properties from config data
  if serverType == "GENERIC_SERVER":
    nodeName = Util.getNodeNameFromObjID(parentid);
    name = roleProperties.optString("websphere.server", None)
    params = "[-name " + name + " ]"
    Log.logMsg("Creating a generic server on node " + nodeName + " with params " + params, Log.LogLevelDebug);
    gserver = AdminTask.createGenericServer(nodeName, params)
    Util.popPathElement('Server');
    # now, update the generic server we just created
    update(gserver, jsonobject, containmentpath)
    return gserver;

  properties = [];
  if int(Util.getVersion().split(".", 1)[0]) >= 8:
    Util.addIfNotNone(properties, "adjustPort", roleProperties.optString("websphere.server.adjustport", None));
  Util.addIfNotNoneOrEmpty(properties, "changeGroupAfterStartup", roleProperties.optString("websphere.server.changegroupafterstartup", None));
  Util.addIfNotNone(properties, "modelId", roleProperties.optString("websphere.server.modelid", None));
  Util.addIfNotNone(properties, "shortName", roleProperties.optString("websphere.server.shortname", None));
  Util.addIfNotNone(properties, "uniqueId", roleProperties.optString("websphere.server.uniqueid", None));
  #Util.addIfNotNone(properties, "serverType", roleProperties.optString("websphere.server.servertype", None));
  Util.addIfNotNone(properties, "developmentMode", roleProperties.optString("websphere.server.developmentmode", None));
  Util.addIfNotNone(properties, "provisionComponents", roleProperties.optString("websphere.server.provisioncomponents", None));
  Util.addIfNotNone(properties, "parallelStartEnabled", roleProperties.optString("websphere.server.parallelstartenabled", None));
  Util.addIfNotNoneOrEmpty(properties, "clusterName", roleProperties.optString("websphere.server.clustername", None));
  Util.addIfNotNoneOrEmpty(properties, "changeUserAfterStartup", roleProperties.optString("websphere.server.changeuserafterstartup", None));
  Util.addIfNotNone(properties, "name", roleProperties.optString("websphere.server", None));
  print "Creating Server with attributes";
  for prop in properties:
    print "%(name)s = %(value)s" % { 'name': prop[0], 'value': prop[1] };
  objid = Util.create("Server", parentid, properties);

  for prop in getProcessDefObjIds(objid):
    Util.remove(prop);

  Component.removeComponents(objid, 'components', "Server");
  Service.removeServices(objid, 'services', "Server");

  customServices = Util.parseConfigIdListAttribute(objid, 'customServices',"Server");
  for customService in customServices:
    if len(customService) > 0:
      Util.remove(customService);

  errorStreamRedirect = Util.getRequiredAttribute(objid, 'errorStreamRedirect',"Server");
  if errorStreamRedirect is not None and len(errorStreamRedirect) > 0:
    Util.remove(errorStreamRedirect);

  outputStreamRedirect = Util.getRequiredAttribute(objid, 'outputStreamRedirect',"Server");
  if outputStreamRedirect is not None and len(outputStreamRedirect) > 0:
    Util.remove(outputStreamRedirect);

  name = roleProperties.optString("websphere.server", None);
  auditConPath = "%(cur)sAudit:/" % { 'cur':containmentpath }
  audits = Util.getid(auditConPath, ['Audit']);
  if audits is not None and len(audits) > 0:
    auditList = audits.splitlines();
    for audit in auditList:
      if len(audit) > 0:
        Util.remove(audit);

  # Handle the case where the json file does not contain PMEServerExtension and/or SIBService configuration objects.
  # This may happen if the configuration was discovered by a version of the plugin that did not yet have support
  # for those objects.   In that case, we don't want to delete the objects from the server.  We will just let the
  # existing objects remain.
  if jsonobject.has('children'):
    children = Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children'));

    foundPMEServerExtension = "false";
    foundSIBService = "false";
    for curjsonobject in children:
      currole = curjsonobject.getString("roleName");
      if currole == "WebSpherePMEServerExtension":
        print "Server Create:  Found PMEServerExtension configuration object in the json being applied so deleting the existing live object."
        foundPMEServerExtension = "true";
      elif currole == "WebSphereSIBService":
        print "Server Create:  Found SIBService configuration object in the json being applied so deleting the existing live object."
        foundSIBService = "true";

    if foundPMEServerExtension == "true":
      pmeServerExtensionConPath = "%(cur)sPMEServerExtension:/" % { 'cur':containmentpath }
      pmeServerExtensions = Util.getid(pmeServerExtensionConPath, ['PMEServerExtension']);
      if pmeServerExtensions is not None and len(pmeServerExtensions) > 0:
        pmeServerExtensionList = pmeServerExtensions.splitlines();
        for pmeServerExtension in pmeServerExtensionList:
          if len(pmeServerExtension) > 0:
            Util.remove(pmeServerExtension);

    if foundSIBService == "true":
      sibServiceConPath = "%(cur)sSIBService:/" % { 'cur':containmentpath }
      sibServices = Util.getid(sibServiceConPath, ['SIBService']);
      if sibServices is not None and len(sibServices) > 0:
        sibServiceList = sibServices.splitlines();
        for sibService in sibServiceList:
          if len(sibService) > 0:
            Util.remove(sibService);

  stateManagement = Util.getRequiredAttribute(objid, 'stateManagement',"Server");
  if stateManagement is not None and len(stateManagement) > 0:
    Util.remove(stateManagement);

  #should only have one of these
  topPMIModule = PMIModule.getTopPMIModule(objid);
  if topPMIModule is not None and len(topPMIModule) > 0:
    Util.remove(topPMIModule[0]);

  """
  please don't judge me. websphere makes this necessary.
  SERVICES MUST BE IMPORTED BEFORE COMPONENTS(at least top level services)
  ThreadPoolManager MUST BE IMPORTED BEFORE ANY OTHER SERVICES.
  This is mostly caused by references from services/components to ThreadPools. From what I(kensie sturdevant) can tell, all referenced thread pools must exists on the ThreadPoolManager for the server.
  We will then need to pass the "ThreadPool lookup containment path" through to all services/components
  """
  threadPoolLookupPath = "%sThreadPoolManager:/" % containmentpath; #assuming only a single thread pool manager
  if jsonobject.has('children'):
    children = Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children'));
    Log.debug(len(children));
    for curjsonobject in children[:]:
      currole = curjsonobject.getString("roleName");
      if currole == "WebSphereThreadPoolManager":
        Service.createObjIfRole(objid, curjsonobject, currole, threadPoolLookupPath);
        children.remove(curjsonobject);

    Log.debug(len(children));

    for curjsonobject in children[:]:
      currole = curjsonobject.getString("roleName");
      if (Service.createObjIfRole(objid, curjsonobject, currole, threadPoolLookupPath) == 1):
        children.remove(curjsonobject);

    Log.debug(len(children));

    for curjsonobject in children:
      currole = curjsonobject.getString("roleName");
      componentObject = 0;
      componentObject = Component.createObjIfRole(objid, curjsonobject, currole, threadPoolLookupPath);
      if (componentObject == 0):
        if currole == "WebSphereProcessDef":
          ProcessDef.create(objid, curjsonobject, 'processDefinitions');
        elif currole == "WebSphereJavaProcessDef":
          JavaProcessDef.create(objid, curjsonobject, 'processDefinitions');
        elif currole == "WebSphereNamedProcessDef":
          NamedProcessDef.create(objid, curjsonobject, 'processDefinitions');
        elif currole == "WebSphereNamedJavaProcessDef":
          NamedJavaProcessDef.create(objid, curjsonobject, 'processDefinitions');
        elif (currole == "WebSphereStreamRedirect") and (curjsonobject.getString("name") == "ErrorStreamRedirect"):
          StreamRedirect.create(objid, curjsonobject, 'errorStreamRedirect');
        elif (currole == "WebSphereStreamRedirect") and (curjsonobject.getString("name") == "OutputStreamRedirect"):
          StreamRedirect.create(objid, curjsonobject, 'outputStreamRedirect');
        elif currole == "WebSphereAudit":
          Audit.create(objid, curjsonobject);
        elif currole == "WebSpherePMIModule":
          PMIModule.create(objid, curjsonobject);
        elif currole == "WebSpherePMEServerExtension":
          PMEServerExtension.create(objid, curjsonobject);
        elif currole == "WebSphereProxySettings":
          ProxySettings.create(objid, curjsonobject);
        elif currole == "WebSphereStateManageable":
          StateManageable.create(objid, curjsonobject);
        elif currole == "WebSphereProxyVirtualHostConfig":
          ProxyVirtualHostConfig.create(objid, curjsonobject);
        elif currole == "WebSphereCoreGroupMapping":
          CoreGroupMapping.doImport(objid, curjsonobject);
        elif currole == "WebSphereSecurity":
          Security.update(objid, curjsonobject);
        elif currole == "WebSphereSIBService":
          SIBService.create(objid, curjsonobject)
        elif currole == "WebSphereServerEntry":
          #ServerIndex -> serverEntries is read-only.  We cannot do normal remove/create.
          #Have to do an update once we find the right server entry to update.
          roleProperties = curjsonobject.getJSONObject("roleProperties");
          objectName = roleProperties.optString("websphere.serverentry.servername", None);
          serverEntry = getServerEntry(objid);
          if serverEntry is not None and len(serverEntry) > 0:
            serverName = Util.getOptionalAttribute(serverEntry, 'serverName', "ServerEntry");
            if (serverName == objectName):
              ServerEntry.update(serverEntry, curjsonobject);
            else:
              Log.debug("Server name on ServerEntry resource does not match the current server name!");
          else:
            Log.debug("Unable to locate ServerEntry for %s" % objectName);

  Util.popPathElement('Server');
  return objid;

def update(objid,jsonobject, containmentpath, dynamicClusterServerTemplate = 0, dcServerTemplateContainmentPath = None):
  if dynamicClusterServerTemplate == 1:
    Util.pushPathElement('DynamicClusterServerTemplate')
    tpmcontainmentpath = dcServerTemplateContainmentPath
  else:
    Util.pushPathElement('Server')
    tpmcontainmentpath = containmentpath
  if not jsonobject.has("roleProperties"):
    raise Exception("Server resource has no role properties!");

  roleProperties = jsonobject.getJSONObject("roleProperties");

  if not roleProperties.has("websphere.server"):
    raise Exception("Resource role properties does not contain websphere.server!");

  atts = [];
  if int(Util.getVersion().split(".", 1)[0]) >= 8:
    Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.server.adjustport", "true"), "adjustPort","Server");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.server.changegroupafterstartup", None), "changeGroupAfterStartup","Server");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.server.modelid", None), "modelId","Server");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.server.shortname", None), "shortName","Server");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.server.uniqueid", None), "uniqueId","Server");
  #Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.server.servertype", None), "serverType","Server");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.server.developmentmode", None), "developmentMode","Server");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.server.provisioncomponents", None), "provisionComponents","Server");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.server.parallelstartenabled", None), "parallelStartEnabled","Server");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.server.clustername", None), "clusterName","Server");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.server.changeuserafterstartup", None), "changeUserAfterStartup","Server");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.server", None), "name","Server");
  if len(atts) != 0:
    print "Modifying Server with attributes:"
    for prop in atts:
      print "%(name)s = %(value)s" % { 'name': prop[0], 'value': prop[1] };

    Util.modify(objid, atts);
  else:
    print "Server configuration up to date.";

  for prop in getProcessDefObjIds(objid):
    Util.remove(prop);

  Component.removeComponents(objid, 'components', "Server");
  Service.removeServices(objid, 'services', "Server");

  #should only have one of these
  topPMIModule = PMIModule.getTopPMIModule(objid);
  if topPMIModule is not None and len(topPMIModule) > 0:
    Util.remove(topPMIModule[0]);

  proxySettings = ProxySettings.getProxySettings(objid);
  if proxySettings is not None and len(proxySettings) > 0:
    Util.remove(proxySettings);

  proxyVirtualHostConfig = ProxyVirtualHostConfig.getProxyVirtualHostConfig(objid);
  if proxyVirtualHostConfig is not None and len(proxyVirtualHostConfig) > 0:
    Util.remove(proxyVirtualHostConfig);

  customServices = Util.parseConfigIdListAttribute(objid, 'customServices',"Server");
  for customService in customServices:
    if len(customService) > 0:
      Util.remove(customService);

  errorStreamRedirect = Util.getRequiredAttribute(objid, 'errorStreamRedirect',"Server");
  if errorStreamRedirect is not None and len(errorStreamRedirect) > 0:
    Util.remove(errorStreamRedirect);

  outputStreamRedirect = Util.getRequiredAttribute(objid, 'outputStreamRedirect',"Server");
  if outputStreamRedirect is not None and len(outputStreamRedirect) > 0:
    Util.remove(outputStreamRedirect);

  name = roleProperties.optString("websphere.server", None);
  auditConPath = "%(cur)sAudit:/" % { 'cur':containmentpath }
  audits = Util.getid(auditConPath, ['Audit']);
  if audits is not None and len(audits) > 0:
    auditList = audits.splitlines();
    for audit in auditList:
      if len(audit) > 0:
        Util.remove(audit);

  # Handle the case where the json file does not contain PMEServerExtension and/or SIBService configuration objects.
  # This may happen if the configuration was discovered by a version of the plugin that did not yet have support
  # for those objects.   In that case, we don't want to delete the objects from the server.  We will just let the
  # existing objects remain.
  if jsonobject.has('children'):
    children = Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children'));

    foundPMEServerExtension = "false";
    foundSIBService = "false";
    for curjsonobject in children:
      currole = curjsonobject.getString("roleName");
      if currole == "WebSpherePMEServerExtension":
        print "Server Create:  Found PMEServerExtension configuration object in the json being applied so deleting the existing live object."
        foundPMEServerExtension = "true";
      elif currole == "WebSphereSIBService":
        print "Server Create:  Found SIBService configuration object in the json being applied so deleting the existing live object."
        foundSIBService = "true";

    if foundPMEServerExtension == "true":
      pmeServerExtensionConPath = "%(cur)sPMEServerExtension:/" % { 'cur':containmentpath }
      pmeServerExtensions = Util.getid(pmeServerExtensionConPath, ['PMEServerExtension']);
      if pmeServerExtensions is not None and len(pmeServerExtensions) > 0:
        pmeServerExtensionList = pmeServerExtensions.splitlines();
        for pmeServerExtension in pmeServerExtensionList:
          if len(pmeServerExtension) > 0:
            Util.remove(pmeServerExtension);

    if foundSIBService == "true":
      sibServiceConPath = "%(cur)sSIBService:/" % { 'cur':containmentpath }
      sibServices = Util.getid(sibServiceConPath, ['SIBService']);
      if sibServices is not None and len(sibServices) > 0:
        sibServiceList = sibServices.splitlines();
        for sibService in sibServiceList:
          if len(sibService) > 0:
            Util.remove(sibService);

  stateManagement = Util.getRequiredAttribute(objid, 'stateManagement',"Server");
  if stateManagement is not None and len(stateManagement) > 0:
    Util.remove(stateManagement);

  """
  please don't judge me. websphere makes this necessary.
  SERVICES MUST BE IMPORTED BEFORE COMPONENTS(at least top level services)
  ThreadPoolManager MUST BE IMPORTED BEFORE ANY OTHER SERVICES.
  This is mostly caused by references from services/components to ThreadPools. From what I(kensie sturdevant) can tell, all referenced thread pools must exists on the ThreadPoolManager for the server.
  We will then need to pass the "ThreadPool lookup containment path" through to all services/components
  """
  threadPoolLookupPath = "%sThreadPoolManager:/" % tpmcontainmentpath; #assuming only a single thread pool manager
  if jsonobject.has('children'):
    children = Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children'));
    Log.debug(len(children));
    for curjsonobject in children[:]:
      currole = curjsonobject.getString("roleName");
      if currole == "WebSphereThreadPoolManager":
        Service.createObjIfRole(objid, curjsonobject, currole, threadPoolLookupPath);
        children.remove(curjsonobject);

    Log.debug(len(children));

    for curjsonobject in children[:]:
      currole = curjsonobject.getString("roleName");
      if (Service.createObjIfRole(objid, curjsonobject, currole, threadPoolLookupPath) == 1):
        children.remove(curjsonobject);

    Log.debug(len(children));

    for curjsonobject in children:
      currole = curjsonobject.getString("roleName");
      componentObject = 0;
      componentObject = Component.createObjIfRole(objid, curjsonobject, currole, threadPoolLookupPath);
      if (componentObject == 0):
        if currole == "WebSphereProcessDef":
          ProcessDef.create(objid, curjsonobject, 'processDefinitions');
        elif currole == "WebSphereJavaProcessDef":
          JavaProcessDef.create(objid, curjsonobject, 'processDefinitions');
        elif currole == "WebSphereNamedProcessDef":
          NamedProcessDef.create(objid, curjsonobject, 'processDefinitions');
        elif currole == "WebSphereNamedJavaProcessDef":
          NamedJavaProcessDef.create(objid, curjsonobject, 'processDefinitions');
        elif (currole == "WebSphereStreamRedirect") and (curjsonobject.getString("name") == "ErrorStreamRedirect"):
          StreamRedirect.create(objid, curjsonobject, 'errorStreamRedirect');
        elif (currole == "WebSphereStreamRedirect") and (curjsonobject.getString("name") == "OutputStreamRedirect"):
          StreamRedirect.create(objid, curjsonobject, 'outputStreamRedirect');
        elif currole == "WebSphereAudit":
          Audit.create(objid, curjsonobject);
        elif currole == "WebSpherePMEServerExtension":
          PMEServerExtension.create(objid, curjsonobject);
        elif currole == "WebSpherePMIModule":
          PMIModule.create(objid, curjsonobject);
        elif currole == "WebSphereProxySettings":
          ProxySettings.create(objid, curjsonobject);
        elif currole == "WebSphereStateManageable":
          StateManageable.create(objid, curjsonobject);
        elif currole == "WebSphereProxyVirtualHostConfig":
          ProxyVirtualHostConfig.create(objid, curjsonobject);
        elif currole == "WebSphereCoreGroupMapping":
          CoreGroupMapping.doImport(objid, curjsonobject);
        elif currole == "WebSphereSecurity":
          Security.update(objid, curjsonobject);
        elif currole == "WebSphereSIBService":
          SIBService.create(objid, curjsonobject)
        elif currole == "WebSphereServerEntry":
          #ServerIndex -> serverEntries is read-only.  We cannot do normal remove/create.
          #Have to do an update once we find the right server entry to update.
          roleProperties = curjsonobject.getJSONObject("roleProperties");
          objectName = roleProperties.optString("websphere.serverentry.servername", None);
          serverEntry = getServerEntry(objid);
          if serverEntry is not None and len(serverEntry) > 0:
            serverName = Util.getOptionalAttribute(serverEntry, 'serverName', "ServerEntry");
            if (serverName == objectName):
              ServerEntry.update(serverEntry, curjsonobject);
            else:
              Log.debug("Server name on ServerEntry resource does not match the current server name!");
          else:
            Log.debug("Unable to locate ServerEntry for %s" % objectName);

  if dynamicClusterServerTemplate == 1:
    Util.popPathElement('DynamicClusterServerTemplate')
  else:
    Util.popPathElement('Server')
  return objid;

def getServerEntry(serverid):
  serverName = Util.getRequiredAttribute(serverid, 'name', 'Server');
  # check to see if this is a dynamic cluster server template
  if serverid.find("/dynamicclusters/") != -1:
    return getServerEntryForDCServerTemplate(serverid, serverName)
  else:
    nodename = Util.getNodeName(serverid);
    return getServerEntryFromNode(nodename, serverName);

def getServerEntryFromNode(nodename, serverName):
  nodeobj = Util.getid("/Node:%s/" % nodename);
  serind = Util.getid("/Node:%s/ServerIndex:/" % nodename);
  serEntries = Util.parseConfigIdListAttribute(serind, 'serverEntries', 'ServerIndex');
  for entry in serEntries:
    entryName = Util.getRequiredAttribute(entry, 'serverName', 'ServerEntry');
    if entryName == serverName:
      return entry;
  return None;

def getServerEntryForDCServerTemplate(serverid, serverName):
  serind = None;
  # find the server index that has /dynamicclusters/dynmaicClusterName| in the objid
  serverIndexes = Util.getAllObjectsOfType("ServerIndex")
  if len(serverIndexes) > 0:
    for serverIndex in serverIndexes:
      if len(serverIndex) > 0:
        if serverIndex.find("/dynamicclusters/%s|" % serverName) != -1:
          serind = serverIndex
          break;

  if serind is not None:
    serEntries = Util.parseConfigIdListAttribute(serind, 'serverEntries', 'ServerIndex');
    for entry in serEntries:
      entryName = Util.getRequiredAttribute(entry, 'serverName', 'ServerEntry');
      if entryName == serverName:
        return entry;
  else:
    return None;
