class ApplicationsVersionHelper(object):
    _EXTENSION_INDEX = 0
    _SPEC_INDEX = 1
    _IMPL_INDEX = 2

    _APP_VERSION_MANIFEST_KEY = 'Weblogic-Application-Version'

    def __init__(self, model_context, archive_helper):
        self._class_name = 'ApplicationsVersionHelper'
        self.model_context = model_context
        self.archive_helper = archive_helper
        self.logger = PlatformLogger('wlsdeploy.deploy')

    def get_library_versioned_name(self, source_path, model_name, from_archive=False):
        """
        Get the proper name of the deployable library that WLST requires in the target domain.  This method is
        primarily needed for shared libraries in the Oracle Home where the implementation version may have
        changed.  Rather than requiring the modeller to have to know/adjust the shared library name, we extract
        the information from the target domain's archive file (e.g., war file) and compute the correct name.
        :param source_path: the SourcePath value of the shared library
        :param model_name: the model name of the library
        :param from_archive: if True, use the manifest from the archive, otherwise from the file system
        :return: the updated shared library name for the target environment
        :raises: DeployException: if an error occurs
        """
        _method_name = 'get_library_versioned_name'

        self.logger.entering(source_path, model_name, class_name=self._class_name, method_name=_method_name)

        old_name_tuple = deployer_utils.get_library_name_components(model_name)
        try:
            versioned_name = old_name_tuple[self._EXTENSION_INDEX]
            manifest = self.__get_manifest(source_path, from_archive)
            if manifest is not None:
                attributes = manifest.getMainAttributes()

                extension_name = attributes.getValue(EXTENSION_NAME)
                if not string_utils.is_empty(extension_name):
                    versioned_name = extension_name

                specification_version = attributes.getValue(SPECIFICATION_VERSION)
                if not string_utils.is_empty(specification_version):
                    versioned_name += '#' + specification_version

                    # Cannot specify an impl version without a spec version
                    implementation_version = attributes.getValue(IMPLEMENTATION_VERSION)
                    if not string_utils.is_empty(implementation_version):
                        versioned_name += '@' + implementation_version

                self.logger.info('WLSDPLY-09324', model_name, versioned_name,
                                 class_name=self._class_name, method_name=_method_name)

        except (IOException, FileNotFoundException, ZipException, IllegalStateException), e:
            ex = exception_helper.create_deploy_exception('WLSDPLY-09325', model_name, source_path, str(e), error=e)
            self.logger.throwing(ex, class_name=self._class_name, method_name=_method_name)
            raise ex

        self.logger.exiting(class_name=self._class_name, method_name=_method_name, result=versioned_name)
        return versioned_name
示例#2
0
class PythonToYaml(object):
    """
    A class that converts a Python dictionary into Yaml and writes the output to a file.
    """
    _class_name = 'PythonToYaml'
    # 4 spaces
    _indent_unit = '    '
    _requires_quotes_chars_regex = '[:{}\[\],&*#?|<>=!%@`-]'

    def __init__(self, dictionary):
        # Fix error handling for None
        self._dictionary = dictionary
        self._logger = PlatformLogger('wlsdeploy.yaml')
        self._hyphenate_lists = False
        return

    def write_to_yaml_file(self, file_name):
        """
        Convert the Python dictionary to Yaml and write it to the specified file.
        :param file_name: the file name to which to write the Yaml output
        :return: The canonical java.io.File object for the Yaml File
        :raises: YamlException: if an error occurs while converting the dictionary to Yaml or writing to the file
        """
        _method_name = 'writeToYamlFile'

        self._logger.entering(file_name,
                              class_name=self._class_name,
                              method_name=_method_name)
        try:
            yaml_file = JFileUtils.validateWritableFile(file_name)
        except JIllegalArgumentException, iae:
            yaml_ex = exception_helper.create_yaml_exception(
                'WLSDPLY-18009',
                file_name,
                iae.getLocalizedMessage(),
                error=iae)
            self._logger.throwing(class_name=self._class_name,
                                  method_name=_method_name,
                                  error=yaml_ex)
            raise yaml_ex

        fos = None
        writer = None
        try:
            fos = JFileOutputStream(yaml_file, False)
            writer = JPrintWriter(fos, True)
            self._write_dictionary_to_yaml_file(self._dictionary, writer)

        except JFileNotFoundException, fnfe:
            yaml_ex = exception_helper.create_yaml_exception(
                'WLSDPLY-18010',
                file_name,
                fnfe.getLocalizedMessage(),
                error=fnfe)
            self._logger.throwing(class_name=self._class_name,
                                  method_name=_method_name,
                                  error=yaml_ex)
            self._close_streams(fos, writer)
            raise yaml_ex
示例#3
0
class DomainTypedef(object):
    """
    The class that processes domain type definitions.
    """
    __class_name = 'DomainTypedef'

    __domain_typedef_extension = '.json'

    JRF_TEMPLATE_REGEX = "^(.*jrf_template[0-9._]*\\.jar)|(Oracle JRF WebServices Asynchronous services)$"
    RESTRICTED_JRF_TEMPLATE_REGEX = "^(Oracle Restricted JRF)$"
    JRF_SERVER_GROUP = 'JRF-MAN-SVR'

    def __init__(self, program_name, domain_type):
        """
        The DomainTypedef constructor.
        :param program_name: the name of the program create this object
        :param domain_type: the domain type
        """
        _method_name = '__init__'

        self._logger = PlatformLogger('wlsdeploy.create')
        self._program_name = program_name
        self._domain_type = domain_type
        self.wls_helper = WebLogicHelper(self._logger)

        file_name = domain_type + self.__domain_typedef_extension
        self._domain_typedef_filename = path_utils.find_config_path(
            os.path.join('typedefs', file_name))

        # No need to explicitly validate the filename since the JsonToPython constructor does that...
        try:
            json_parser = JsonToPython(self._domain_typedef_filename)
            self._domain_typedefs_dict = json_parser.parse()
        except IllegalArgumentException, iae:
            ex = exception_helper.create_cla_exception(
                'WLSDPLY-12300',
                self._program_name,
                self._domain_type,
                self._domain_typedef_filename,
                iae.getLocalizedMessage(),
                error=iae)
            ex.setExitCode(CommandLineArgUtil.ARG_VALIDATION_ERROR_EXIT_CODE)
            self._logger.throwing(ex,
                                  class_name=self.__class_name,
                                  method_name=_method_name)
            raise ex
        except JsonException, je:
            ex = exception_helper.create_cla_exception(
                'WLSDPLY-12301',
                self._program_name,
                self._domain_type,
                self._domain_typedef_filename,
                je.getLocalizedMessage(),
                error=je)
            ex.setExitCode(CommandLineArgUtil.ARG_VALIDATION_ERROR_EXIT_CODE)
            self._logger.throwing(ex,
                                  class_name=self.__class_name,
                                  method_name=_method_name)
            raise ex
