###
# Licensed Materials - Property of IBM Corp.
# @product.name.full@
# (c) Copyright IBM Corporation 2003, 2016. All Rights Reserved.
#
# U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
# GSA ADP Schedule Contract with IBM Corp.
#
# Filename: confdiscover.py
#
#
###


import codecs;

from org.codehaus.jettison.json import JSONObject, JSONArray;
import sys;
import os;

from java.lang import Throwable
import traceback
# Necessary to make "os" functions work on Windows systems that did not exist when Jython 2.1 was created.
# This workaround overcomes the Jython Windows limitation described on the following webpage:
# http://www.ibm.com/support/knowledgecenter/SS7JFU_6.1.0/com.ibm.websphere.express.doc/info/exp/ae/cxml_jython.html
# WebSphere 9 has moved to Jython 2.7 so this workaround will fail in that environment - that is why
# I surrounded it with a try/except structure.
try:
    import javaos
    if javaos._osType == 'posix' and java.lang.System.getProperty('os.name').startswith('Windows'):  # @UndefinedVariable
      sys.registry.setProperty('python.os', 'nt');
      reload(javaos);
except:
    pass

sys.modules['AdminConfig'] = AdminConfig # @UndefinedVariable
sys.modules['AdminControl'] = AdminControl # @UndefinedVariable
sys.modules['AdminApp'] = AdminApp # @UndefinedVariable
sys.modules['AdminTask'] = AdminTask # @UndefinedVariable

configurationTypes = {};
stack = [];