class DomainTypedef(object):
    """
    The class that processes domain type definitions.
    """
    __class_name = 'DomainTypedef'

    __domain_typedefs_location = os.path.join(os.environ.get('WLSDEPLOY_HOME'),
                                              'lib', 'typedefs')
    __domain_typedef_extension = '.json'

    __wild_card_suffix = '%%'
    __wild_card_suffix_len = len(__wild_card_suffix)

    def __init__(self, program_name, domain_type):
        """
        The DomainTypedef constructor.
        :param program_name: the name of the program create this object
        :param domain_type: the domain type
        """
        _method_name = '__init__'

        self._logger = PlatformLogger('wlsdeploy.create')
        self._program_name = program_name
        self._domain_type = domain_type
        self.wls_helper = WebLogicHelper(self._logger)

        self._domain_typedef_filename = \
            os.path.join(self.__domain_typedefs_location, domain_type + self.__domain_typedef_extension)
        # No need to explicitly validate the filename since the JsonToPython constructor does that...
        try:
            json_parser = JsonToPython(self._domain_typedef_filename)
            self._domain_typedefs_dict = json_parser.parse()
        except IllegalArgumentException, iae:
            ex = exception_helper.create_cla_exception(
                'WLSDPLY-12300',
                self._program_name,
                self._domain_type,
                self._domain_typedef_filename,
                iae.getLocalizedMessage(),
                error=iae)
            ex.setExitCode(CommandLineArgUtil.ARG_VALIDATION_ERROR_EXIT_CODE)
            self._logger.throwing(ex,
                                  class_name=self.__class_name,
                                  method_name=_method_name)
            raise ex
        except JsonException, je:
            ex = exception_helper.create_cla_exception(
                'WLSDPLY-12301',
                self._program_name,
                self._domain_type,
                self._domain_typedef_filename,
                je.getLocalizedMessage(),
                error=je)
            ex.setExitCode(CommandLineArgUtil.ARG_VALIDATION_ERROR_EXIT_CODE)
            self._logger.throwing(ex,
                                  class_name=self.__class_name,
                                  method_name=_method_name)
            raise ex
示例#5
0
class PythonToJson(object):
    """
    This class writes a Python dictionary out in a JSON format.
    """
    _class_name = 'PythonToJson'
    # 4 spaces of indent
    _indent_unit = '    '

    def __init__(self, dictionary):
        # Fix error handling for None
        self._dictionary = dictionary
        self._logger = PlatformLogger('wlsdeploy.json')
        return

    def write_to_json_file(self, file_name):
        """
        Convert the Python dictionary to JSON and write it to the specified file.
        :param file_name:  the name of the file
        :return: the java.io.File object of the JSON file
        """
        _method_name = 'writeToJsonFile'

        self._logger.entering(file_name,
                              class_name=self._class_name,
                              method_name=_method_name)
        try:
            json_file = JFileUtils.validateWritableFile(file_name)
        except JIllegalArgumentException, iae:
            json_ex = exception_helper.create_json_exception(
                'WLSDPLY-18015',
                file_name,
                iae.getLocalizedMessage(),
                error=iae)
            self._logger.throwing(class_name=self._class_name,
                                  method_name=_method_name,
                                  error=json_ex)
            raise json_ex

        fos = None
        writer = None
        try:
            fos = JFileOutputStream(json_file, False)
            writer = JPrintWriter(fos, True)
            self._write_dictionary_to_json_file(self._dictionary, writer)

        except JFileNotFoundException, fnfe:
            json_ex = exception_helper.create_json_exception(
                'WLSDPLY-18010',
                file_name,
                fnfe.getLocalizedMessage(),
                error=fnfe)
            self._logger.throwing(class_name=self._class_name,
                                  method_name=_method_name,
                                  error=json_ex)
            self._close_streams(fos, writer)
            raise json_ex
示例#6
0
class JsonToPython(object):
    """
    This class turns JSON file into an equivalent Python dictionary.
    """
    _class_name = 'JsonToPython'

    def __init__(self, file_name, use_ordering=False):
        _method_name = '__init__'

        self._file_name = file_name
        self._logger = PlatformLogger('wlsdeploy.json')
        try:
            self._translator = JJsonTranslator(file_name, use_ordering)
        except JIllegalArgumentException, iae:
            json_ex = \
                exception_helper.create_json_exception('WLSDPLY-18014', file_name, iae.getLocalizedMessage(), error=iae)
            self._logger.throwing(class_name=self._class_name, method_name=_method_name, error=json_ex)
            raise json_ex
        return
class YamlStreamToPython(object):
    """
    A class that translates a YAML input stream into a python dictionary.
    """
    _class_name = 'YamlStreamToPython'

    def __init__(self, file_name, input_stream, use_ordering=False):
        _method_name = '__init__'

        self._file_name = file_name
        self._use_ordering = use_ordering
        self._logger = PlatformLogger('wlsdeploy.yaml')
        try:
            self._translator = JYamlStreamTranslator(self._file_name, input_stream, self._use_ordering)
        except JIllegalArgumentException, iae:
            yaml_ex = \
                exception_helper.create_yaml_exception('WLSDPLY-18008', file_name, iae.getLocalizedMessage(), error=iae)
            self._logger.throwing(class_name=self._class_name, method_name=_method_name, error=yaml_ex)
            raise yaml_ex
        return
                _program_name,
                model_file_name,
                iae.getLocalizedMessage(),
                error=iae)
            ex.setExitCode(CommandLineArgUtil.ARG_VALIDATION_ERROR_EXIT_CODE)
            __logger.throwing(ex,
                              class_name=_class_name,
                              method_name=_method_name)
            raise ex
    elif CommandLineArgUtil.ENCRYPT_MANUAL_SWITCH not in optional_arg_map:
        ex = exception_helper.create_cla_exception(
            'WLSDPLY-04202', _program_name,
            CommandLineArgUtil.MODEL_FILE_SWITCH,
            CommandLineArgUtil.ENCRYPT_MANUAL_SWITCH)
        ex.setExitCode(CommandLineArgUtil.USAGE_ERROR_EXIT_CODE)
        __logger.throwing(ex, class_name=_class_name, method_name=_method_name)
        raise ex
    return


def __process_passphrase_arg(optional_arg_map):
    """
    Prompt for the passphrase.
    :param optional_arg_map: the optional arguments map
    :raises CLAException: if an error occurs reading the passphrase input from the user
    """
    _method_name = '__process_passphrase_arg'

    if CommandLineArgUtil.PASSPHRASE_SWITCH not in optional_arg_map:
        got_matching_passphrases = False
        while not got_matching_passphrases:
class Deployer(object):
    """
    The base class for deployers.
    Maintains model, model context, WLST mode, etc.
    Has common methods for deployers.
    """
    _class_name = "Deployer"

    _mbean_interface = Class.forName('weblogic.management.configuration.ConfigurationMBean')
    _object_name_class = Class.forName('javax.management.ObjectName')
    _list_interface = Class.forName('java.util.List')

    def __init__(self, model, model_context, aliases, wlst_mode=WlstModes.OFFLINE):
        self.name = self._class_name
        self.model = model
        self.wlst_mode = wlst_mode
        self.model_context = model_context
        self.aliases = aliases
        self.logger = PlatformLogger('wlsdeploy.deploy')
        self.alias_helper = AliasHelper(aliases, self.logger, ExceptionType.DEPLOY)
        self.wls_helper = WebLogicHelper(self.logger)
        self.wlst_helper = WlstHelper(self.logger, ExceptionType.DEPLOY)
        self.attribute_setter = AttributeSetter(self.aliases, self.logger, ExceptionType.DEPLOY, wlst_mode=wlst_mode)

        self.archive_helper = None
        archive_file_name = self.model_context.get_archive_file_name()
        if archive_file_name is not None:
            self.archive_helper = ArchiveHelper(archive_file_name, self.model_context.get_domain_home(), self.logger,
                                                exception_helper.ExceptionType.DEPLOY)
        return

    def _add_named_elements(self, type_name, model_nodes, location):
        """
        Add each named element from the specified nodes in WLST and set its attributes.
        Sub-folders are processed in a generic manner if present.
        It is assumed that there are no attributes or sub-folders with special processing.
        :param type_name: the type name of the child nodes
        :param model_nodes: the child nodes of a model element
        :param location: the location where elements should be added
        """
        _method_name = '_add_named_elements'

        if len(model_nodes) == 0:
            return

        parent_type, parent_name = self.get_location_type_and_name(location)
        location = LocationContext(location).append_location(type_name)
        if not self._check_location(location):
            return

        deployer_utils.check_flattened_folder(location, self.alias_helper)
        existing_names = deployer_utils.get_existing_object_list(location, self.alias_helper)

        token = self.alias_helper.get_name_token(location)
        for name in model_nodes:
            is_add = name not in existing_names
            log_helper.log_updating_named_folder(type_name, name, parent_type, parent_name, is_add, self._class_name,
                                                 _method_name)

            if token is not None:
                location.add_name_token(token, name)
            deployer_utils.create_and_cd(location, existing_names, self.alias_helper)

            child_nodes = dictionary_utils.get_dictionary_element(model_nodes, name)
            self._set_attributes_and_add_subfolders(location, child_nodes)
        return

    def _add_subfolders(self, model_nodes, location, excludes=None):
        """
        Add each model sub-folder from the specified nodes and set its attributes.
        :param model_nodes: the child nodes of a model element
        :param location: the location where sub-folders should be added
        :param excludes: optional list of sub-folder names to be excluded from processing
        """
        location = LocationContext(location)
        model_subfolder_names = self.alias_helper.get_model_subfolder_names(location)

        for subfolder in model_nodes:
            key_excluded = (excludes is not None) and (subfolder in excludes)
            if subfolder in model_subfolder_names and not key_excluded:
                subfolder_nodes = model_nodes[subfolder]
                if len(subfolder_nodes) != 0:
                    sub_location = LocationContext(location).append_location(subfolder)
                    if self.alias_helper.supports_multiple_mbean_instances(sub_location):
                        self._add_named_elements(subfolder, subfolder_nodes, location)
                    else:
                        self._add_model_elements(subfolder, subfolder_nodes, location)
        return

    def _add_model_elements(self, type_name, model_nodes, location):
        """
        Add each model element from the specified nodes at the specified location and set its attributes.
        :param model_nodes: the child nodes of a model element
        :param location: the location where sub-folders should be added
        :param type_name: the name of the model folder to add
        """
        _method_name = '_add_model_elements'

        parent_type, parent_name = self.get_location_type_and_name(location)
        location = LocationContext(location).append_location(type_name)
        if not self._check_location(location):
            return

        deployer_utils.check_flattened_folder(location, self.alias_helper)
        existing_subfolder_names = deployer_utils.get_existing_object_list(location, self.alias_helper)

        mbean_name = deployer_utils.get_mbean_name(location, existing_subfolder_names, self.alias_helper)
        is_add = mbean_name not in existing_subfolder_names
        log_helper.log_updating_folder(type_name, parent_type, parent_name, is_add, self._class_name, _method_name)

        deployer_utils.create_and_cd(location, existing_subfolder_names, self.alias_helper)

        self._set_attributes_and_add_subfolders(location, model_nodes)
        return

    def _set_attributes_and_add_subfolders(self, location, model_nodes):
        """
        Set the attributes and add sub-folders for the specified location.
        This method can be overridden for finer control of the ordering
        :param location: the location of the attributes and sub-folders
        :param model_nodes: a map of model nodes including attributes and sub-folders
        :raise: DeployException: if an error condition is encountered
        """
        self.set_attributes(location, model_nodes)
        self._add_subfolders(model_nodes, location)
        return

    def set_attributes(self, location, model_nodes, excludes=None):
        """
        Set all the attributes in the model_nodes list. Exclude items that are sub-folders.
        :param location: the location of the attributes to be set
        :param model_nodes: a map of model nodes with attributes to be set
        :param excludes: a list of items that should not be set
        :raise: DeployException: if an error condition is encountered
        """
        _method_name = 'set_attributes'
        attribute_names = self.alias_helper.get_model_attribute_names(location)
        uses_path_tokens_attribute_names = self.alias_helper.get_model_uses_path_tokens_attribute_names(location)
        restart_attribute_names = self.alias_helper.get_model_restart_required_attribute_names(location)
        merge_attribute_names = self.alias_helper.get_model_merge_required_attribute_names(location)
        lsa_required_attribute_names = self.aliases.get_model_lsa_required_attribute_names(location)
        set_method_map = self.alias_helper.get_model_mbean_set_method_attribute_names_and_types(location)

        for key in model_nodes:
            key_excluded = (excludes is not None) and (key in excludes)
            if key in attribute_names and not key_excluded:
                value = model_nodes[key]
                if key in uses_path_tokens_attribute_names:
                    self._extract_from_archive_if_needed(location, key, value)

                wlst_merge_value = None
                if key in merge_attribute_names:
                    wlst_merge_value = self._get_existing_wlst_value(location, key, lsa_required_attribute_names)

                if not self._skip_setting_attribute(key, value, wlst_merge_value, restart_attribute_names) and \
                        (not self.set_special_attribute(location, key, value, wlst_merge_value, set_method_map)):
                    try:
                        self.attribute_setter.set_attribute(location, key, value, wlst_merge_value)
                    except PyWLSTException, pwe:
                        loc_type, loc_name = self.get_location_type_and_name(location)
                        ex = exception_helper.create_deploy_exception('WLSDPLY-09200', key, loc_type, loc_name,
                                                                      pwe.getLocalizedMessage(), error=pwe)
                        self.logger.throwing(ex, class_name=self._class_name, method_name=_method_name)
                        raise ex
        return
示例#10
0
        new_name = None
        try:
            6
        except IllegalArgumentException, iae:
            _logger.warning('WLSDPLY-06624',
                            server_name,
                            file_path,
                            iae.getLocalizedMessage(),
                            class_name=_class_name,
                            method_name=_method_name)
        except WLSDeployArchiveIOException, wioe:
            de = exception_helper.create_discover_exception(
                'WLSDPLY-06625', server_name, file_path,
                wioe.getLocalizedMessage())
            _logger.throwing(class_name=_class_name,
                             method_name=_method_name,
                             error=de)
            raise de
        _logger.exiting(class_name=_class_name,
                        method_name=_method_name,
                        result=new_name)
        return new_name

    def _get_server_name_from_location(self, location):
        """
        Retrieve the server name from the location context file.
        :param location: context containing the server information
        :return: server name
        """
        temp = LocationContext()
        temp.append_location(model_constants.SERVER)