def mainmethod():
  pihelper = PluginInputHelper.PluginInputHelper(sys.argv[0]);
  inputProps = pihelper.getInputProperties();

  logDir = pihelper.getLogDirectory();
  logFile = open("%s/debugLog.txt" % logDir.getAbsolutePath(),'w');
  redoFile = open("%s/redoLog.txt" % logDir.getAbsolutePath(),'w');
  outFile = codecs.open(sys.argv[1], "w", "utf-8");
  Log.setLogLevel(inputProps.getProperty("logLevel"));
  Log.setLogFile(logFile);
  Log.setRedoFile(redoFile);

  resourceJSONObject = pihelper.getFullResourceConfiguration();
  configurationTypesInput = Util.formatConfigurationTypes(inputProps.getProperty("configurationTypes"))
  adminConfigTypes = Util.getAdminConfigTypes();

  discConfigTypesJson = ""

  if configurationTypesInput is not None and len(configurationTypesInput) > 0:
    for line in configurationTypesInput.splitlines():
      line = line.strip();
      if len(line) > 0:
        if line in adminConfigTypes:
          configurationTypes[line] = line;
          discConfigTypesJson = discConfigTypesJson + line + ","

  # trim trailing comma
  if discConfigTypesJson != "":
    discConfigTypesJson = discConfigTypesJson[:-1]

  Util.setConfigurationTypes(configurationTypes);

  discoveryRunOnCluster = "false"
  roleName = None;
  containmentpath = "/Cell:" + Util.getCell();
  if resourceJSONObject is not None:
    roleName = resourceJSONObject.getString("roleName");
    roleName = Util.roleNameToType(roleName);
    containmentpath = Util.findContainmentPath(resourceJSONObject);
  else:
    # if we run Discovery from a process step (not the resource tree), there is no fullResourceConfiguration
    # property in the input.props file, and therefore resourceJSONObject is None.
    # So, we need to figure out the containment path and roleName using the resource path.
    #
    # Assume that users may only discover at Cell, Node, Server, and Cluster scope, since those are the
    # only objects available in resource tree after Topology Discovery.

    # get the path of the resource we are running Discovery on
    resourcePath = inputProps.getProperty("resourcePath");
    if resourcePath.find("/Servers/") != -1:
      roleName = "Server";
      # our resource path looks like /TopLevelGroup/Agent/myCellName/Nodes/myNodeName/Servers/myServerName
      # get the node name
      nodeNameStart = resourcePath.find("/Nodes/") + 7;
      nodeNameEnd = resourcePath.find("/Servers/");
      nodeName = resourcePath[nodeNameStart:nodeNameEnd];
      # get the server name
      serverNameStart = resourcePath.find("/Servers/") + 9;
      serverName = resourcePath[serverNameStart:];
      containmentpath = containmentpath + "/Node:" + nodeName + "/Server:" + serverName + "/"
    elif resourcePath.find("/ServerClusters/") != -1:
      discoveryRunOnCluster = "true"
      roleName = "ServerCluster";
      # our resource path looks like /TopLevelGroup/Agent/myCellName/ServerClusters/myClusterName
      # get the cluster name
      clusterNameStart = resourcePath.find("/ServerClusters/") + 16;
      clusterName = resourcePath[clusterNameStart:];
      containmentpath = containmentpath + "/ServerCluster:" + clusterName + "/"
    elif resourcePath.find("/Nodes/") != -1:
      roleName = "Node";
      # our resource path looks like /TopLevelGroup/Agent/myCellName/Nodes/myNodeName
      # get the node name
      nodeNameStart = resourcePath.find("/Nodes/") + 7;
      nodeName = resourcePath[nodeNameStart:];
      containmentpath = containmentpath + "/Node:" + nodeName + "/"
    else:
      roleName = "Cell";
      containmentpath = containmentpath + "/"

  topObjectDir = Util.findObjectDir(roleName, objectsDir);
  finalResources = JSONArray();
  respath = "/"

  index = containmentpath.rindex('/',0,len(containmentpath)-2)+1;
  parentcontainmentpath = containmentpath[0:index];
  if parentcontainmentpath == "/":
    parentcontainmentpath="";
  Log.debug("Initial Containment path %s" % containmentpath);
  if containmentpath != "":
    objid = Util.getid(containmentpath);
  else:
    objid = Util.getid("/Cell:/");
  Log.debug("Fin Containment path %s" % containmentpath);
  Log.debug("Parent Containment path %s" % parentcontainmentpath);
  Log.debug(roleName);
  Log.debug(respath)
  Log.debug(objid)
  limitDiscovery = inputProps.getProperty("limitDiscovery")
  stack = [];
  curresources = Util.exportObjectToResources(stack, objectsDir, topObjectDir, objid, respath, parentcontainmentpath, roleName, limitDiscovery);
  if curresources is not None:
    for y in range(curresources.length()):
      finalResources.put(curresources.get(y));

  # if a cluster, check to see if it's a dynamic cluster.
  # if it is a dynamic cluster, get the dynamic cluster-specific config data
  if discoveryRunOnCluster == "true":
    roleName = "DynamicCluster";
    containmentpath = "/Cell:" + Util.getCell()
    if Util.isValidType("DynamicCluster"):
      containmentpath = containmentpath + "/DynamicCluster:" + clusterName + "/"
      objid = Util.getid(containmentpath);
      if objid is not None and len(objid) > 0:
        topObjectDir = Util.findObjectDir(roleName, objectsDir);
        curresources = Util.exportObjectToResources(stack, objectsDir, topObjectDir, objid, respath, "/Cell:/", roleName, limitDiscovery);
        if curresources is not None:
          for y in range(curresources.length()):
            finalResources.put(curresources.get(y));

  applicableTypes = Util.getApplicableTypes("%s/plugin.xml" % PLUGIN_HOME);
  finalResources = Util.filterExportForTypes(finalResources, applicableTypes, configurationTypes);

  # add the discovered configuration types to json
  if discConfigTypesJson != "":
    Log.logMsg("Specified configuration types to discover: " + str(discConfigTypesJson), Log.LogLevelDebug);
    discConfigTypesJsonObj = JSONObject()
    discConfigTypesJsonObj.put("name", "Specified Configuration Types to Discover");
    discConfigTypesJsonObj.put("path", "/");
    discConfigTypesJsonObj.put("description", ("When the WebSphere Configuration Discovery step was executed, "
      "these values were specified in the WebSphere Configuration Types field. Changing these values may create "
      "configuration problems when running WebSphere Configuration Apply."));
    discConfigTypesJsonObj.put("discoveredConfigurationTypes", discConfigTypesJson);
    finalResources.put(discConfigTypesJsonObj)

  # Write discovered configuration to file
  outFile.write(finalResources.toString(4));

  outFile.close();
  logFile.close();
  redoFile.close();

  print "\nConfiguration Discovery Complete.";

PLUGIN_HOME=os.environ['PLUGIN_HOME'];
objectsDir = "%(plugHome)s%(fileSep)sobjects" % { 'plugHome': PLUGIN_HOME, 'fileSep': os.sep };
sys.path.insert(0,objectsDir);
Util = __import__("utilities.Util").Util;
Log = __import__("WASConfLog.Log").Log;
PluginInputHelper = __import__("PluginInputHelper.PluginInputHelper").PluginInputHelper;

#we put everything possible in a method due to python global versus function scoping.
#repeatadly had issues with name collisions causing refactoring to pick up  a global variable with the same name as a local variable that was removed
try:
  mainmethod();
except: #except on anything, then check if its a java or python exception
  #why in the did jython not handle this gracefully....
  #print the stack here because websphere may decide to just swallow it
  actualExcept = sys.exc_info()[1];
  if isinstance(actualExcept, Throwable):
    actualExcept.printStackTrace();
  traceback.print_exc();
  raise actualExcept;