示例#11
0
class CommandLineArgUtil(object):
    """
    Class that handles command-line argument parsing and common validation.
    """
    _class_name = 'CommandLineArgUtil'

    HELP_SWITCH = '-help'
    ORACLE_HOME_SWITCH = '-oracle_home'
    JAVA_HOME_SWITCH = '-java_home'
    DOMAIN_HOME_SWITCH = '-domain_home'
    DOMAIN_PARENT_SWITCH = '-domain_parent'
    DOMAIN_TYPE_SWITCH = '-domain_type'
    # never used by the tools but used by shell scripts
    WLST_PATH_SWITCH = '-wlst_path'
    ADMIN_URL_SWITCH = '-admin_url'
    ADMIN_USER_SWITCH = '-admin_user'
    # phony arg used as a key to store the password
    ADMIN_PASS_SWITCH = '-admin_pass'
    ARCHIVE_FILE_SWITCH = '-archive_file'
    MODEL_FILE_SWITCH = '-model_file'
    PREVIOUS_MODEL_FILE_SWITCH = '-prev_model_file'
    VARIABLE_FILE_SWITCH = '-variable_file'
    PRINT_USAGE_SWITCH = '-print_usage'
    RCU_DB_SWITCH = '-rcu_db'
    RCU_PREFIX_SWITCH = '-rcu_prefix'
    # phony arg used as a key to store the password
    RCU_SYS_PASS_SWITCH = '-rcu_sys_pass'
    # phony arg used as a key to store the password
    RCU_SCHEMA_PASS_SWITCH = '-rcu_schema_pass'
    # phony arg used as a key to store the encryption passphrase
    PASSPHRASE_SWITCH = '-passphrase'
    ENCRYPT_MANUAL_SWITCH = '-manual'
    # phony arg used as a key to store the password
    ONE_PASS_SWITCH = '-password'
    USE_ENCRYPTION_SWITCH = '-use_encryption'
    RUN_RCU_SWITCH = '-run_rcu'
    TARGET_VERSION_SWITCH = '-target_version'
    TARGET_MODE_SWITCH = '-target_mode'
    ATTRIBUTES_ONLY_SWITCH = '-attributes_only'
    FOLDERS_ONLY_SWITCH = '-folders_only'
    RECURSIVE_SWITCH = '-recursive'
    # overrides for the variable injector
    VARIABLE_INJECTOR_FILE_SWITCH = '-variable_injector_file'
    VARIABLE_KEYWORDS_FILE_SWITCH = '-variable_keywords_file'
    VARIABLE_PROPERTIES_FILE_SWITCH = '-variable_properties_file'

    # a slot to stash the parsed domain typedef dictionary
    DOMAIN_TYPEDEF = 'domain_typedef'
    # a slot to stash the archive file object
    ARCHIVE_FILE = 'archive_file'

    HELP_EXIT_CODE = 100
    USAGE_ERROR_EXIT_CODE = 99
    ARG_VALIDATION_ERROR_EXIT_CODE = 98
    PROG_ERROR_EXIT_CODE = 2
    PROG_WARNING_EXIT_CODE = 1
    PROG_OK_EXIT_CODE = 0

    def __init__(self, program_name, required_args, optional_args):
        self._program_name = program_name
        self._logger = PlatformLogger('wlsdeploy.util')

        self._required_args = list(required_args)
        self._optional_args = list(optional_args)

        #
        # Add args that all tools should accept.
        #
        self._optional_args.append(self.HELP_SWITCH)
        self._optional_args.append(self.WLST_PATH_SWITCH)

        self._required_result = {}
        self._optional_result = {}
        return

    def process_args(self, args, for_domain_create=False):
        """
        This method parses the command-line arguments and returns dictionaries of the required and optional args.

        :param args: sys.argv
        :param for_domain_create: true if validating for domain creation
        :return: the required and optional argument dictionaries
        :raises CLAException: if argument processing encounters a usage or validation exception
        """

        method_name = 'process_args'

        self._logger.entering(args,
                              class_name=self._class_name,
                              method_name=method_name)
        #
        # reset the result fields in case the object was reused
        #
        self._required_result = {}
        self._optional_result = {}

        args_len = len(args)
        if args_len == 1:
            ex = exception_helper.create_cla_exception('Dummy Key')
            ex.setExitCode(self.HELP_EXIT_CODE)
            raise ex

        idx = 1
        while idx < args_len:
            key = args[idx]
            self._logger.fine('WLSDPLY-01600',
                              key,
                              class_name=self._class_name,
                              method_name=method_name)
            if self.is_help_key(key):
                ex = exception_helper.create_cla_exception('Dummy Key')
                ex.setExitCode(self.HELP_EXIT_CODE)
                raise ex
            elif self.is_oracle_home_key(key):
                idx += 1
                if idx < args_len:
                    full_path = self._validate_oracle_home_arg(args[idx])
                    self._add_arg(key, full_path, True)
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_java_home_key(key):
                idx += 1
                if idx < args_len:
                    full_path = self._validate_java_home_arg(args[idx])
                    self._add_arg(key, full_path, True)
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_domain_home_key(key):
                idx += 1
                if idx < args_len:
                    if for_domain_create:
                        full_path = self._validate_domain_home_arg_for_create(
                            args[idx])
                    else:
                        full_path = self._validate_domain_home_arg(args[idx])
                    self._add_arg(key, full_path, True)
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_domain_parent_key(key):
                idx += 1
                if idx < args_len:
                    full_path = self._validate_domain_parent_arg(args[idx])
                    self._add_arg(key, full_path, True)
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_domain_type_key(key):
                idx += 1
                if idx < args_len:
                    self._validate_domain_type_arg(args[idx])
                    self._add_arg(key, args[idx])
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_wlst_path_key(key):
                idx += 1
                if idx < args_len:
                    full_path = self._validate_wlst_path_arg(args[idx])
                    self._add_arg(key, full_path, True)
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_admin_url_key(key):
                idx += 1
                if idx < args_len:
                    self._validate_admin_url_arg(args[idx])
                    self._add_arg(key, args[idx])
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_admin_user_key(key):
                idx += 1
                if idx < args_len:
                    self._validate_admin_user_arg(args[idx])
                    self._add_arg(key, args[idx])
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_admin_pass_key(key):
                idx += 1
                if idx < args_len:
                    self._validate_admin_pass_arg(args[idx])
                    self._add_arg(key, args[idx])
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_archive_file_key(key):
                idx += 1
                if idx < args_len:
                    full_path = self._validate_archive_file_arg(args[idx])
                    self._add_arg(key, full_path, True)
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_model_file_key(key):
                idx += 1
                if idx < args_len:
                    full_path = self._validate_model_file_arg(args[idx])
                    self._add_arg(key, full_path, True)
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_previous_model_file_key(key):
                idx += 1
                if idx < args_len:
                    full_path = self._validate_previous_model_file_arg(
                        args[idx])
                    self._add_arg(key, full_path, True)
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_print_usage_key(key):
                idx += 1
                if idx < args_len:
                    context = self._validate_print_usage_arg(args[idx])
                    self._add_arg(key, context)
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_variable_file_key(key):
                idx += 1
                if idx < args_len:
                    full_path = self._validate_variable_file_arg(args[idx])
                    self._add_arg(key, full_path, True)
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_rcu_database_key(key):
                idx += 1
                if idx < args_len:
                    self._validate_rcu_database_arg(args[idx])
                    self._add_arg(key, args[idx])
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_rcu_prefix_key(key):
                idx += 1
                if idx < args_len:
                    self._validate_rcu_prefix_arg(args[idx])
                    self._add_arg(key, args[idx])
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_rcu_sys_pass_key(key):
                idx += 1
                if idx < args_len:
                    self._validate_rcu_sys_pass_arg(args[idx])
                    self._add_arg(key, args[idx])
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_rcu_schema_pass_key(key):
                idx += 1
                if idx < args_len:
                    self._validate_rcu_schema_pass_arg(args[idx])
                    self._add_arg(key, args[idx])
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_passphrase_switch(key):
                idx += 1
                if idx < args_len:
                    self._validate_passphrase_arg(args[idx])
                    self._add_arg(key, args[idx])
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_encrypt_manual_switch(key):
                self._add_arg(key, True)
            elif self.is_one_pass_switch(key):
                idx += 1
                if idx < args_len:
                    self._validate_one_pass_arg(args[idx])
                    self._add_arg(key, args[idx])
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_use_encryption_switch(key):
                self._add_arg(key, True)
            elif self.is_run_rcu_switch(key):
                self._add_arg(key, True)
            elif self.is_target_version_switch(key):
                idx += 1
                if idx < args_len:
                    self._validate_target_version_arg(args[idx])
                    self._add_arg(key, args[idx])
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_target_mode_switch(key):
                idx += 1
                if idx < args_len:
                    self._validate_target_mode_arg(args[idx])
                    self._add_arg(key, args[idx])
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_attributes_only_switch(key):
                self._add_arg(key, True)
            elif self.is_folders_only_switch(key):
                self._add_arg(key, True)
            elif self.is_recursive_switch(key):
                self._add_arg(key, True)
            elif self.is_variable_injector_file_key(key):
                idx += 1
                if idx < args_len:
                    full_path = self._validate_variable_injector_file_arg(
                        args[idx])
                    self._add_arg(key, full_path, True)
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_variable_keywords_file_key(key):
                idx += 1
                if idx < args_len:
                    full_path = self._validate_variable_keywords_file_arg(
                        args[idx])
                    self._add_arg(key, full_path, True)
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            elif self.is_variable_properties_file_key(key):
                idx += 1
                if idx < args_len:
                    full_path = self._validate_variable_properties_file_arg(
                        args[idx])
                    self._add_arg(key, full_path, True)
                else:
                    ex = self._get_out_of_args_exception(key)
                    self._logger.throwing(ex,
                                          class_name=self._class_name,
                                          method_name=method_name)
                    raise ex
            else:
                ex = exception_helper.create_cla_exception(
                    'WLSDPLY-01601', self._program_name, key)
                ex.setExitCode(self.USAGE_ERROR_EXIT_CODE)
                self._logger.throwing(ex,
                                      class_name=self._class_name,
                                      method_name=method_name)
                raise ex
            idx += 1

        print_result = {
            'required': self._required_result,
            'optional': self._optional_result
        }
        self._logger.exiting(class_name=self._class_name,
                             method_name=method_name,
                             result=print_result)
        return self._required_result, self._optional_result

    def get_help_key(self):
        return self.HELP_SWITCH

    def is_help_key(self, key):
        return self.HELP_SWITCH == key

    def get_oracle_home_key(self):
        return str(self.ORACLE_HOME_SWITCH)

    def is_oracle_home_key(self, key):
        return self.ORACLE_HOME_SWITCH == key

    def _validate_oracle_home_arg(self, value):
        method_name = '_validate_oracle_home_arg'

        try:
            oh = JFileUtils.validateExistingDirectory(value)
        except JIllegalArgumentException, iae:
            ex = exception_helper.create_cla_exception(
                'WLSDPLY-01602', value, iae.getLocalizedMessage(), error=iae)
            ex.setExitCode(self.ARG_VALIDATION_ERROR_EXIT_CODE)
            self._logger.throwing(ex,
                                  class_name=self._class_name,
                                  method_name=method_name)
            raise ex

        oh_name = oh.getAbsolutePath()
        wl_helper = WebLogicHelper(self._logger)
        wl_home_name = wl_helper.get_weblogic_home(oh_name)
        try:
            JFileUtils.validateExistingDirectory(wl_home_name)
        except JIllegalArgumentException, iae:
            ex = exception_helper.create_cla_exception(
                'WLSDPLY-01603',
                wl_home_name,
                iae.getLocalizedMessage(),
                error=iae)
            ex.setExitCode(self.ARG_VALIDATION_ERROR_EXIT_CODE)
            self._logger.throwing(ex,
                                  class_name=self._class_name,
                                  method_name=method_name)
            raise ex
示例#12
0
class CommandLineArgUtil(object):
    """
    Class that handles command-line argument parsing and common validation.
    """
    _class_name = 'CommandLineArgUtil'

    HELP_SWITCH = '-help'
    ORACLE_HOME_SWITCH = '-oracle_home'
    JAVA_HOME_SWITCH = '-java_home'
    DOMAIN_HOME_SWITCH = '-domain_home'
    DOMAIN_PARENT_SWITCH = '-domain_parent'
    DOMAIN_TYPE_SWITCH = '-domain_type'
    # never used by the tools but used by shell scripts
    WLST_PATH_SWITCH = '-wlst_path'
    ADMIN_URL_SWITCH = '-admin_url'
    ADMIN_USER_SWITCH = '-admin_user'
    # phony arg used as a key to store the password
    ADMIN_PASS_SWITCH = '-admin_pass'
    ARCHIVE_FILE_SWITCH = '-archive_file'
    MODEL_FILE_SWITCH = '-model_file'
    OPSS_WALLET_SWITCH = '-opss_wallet'
    OPSS_WALLET_PASSPHRASE = '-opss_wallet_passphrase'
    PREVIOUS_MODEL_FILE_SWITCH = '-prev_model_file'
    VARIABLE_FILE_SWITCH = '-variable_file'
    RCU_DB_SWITCH = '-rcu_db'
    RCU_PREFIX_SWITCH = '-rcu_prefix'
    # phony arg used as a key to store the password
    RCU_SYS_PASS_SWITCH = '-rcu_sys_pass'
    # phony arg used as a key to store the password
    RCU_SCHEMA_PASS_SWITCH = '-rcu_schema_pass'
    # phony arg used as a key to store the encryption passphrase
    PASSPHRASE_SWITCH = '-passphrase'
    ENCRYPT_MANUAL_SWITCH = '-manual'
    # phony arg used as a key to store the password
    ONE_PASS_SWITCH = '-password'
    ROLLBACK_IF_RESTART_REQ_SWITCH = '-rollback_if_require_restart'
    USE_ENCRYPTION_SWITCH = '-use_encryption'
    RUN_RCU_SWITCH = '-run_rcu'
    TARGET_VERSION_SWITCH = '-target_version'
    TARGET_MODE_SWITCH = '-target_mode'
    # phony arg used as a key to store the trailing (non-switched) arguments
    TRAILING_ARGS_SWITCH = '-trailing_arguments'
    ATTRIBUTES_ONLY_SWITCH = '-attributes_only'
    FOLDERS_ONLY_SWITCH = '-folders_only'
    MODEL_SAMPLE_SWITCH = '-model_sample'
    RECURSIVE_SWITCH = '-recursive'
    UPDATE_RCU_SCHEMA_PASS_SWITCH = '-updateRCUSchemaPassword'
    VALIDATION_METHOD = '-method'
    # overrides for the variable injector
    VARIABLE_INJECTOR_FILE_SWITCH = '-variable_injector_file'
    VARIABLE_KEYWORDS_FILE_SWITCH = '-variable_keywords_file'
    VARIABLE_PROPERTIES_FILE_SWITCH = '-variable_properties_file'
    # extractDomainResource output file
    DOMAIN_RESOURCE_FILE_SWITCH = '-domain_resource_file'
    COMPARE_MODEL_OUTPUT_DIR_SWITCH = "-output_dir"

    # arguments that are true if specified, false if not
    BOOLEAN_SWITCHES = [
        ATTRIBUTES_ONLY_SWITCH, ENCRYPT_MANUAL_SWITCH, FOLDERS_ONLY_SWITCH,
        MODEL_SAMPLE_SWITCH, RECURSIVE_SWITCH, ROLLBACK_IF_RESTART_REQ_SWITCH,
        RUN_RCU_SWITCH, UPDATE_RCU_SCHEMA_PASS_SWITCH, USE_ENCRYPTION_SWITCH
    ]

    # a slot to stash the parsed domain typedef dictionary
    DOMAIN_TYPEDEF = 'domain_typedef'
    # a slot to stash the archive file object
    ARCHIVE_FILE = 'archive_file'

    ARCHIVE_FILES_SEPARATOR = ','
    MODEL_FILES_SEPARATOR = ','

    HELP_EXIT_CODE = 100
    USAGE_ERROR_EXIT_CODE = 99
    ARG_VALIDATION_ERROR_EXIT_CODE = 98
    PROG_RESTART_REQUIRED = 103
    PROG_ROLLBACK_IF_RESTART_EXIT_CODE = 104
    PROG_ERROR_EXIT_CODE = 2
    PROG_WARNING_EXIT_CODE = 1
    PROG_OK_EXIT_CODE = 0

    def __init__(self, program_name, required_args, optional_args):
        self._program_name = program_name
        self._logger = PlatformLogger('wlsdeploy.util')

        self._required_args = list(required_args)
        self._optional_args = list(optional_args)
        self._allow_multiple_models = False

        #
        # Add args that all tools should accept.
        #
        self._optional_args.append(self.HELP_SWITCH)
        self._optional_args.append(self.WLST_PATH_SWITCH)

        self._required_result = {}
        self._optional_result = {}
        return

    def set_allow_multiple_models(self, allow_multiple_models):
        """
        This method determines if this instance allows multiple models to be specified for the MODEL_FILE_SWITCH
        argument. By default, multiple models are not allowed.
        :param allow_multiple_models: the flag indicating if multiple models are allowed
        """
        self._allow_multiple_models = allow_multiple_models

    def process_args(self,
                     args,
                     tool_type=TOOL_TYPE_DEFAULT,
                     trailing_arg_count=0):
        """
        This method parses the command-line arguments and returns dictionaries of the required and optional args.

        :param args: sys.argv
        :param tool_type: optional, type of tool for special argument processing
        :param trailing_arg_count: optional, the number of trailing (no switch) arguments
        :return: the required and optional argument dictionaries
        :raises CLAException: if argument processing encounters a usage or validation exception
        """

        method_name = 'process_args'

        self._logger.entering(args,
                              class_name=self._class_name,
                              method_name=method_name)
        #
        # reset the result fields in case the object was reused
        #
        self._required_result = {}
        self._optional_result = {}

        args_len = len(args)
        if args_len == 1:
            ex = exception_helper.create_cla_exception('Dummy Key')
            ex.setExitCode(self.HELP_EXIT_CODE)
            raise ex

        args = self._check_trailing_arguments(args, trailing_arg_count)
        args_len = len(args)

        idx = 1
        while idx < args_len:
            key = args[idx]
            self._logger.fine('WLSDPLY-01600',
                              key,
                              class_name=self._class_name,
                              method_name=method_name)
            if self.is_help_key(key):
                ex = exception_helper.create_cla_exception('Dummy Key')
                ex.setExitCode(self.HELP_EXIT_CODE)
                raise ex
            elif self.is_oracle_home_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                full_path = self._validate_oracle_home_arg(value)
                self._add_arg(key, full_path, True)
            elif self.is_java_home_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                full_path = self._validate_java_home_arg(value)
                self._add_arg(key, full_path, True)
            elif self.is_domain_home_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                if tool_type == TOOL_TYPE_CREATE:
                    full_path = self._validate_domain_home_arg_for_create(
                        value)
                elif tool_type == TOOL_TYPE_EXTRACT:
                    full_path = self._validate_domain_home_arg_for_extract(
                        value)
                else:
                    full_path = self._validate_domain_home_arg(value)
                self._add_arg(key, full_path, True)
            elif self.is_domain_parent_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                full_path = self._validate_domain_parent_arg(value)
                self._add_arg(key, full_path, True)
            elif self.is_domain_type_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                self._validate_domain_type_arg(value)
                self._add_arg(key, value)
            elif self.is_wlst_path_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                full_path = self._validate_wlst_path_arg(value)
                self._add_arg(key, full_path, True)
            elif self.is_admin_url_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                self._validate_admin_url_arg(value)
                self._add_arg(key, value)
            elif self.is_admin_user_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                self._validate_admin_user_arg(value)
                self._add_arg(key, value)
            elif self.is_admin_pass_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                self._validate_admin_pass_arg(value)
                self._add_arg(key, value)
            elif self.is_archive_file_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                full_path = self._validate_archive_file_arg(value)
                self._add_arg(key, full_path, True)
            elif self.is_opss_passphrase_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                self._validate_opss_passphrase_arg(value)
                self._add_arg(key, value)
            elif self.is_opss_wallet_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                full_path = self._validate_opss_wallet_arg(value)
                self._add_arg(key, full_path, True)
            elif self.is_model_file_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                full_path = self._validate_model_file_arg(value)
                self._add_arg(key, full_path, True)
            elif self.is_previous_model_file_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                full_path = self._validate_previous_model_file_arg(value)
                self._add_arg(key, full_path, True)
            elif self.is_validate_method_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                context = self._validate_validate_method_arg(value)
                self._add_arg(key, context)
            elif self.is_variable_file_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                self._add_arg(key, value, True)
            elif self.is_rcu_database_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                self._validate_rcu_database_arg(value)
                self._add_arg(key, value)
            elif self.is_rcu_prefix_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                self._validate_rcu_prefix_arg(value)
                self._add_arg(key, value)
            elif self.is_rcu_sys_pass_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                self._validate_rcu_sys_pass_arg(value)
                self._add_arg(key, value)
            elif self.is_rcu_schema_pass_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                self._validate_rcu_schema_pass_arg(value)
                self._add_arg(key, value)
            elif self.is_passphrase_switch(key):
                value, idx = self._get_arg_value(args, idx, key)
                self._validate_passphrase_arg(value)
                self._add_arg(key, value)
            elif self.is_one_pass_switch(key):
                value, idx = self._get_arg_value(args, idx, key)
                self._validate_one_pass_arg(value)
                self._add_arg(key, value)
            elif self.is_target_version_switch(key):
                value, idx = self._get_arg_value(args, idx, key)
                self._validate_target_version_arg(value)
                self._add_arg(key, value)
            elif self.is_target_mode_switch(key):
                value, idx = self._get_arg_value(args, idx, key)
                self._validate_target_mode_arg(value)
                self._add_arg(key, value)
            elif self.is_variable_injector_file_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                full_path = self._validate_variable_injector_file_arg(value)
                self._add_arg(key, full_path, True)
            elif self.is_variable_keywords_file_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                full_path = self._validate_variable_keywords_file_arg(value)
                self._add_arg(key, full_path, True)
            elif self.is_variable_properties_file_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                full_path = self._validate_variable_properties_file_arg(value)
                self._add_arg(key, full_path, True)
            elif self.is_domain_resource_file_key(key):
                value, idx = self._get_arg_value(args, idx, key)
                full_path = self._validate_domain_resource_file_arg(value)
                self._add_arg(key, full_path, True)
            elif self.is_boolean_switch(key):
                self._add_arg(key, True)
            elif self.is_compare_model_output_dir_switch(key):
                value, idx = self._get_arg_value(args, idx, key)
                full_path = self._validate_compare_model_output_dir_arg(value)
                self._add_arg(key, full_path, True)
            else:
                ex = exception_helper.create_cla_exception(
                    'WLSDPLY-01601', self._program_name, key)
                ex.setExitCode(self.USAGE_ERROR_EXIT_CODE)
                self._logger.throwing(ex,
                                      class_name=self._class_name,
                                      method_name=method_name)
                raise ex
            idx += 1

        print_result = {
            'required': self._required_result,
            'optional': self._optional_result
        }
        self._logger.exiting(class_name=self._class_name,
                             method_name=method_name,
                             result=print_result)
        return self._required_result, self._optional_result

    def _get_arg_value(self, args, index, key):
        """
        Return the value after the specified index in the argument array.
        Throw an exception if the next index is past the end of the arguments.
        :param args: the arguments to be examined
        :param index: the index argument before the value
        :param key: the key of the previous argument, for logging
        :return: the value of the argument, and the next index value
        """
        method_name = '_get_arg_value'
        key = args[index]
        index = index + 1
        if index >= len(args):
            ex = self._get_out_of_args_exception(key)
            self._logger.throwing(ex,
                                  class_name=self._class_name,
                                  method_name=method_name)
            raise ex
        return args[index], index

    def _check_trailing_arguments(self, args, trailing_arg_count):
        """
        Remove any trailing (no switch) arguments from the argument list and add them to the required result.
          example:
            command.sh -oracle_home /oracle file1 file2
            file1 and file2 are trailing arguments

        :param args: the arguments to be examined
        :param trailing_arg_count: the number of trailing arguments that are expected
        :return: the argument list, with the trailing arguments removed
        :raises CLAException: if there are not enough arguments present
        """
        method_name = '_check_trailing_arguments'
        args_len = len(args)

        # verify there are enough arguments for any trailing (no switch) args
        if args_len < trailing_arg_count + 1:
            ex = exception_helper.create_cla_exception('WLSDPLY-01639',
                                                       trailing_arg_count)
            ex.setExitCode(self.ARG_VALIDATION_ERROR_EXIT_CODE)
            self._logger.throwing(ex,
                                  class_name=self._class_name,
                                  method_name=method_name)
            raise ex

        # set required_result['TRAILING_ARGS'] to list of trailing args (such as ['file1', 'file2'])
        trailing_args = []
        for index in range(args_len - trailing_arg_count, args_len):
            arg = args[index]
            trailing_args.append(arg)
        self._required_result[self.TRAILING_ARGS_SWITCH] = trailing_args

        # remove trailing args from the list and return revised list
        return args[0:(args_len - trailing_arg_count)]

    def get_help_key(self):
        return self.HELP_SWITCH

    def is_help_key(self, key):
        return self.HELP_SWITCH == key

    def get_oracle_home_key(self):
        return str(self.ORACLE_HOME_SWITCH)

    def is_oracle_home_key(self, key):
        return self.ORACLE_HOME_SWITCH == key

    def _validate_oracle_home_arg(self, value):
        method_name = '_validate_oracle_home_arg'

        try:
            oh = JFileUtils.validateExistingDirectory(value)
        except JIllegalArgumentException, iae:
            ex = exception_helper.create_cla_exception(
                'WLSDPLY-01602', value, iae.getLocalizedMessage(), error=iae)
            ex.setExitCode(self.ARG_VALIDATION_ERROR_EXIT_CODE)
            self._logger.throwing(ex,
                                  class_name=self._class_name,
                                  method_name=method_name)
            raise ex

        oh_name = oh.getAbsolutePath()
        wl_helper = WebLogicHelper(self._logger)
        wl_home_name = wl_helper.get_weblogic_home(oh_name)
        try:
            JFileUtils.validateExistingDirectory(wl_home_name)
        except JIllegalArgumentException, iae:
            ex = exception_helper.create_cla_exception(
                'WLSDPLY-01603',
                wl_home_name,
                iae.getLocalizedMessage(),
                error=iae)
            ex.setExitCode(self.ARG_VALIDATION_ERROR_EXIT_CODE)
            self._logger.throwing(ex,
                                  class_name=self._class_name,
                                  method_name=method_name)
            raise ex
class OdlDeployer(object):
    """
    Handle the ODL validation and configuration.
    """
    __class_name = 'OdlHelper'

    def __init__(self, model, model_context, aliases, wlst_mode):
        self.model = model
        self.model_context = model_context
        self.aliases = aliases

        self.logger = PlatformLogger('wlsdeploy.deploy')
        self.wlst_mode = wlst_mode

    def configure_odl(self, parent_dict, parent_location):
        """
        Apply the ODL configuration section of the model, if present.
        :param parent_dict: the model dictionary that may contains ODL configuration
        :param parent_location: the alias location of the parent dictionary (used for logging paths)
        """
        _method_name = 'configure_odl'
        self.logger.entering(class_name=self.__class_name,
                             method_name=_method_name)

        odl_info = dictionary_utils.get_dictionary_element(
            parent_dict, ODL_CONFIGURATION)
        if len(odl_info):
            typedef = self.model_context.get_domain_typedef()
            if not (typedef.is_jrf_domain_type()
                    or typedef.is_restricted_jrf_domain_type()):
                self.logger.info('WLSDPLY-19709',
                                 class_name=self.__class_name,
                                 method_name=_method_name)
            elif self.wlst_mode == WlstModes.ONLINE:
                self.logger.info('WLSDPLY-19700',
                                 class_name=self.__class_name,
                                 method_name=_method_name)
            else:
                for config in odl_info:
                    self._update_config(config, odl_info[config],
                                        parent_location)

        self.logger.exiting(class_name=self.__class_name,
                            method_name=_method_name)
        return

    def _update_config(self, config_name, config_dictionary, parent_location):
        _method_name = '_update_config'

        config_location = LocationContext(parent_location).append_location(
            ODL_CONFIGURATION)
        token = self.aliases.get_name_token(config_location)
        config_location.add_name_token(token, config_name)

        servers = dictionary_utils.get_element(config_dictionary, _SERVERS)
        if servers is not None:
            servers_list = alias_utils.convert_to_type(
                'list', servers, delimiter=MODEL_LIST_DELIMITER)
            for server in servers_list:
                self.logger.info('WLSDPLY-19708',
                                 ODL_CONFIGURATION,
                                 config_name,
                                 server,
                                 class_name=self.__class_name,
                                 method_name=_method_name)
                self._update_server(server, config_dictionary, config_location)

    def _update_server(self, name, dictionary, config_location):
        _method_name = '_update_server'

        # these imports are local, since they are only present in JRF environments.
        # this method is only called after that check has been made.
        from oracle.core.ojdl.weblogic.ODLConfiguration import CONFIG_DIR
        from oracle.core.ojdl.weblogic.ODLConfiguration import CONFIG_FILE
        from oracle.core.ojdl.logging.config import LoggingConfigurationDocument

        config_dir = File(self.model_context.get_domain_home(), CONFIG_DIR)
        server_dir = File(config_dir, name)
        config_file = File(server_dir, CONFIG_FILE)
        log_template_dir = config_dir.getParentFile()

        try:
            if config_file.exists():
                source_file = config_file
                FileUtils.validateWritableFile(config_file.getPath())
            else:
                # for dynamic servers, the logging config does not exist until the server is started.
                # read the from template file, verify that the server directory is present and writable.
                source_file = File(log_template_dir, LOGGING_TEMPLATE_FILE)
                FileUtils.validateExistingFile(source_file)
                if not server_dir.exists() and not server_dir.mkdirs():
                    ex = exception_helper.create_deploy_exception(
                        'WLSDPLY-19710', server_dir)
                    self.logger.throwing(ex,
                                         class_name=self.__class_name,
                                         method_name=_method_name)
                    raise ex
                FileUtils.validateWritableDirectory(server_dir.getPath())

            document = LoggingConfigurationDocument(
                FileInputStream(source_file))

            # configure AddJvmNumber
            add_jvm_number = dictionary_utils.get_element(
                dictionary, _ADD_JVM_NUMBER)
            if add_jvm_number is not None:
                document.setAddJvmNumber(
                    alias_utils.convert_boolean(add_jvm_number))

            # configure HandlerDefaults
            handler_defaults = dictionary_utils.get_dictionary_element(
                dictionary, _HANDLER_DEFAULTS)
            if handler_defaults is not None:
                for key in handler_defaults:
                    value = handler_defaults[key]
                    document.setHandlerDefault(key, _get_property_text(value))

            # configure Handlers
            # do these before loggers, in case new handlers are assigned to loggers
            existing_handler_names = document.getHandlerNames()
            handlers = dictionary_utils.get_dictionary_element(
                dictionary, _HANDLER)
            if handlers is not None:
                for handler_name in handlers:
                    handler = handlers[handler_name]
                    self._configure_handler(handler_name, handler, document,
                                            existing_handler_names,
                                            config_location)

            # configure Loggers
            existing_logger_names = document.getLoggerNames()
            loggers = dictionary_utils.get_dictionary_element(
                dictionary, _LOGGER)
            if loggers is not None:
                for logger_name in loggers:
                    logger = loggers[logger_name]
                    self._configure_logger(logger_name, logger, document,
                                           existing_logger_names,
                                           config_location)

            document.writeDocument(FileOutputStream(config_file))

        except (ParserConfigurationException, SAXException, IOException,
                IllegalArgumentException), ex:
            self.logger.severe('WLSDPLY-19707',
                               name,
                               ex.getLocalizedMessage(),
                               class_name=self.__class_name,
                               method_name=_method_name)
        return
class CredentialMapHelper(object):
    """
    Creates .ldift initialization file for user/password credential mappings
    """
    _class_name = 'CredentialMapHelper'

    def __init__(self, model_context, exception_type):
        """
        Initialize an instance of CredentialMapHelper.
        :param model_context: used to find domain home
        :param exception_type: the type of exception to be thrown
        """
        self._model_context = model_context
        self._exception_type = exception_type
        self._logger = PlatformLogger('wlsdeploy.tool.util')
        self._weblogic_helper = WebLogicHelper(self._logger)
        self._resource_escaper = ResourcePolicyIdUtil.getEscaper()
        self._b64_encoder = BASE64Encoder()

    def create_default_init_file(self, default_mapping_nodes):
        """
        Create a .ldift file to initialize default credential mappers.
        Build a hash map for use with a template file resource.
        Write the file to a known location in the domain.
        :param default_mapping_nodes: the credential mapping elements from the model
        """
        _method_name = 'create_default_init_file'

        template_hash = self._build_default_template_hash(
            default_mapping_nodes)
        template_path = TEMPLATE_PATH + '/' + DEFAULT_MAPPER_INIT_FILE

        output_dir = File(self._model_context.get_domain_home(),
                          SECURITY_SUBDIR)
        output_file = File(output_dir, DEFAULT_MAPPER_INIT_FILE)

        self._logger.info('WLSDPLY-01790',
                          output_file,
                          class_name=self._class_name,
                          method_name=_method_name)

        file_template_helper.create_file(template_path, template_hash,
                                         output_file, self._exception_type)

    def _build_default_template_hash(self, mapping_section_nodes):
        """
        Create a dictionary of substitution values to apply to the default credential mappers template.
        :param mapping_section_nodes: the credential mapping elements from the model
        :return: the template hash dictionary
        """
        template_hash = dict()

        credential_mappings = []
        resource_mappings = []

        for mapping_type in mapping_section_nodes.keys():
            mapping_name_nodes = mapping_section_nodes[mapping_type]
            for mapping_name in mapping_name_nodes.keys():
                mapping = mapping_name_nodes[mapping_name]
                mapping_hash = self._build_mapping_hash(
                    mapping_type, mapping_name, mapping)

                # add a hash with remote target details to create a single passwordCredentialMap element
                credential_mappings.append(mapping_hash)

                # add a modified hash for each local user to create resourceMap elements
                resource_name = mapping_hash[HASH_RESOURCE_NAME]
                local_users = self._get_local_users(mapping_type, mapping_name,
                                                    mapping)
                for local_user in local_users:
                    resource_hash = dict(mapping_hash)
                    resource_hash[HASH_LOCAL_USER] = local_user
                    resource_hash[HASH_RESOURCE_CN] = self._create_cn(
                        resource_name, local_user)
                    resource_mappings.append(resource_hash)

        template_hash[CREDENTIAL_MAPPINGS] = credential_mappings
        template_hash[RESOURCE_MAPPINGS] = resource_mappings
        return template_hash

    def _build_mapping_hash(self, mapping_type, mapping_name, mapping):
        """
        Build a template hash for the specified mapping element from the model.
        :param mapping_type: the type of the mapping, such as 'CrossDomain'
        :param mapping_name: the mapping name from the model, such as 'map1'
        :param mapping: the mapping element from the model
        :return: the template hash
        """
        resource_name = self._build_resource_name(mapping_type, mapping_name,
                                                  mapping)

        remote_user = self._get_required_attribute(mapping, REMOTE_USER,
                                                   mapping_type, mapping_name)
        credential_cn = self._create_cn(resource_name, remote_user)

        # the password needs to be encrypted, then base64 encoded
        password = self._get_required_attribute(mapping, REMOTE_PASSWORD,
                                                mapping_type, mapping_name)
        encrypted = self._weblogic_helper.encrypt(
            password, self._model_context.get_domain_home())
        password_encoded = self._b64_encoder.encodeBuffer(
            String(encrypted).getBytes("UTF-8"))

        # the local user and resource CN will be updated later for each user
        return {
            HASH_CREDENTIAL_CN: credential_cn,
            HASH_LOCAL_USER: NULL,
            HASH_PASSWORD_ENCODED: password_encoded,
            HASH_REMOTE_USER: remote_user,
            HASH_RESOURCE_CN: NULL,
            HASH_RESOURCE_NAME: resource_name
        }

    def _build_resource_name(self, mapping_type, mapping_name, mapping):
        """
        Build the resource name based on elements in the mapping element from the model.
        Example: type=<remote>, protocol=http, remoteHost=my.host, remotePort=7020, path=/myapp, method=POST
        :param mapping_type: the type of the mapping, such as 'CrossDomain'
        :param mapping_name: the mapping name from the model, such as 'map1'
        :param mapping: the mapping element from the model
        :return: the resource name
        """

        # for cross-domain mapping, use domain for remote host, and set cross-domain protocol
        if mapping_type == CROSS_DOMAIN:
            remote_host = self._get_required_attribute(mapping, REMOTE_DOMAIN,
                                                       mapping_type,
                                                       mapping_name)
            protocol = CROSS_DOMAIN_PROTOCOL
        else:
            remote_host = self._get_required_attribute(mapping, REMOTE_HOST,
                                                       mapping_type,
                                                       mapping_name)
            protocol = dictionary_utils.get_element(mapping, PROTOCOL)

        # build a map of available values, some may be None
        resource_name_values = {
            ID_METHOD: dictionary_utils.get_element(mapping, METHOD),
            ID_PATH: dictionary_utils.get_element(mapping, PATH),
            ID_PROTOCOL: protocol,
            ID_REMOTE_HOST: remote_host,
            ID_REMOTE_PORT: dictionary_utils.get_element(mapping, REMOTE_PORT)
        }

        # build the resource name string
        resource_name = 'type=<remote>'
        for field in RESOURCE_FIELDS:
            value = dictionary_utils.get_element(resource_name_values, field)
            if value is not None:
                resource_name += ', %s=%s' % (field, value)

        return resource_name

    def _get_local_users(self, mapping_type, mapping_name, mapping):
        """
        Get the local users list, based on the mapping element from the model.
        :param mapping_type: the type of the mapping, such as 'CrossDomain'
        :param mapping_name: the mapping name from the model, such as 'map1'
        :param mapping: the mapping element from the model
        :return: a list of local users
        """
        if mapping_type == CROSS_DOMAIN:
            return [CROSS_DOMAIN_USER]

        local_user_value = self._get_required_attribute(
            mapping, USER, mapping_type, mapping_name)
        return TypeUtils.convertToType(list, local_user_value)

    def _get_required_attribute(self, dictionary, name, mapping_type,
                                mapping_name):
        """
        Return the value of the specified attribute from the specified dictionary.
        Log and throw an exception if the attribute is not found.
        :param dictionary: the dictionary to be checked
        :param name: the name of the attribute to find
        :param mapping_type: the type of the mapping, such as 'CrossDomain'
        :param mapping_name: the mapping name from the model, such as 'map1'
        :return: the value of the attribute
        :raises: Tool type exception: if an the attribute is not found
        """
        _method_name = '_get_required_attribute'

        result = dictionary_utils.get_element(dictionary, name)
        if result is None:
            pwe = exception_helper.create_exception(self._exception_type,
                                                    'WLSDPLY-01791', name,
                                                    mapping_type, mapping_name)
            self._logger.throwing(class_name=self._class_name,
                                  method_name=_method_name,
                                  error=pwe)
            raise pwe
        return result

    def _create_cn(self, resource_name, user):
        """
        Create a CN string from the specified resource name and user name.
        The result should be escaped for use as a CN.
        :param resource_name: the name of the resource
        :param user: the user name
        :return: the CN string
        """
        name = resource_name + "." + user
        return self._resource_escaper.escapeString(name)