#!/usr/bin/env bash

# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

function get_canonical_dir() {
  target="$1"

  canonical_name=`readlink -f ${target} 2>/dev/null`
  if [[ $? -eq 0 ]]; then
    canonical_dir=`dirname $canonical_name`
    echo ${canonical_dir}
    return
  fi

  # Mac has no readlink -f
  cd `dirname ${target}`
  target=`basename ${target}`

  # chase down the symlinks
  while [ -L ${target} ]; do
    target=`readlink ${target}`
    cd `dirname ${target}`
    target=`basename ${target}`
  done

  canonical_dir=`pwd -P`
  ret=${canonical_dir}
  echo $ret
}

bin=$(get_canonical_dir "$0")
bin=`cd "$bin"; pwd`

DEFAULT_LIBEXEC_DIR="$bin"/../libexec

cygwin=false
case "$(uname)" in
CYGWIN*) cygwin=true;;
esac

HADOOP_LIBEXEC_DIR=${HADOOP_LIBEXEC_DIR:-$DEFAULT_LIBEXEC_DIR}
if [ -e ${HADOOP_LIBEXEC_DIR}/mapred-config.sh ]; then
  . ${HADOOP_LIBEXEC_DIR}/mapred-config.sh
else
  . "$bin/mapred-config.sh"
fi

function print_usage(){
  echo "Usage: mapred [--config confdir] [--loglevel loglevel] COMMAND"
  echo "       where COMMAND is one of:"
  echo "  pipes                run a Pipes job"
  echo "  job                  manipulate MapReduce jobs"
  echo "  queue                get information regarding JobQueues"
  echo "  classpath            prints the class path needed for running"
  echo "                       mapreduce subcommands"
  echo "  historyserver        run job history servers as a standalone daemon"
  echo "  distcp <srcurl> <desturl> copy file or directories recursively"
  echo "  archive -archiveName NAME -p <parent path> <src>* <dest> create a hadoop archive"
  echo "  hsadmin              job history server admin interface"
  echo ""
  echo "Most commands print help when invoked w/o parameters."
}

if [ $# = 0 ]; then
  print_usage
  exit
fi

COMMAND=$1
shift

case $COMMAND in
  # usage flags
  --help|-help|-h)
    print_usage
    exit
    ;;
esac

if [ -f "${HADOOP_CONF_DIR}/mapred-env.sh" ]; then
  . "${HADOOP_CONF_DIR}/mapred-env.sh"
fi

#Enable JMX for MaprMonitoring # tag for older collectd - do not remove
function logJmxMsg() {
    echo $* >> "${YARN_JMX_LOG_FILE:-${HADOOP_HOME}/logs/${COMMAND}_jmx_options.log}"
}

if [ "$COMMAND" = "historyserver" ]; then

    isSecure="false"
    if [ -f "${MAPR_HOME}/conf/mapr-clusters.conf" ]; then
      isSecure=$(head -1 ${MAPR_HOME}/conf/mapr-clusters.conf | grep -o 'secure=\w*' | cut -d= -f2)
    fi

    #Mapr JMX handling
    MAPR_JMX_YARN_HISTORYSERVER_PORT=${MAPR_JMX_YARN_HISTORYSERVER_PORT:-8024}
    if [ -z "$MAPR_JMXLOCALBINDING" ]; then
        MAPR_JMXLOCALBINDING="false"
    fi

    if [ -z "$MAPR_JMXAUTH" ]; then
        MAPR_JMXAUTH="false"
    fi

    if [ -z "$MAPR_JMXSSL" ]; then
        MAPR_JMXSSL="false"
    fi

    if [ -z "$MAPR_AUTH_LOGIN_CONFIG_FILE" ]; then
        MAPR_AUTH_LOGIN_CONFIG_FILE="${MAPR_HOME:-/opt/mapr}/conf/mapr.login.conf"
    fi


    if [ -z "$MAPR_JMX_LOGIN_CONFIG" ]; then
        MAPR_JMX_LOGIN_CONFIG="JMX_AGENT_LOGIN"
    fi

    if [ -z "$MAPR_JMXDISABLE" ] && [ -z "$MAPR_JMXLOCALHOST" ] && [ -z "$MAPR_JMXREMOTEHOST" ]; then
        logJmxMsg "No MapR JMX options given - defaulting to local binding"
    fi

    if [ -z "$MAPR_JMXDISABLE" ] || [ "$MAPR_JMXDISABLE" = 'false' ]; then
        # default setting for localBinding
        MAPR_JMX_OPTS="-Dcom.sun.management.jmxremote"

        if [ "$MAPR_JMXLOCALHOST" = "true" ] && [ "$MAPR_JMXREMOTEHOST" = "true" ]; then
            logJmxMsg "WARNING: Both MAPR_JMXLOCALHOST and MAPR_JMXREMOTEHOST options are enabled - defaulting to MAPR_JMXLOCALHOST config"
            MAPR_JMXREMOTEHOST=false
        fi

        if [ "$isSecure" = "true" ] && [ "$MAPR_JMXREMOTEHOST" = "true" ]; then
            JMX_JAR=$(echo ${MAPR_HOME:-/opt/mapr}/lib/jmxagent*)
            if [ -n "$JMX_JAR" ] && [ -f ${JMX_JAR} ]; then
                MAPR_JMX_OPTS="-javaagent:$JMX_JAR -Dmapr.jmx.agent.login.config=$MAPR_JMX_LOGIN_CONFIG"
                MAPR_JMXAUTH="true"
            else
                echo "jmxagent jar file missed"
                exit 1
            fi
        fi

        if [ "$MAPR_JMXAUTH" = "true" ]; then
            if [ "$isSecure" = "true" ]; then
                if [ -f "$MAPR_AUTH_LOGIN_CONFIG_FILE" ] && \
                   [ -f "${MAPR_HOME:-/opt/mapr}/conf/jmxremote.access" ]; then
                  MAPR_JMX_OPTS="$MAPR_JMX_OPTS -Dcom.sun.management.jmxremote.authenticate=true \
                    -Djava.security.auth.login.config=$MAPR_AUTH_LOGIN_CONFIG_FILE \
                    -Dcom.sun.management.jmxremote.access.file=${MAPR_HOME:-/opt/mapr}/conf/jmxremote.access"
                else
                  echo "JMX login config or access file missing - not starting since we are in secure mode"
                  exit 1
                fi
                if [ "$MAPR_JMXREMOTEHOST" = "false" ]; then
                  MAPR_JMX_OPTS="$MAPR_JMX_OPTS -Dcom.sun.management.jmxremote.login.config=$MAPR_JMX_LOGIN_CONFIG"
                fi
            else
                echo "JMX Authentication configured - not starting since we are not in secure mode"
                exit 1
            fi
        else
            MAPR_JMX_OPTS="$MAPR_JMX_OPTS -Dcom.sun.management.jmxremote.authenticate=false"
        fi

        if [ "$MAPR_JMXLOCALHOST" = "true" ] || [ "$MAPR_JMXREMOTEHOST" = "true" ]; then
            if [ "$MAPR_JMXSSL" = "true" ] && [ "$MAPR_JMXLOCALHOST" = "true" ]; then
                echo "WARNING: ssl is not supported in localhost. Setting default to false"
                MAPR_JMX_OPTS="$MAPR_JMX_OPTS -Dcom.sun.management.jmxremote.ssl=false"
            else
                MAPR_JMX_OPTS="$MAPR_JMX_OPTS -Dcom.sun.management.jmxremote.ssl=false"
            fi

            if [ "$MAPR_JMXLOCALHOST" = "true" ]; then
                MAPR_JMX_OPTS="$MAPR_JMX_OPTS -Djava.rmi.server.hostname=localhost \
                  -Dcom.sun.management.jmxremote.host=localhost \
                  -Dcom.sun.management.jmxremote.local.only=true"
            fi

            # only enable is explicitly specified
            if [ -n "$MAPR_JMX_YARN_HISTORYSERVER_ENABLE" ] && [ "$MAPR_JMX_YARN_HISTORYSERVER_ENABLE" = "true" ]; then
                MAPR_JMX_PORT=${MAPR_JMX_YARN_HISTORYSERVER_PORT}
            else
                MAPR_JMX_PORT=""
                MAPR_JMX_OPTS=""
            fi

            if [ -z "$MAPR_JMX_OPTS" ]; then
                logJmxMsg "WARNING: JMX disabled for $COMMAND"
            elif [ -z "$MAPR_JMX_PORT" ]; then
                logJmxMsg "WARNING: No JMX port given for $COMMAND - disabling TCP base JMX service"
                MAPR_JMX_OPTS=""
            else
                if [ "$MAPR_JMXREMOTEHOST" = "true" ] && [ "$isSecure" = "true" ]; then
                    MAPR_JMX_OPTS="$MAPR_JMX_OPTS -Dmapr.jmx.agent.port=$MAPR_JMX_PORT"
                    logJmxMsg "Enabling TCP JMX for $COMMAND on port $MAPR_JMX_PORT"
                else
                    if [ "$MAPR_JMXLOCALHOST" = "true" ]; then
                        logJmxMsg "Enabling TCP JMX for $COMMAND only on localhost port $MAPR_JMX_PORT"
                    else
                        logJmxMsg "Enabling TCP JMX for $COMMAND on port $MAPR_JMX_PORT"
                    fi
                    MAPR_JMX_OPTS="$MAPR_JMX_OPTS -Dcom.sun.management.jmxremote.port=$MAPR_JMX_PORT"
                fi
            fi
        fi

        if [ "$MAPR_JMXLOCALBINDING" = "true" ] && [ -z "$MAPR_JMX_OPTS" ]; then
            logJmxMsg "Enabling JMX local binding only"
            MAPR_JMX_OPTS="-Dcom.sun.management.jmxremote"
        fi
    else
        logJmxMsg "JMX disabled by user request"
        MAPR_JMX_OPTS=""
    fi
fi

if [ "$COMMAND" = "job" ] ; then
  CLASS=org.apache.hadoop.mapred.JobClient
  HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"
elif [ "$COMMAND" = "queue" ] ; then
  CLASS=org.apache.hadoop.mapred.JobQueueClient
  HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"
elif [ "$COMMAND" = "pipes" ] ; then
  CLASS=org.apache.hadoop.mapred.pipes.Submitter
  HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"
elif [ "$COMMAND" = "sampler" ] ; then
  CLASS=org.apache.hadoop.mapred.lib.InputSampler
  HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"
elif [ "$COMMAND" = "classpath" ] ; then
  echo -n 
elif [ "$COMMAND" = "historyserver" ] ; then
  CLASSPATH=${CLASSPATH}:$MAPR_HOME/lib/JPam-1.1.jar
  CLASS=org.apache.hadoop.mapreduce.v2.hs.JobHistoryServer
  HADOOP_OPTS="$HADOOP_OPTS -Dmapred.jobsummary.logger=${HADOOP_JHS_LOGGER:-INFO,console} $HADOOP_JOB_HISTORYSERVER_OPTS"
  if [ "$HADOOP_JOB_HISTORYSERVER_HEAPSIZE" != "" ]; then
    JAVA_HEAP_MAX="-Xmx""$HADOOP_JOB_HISTORYSERVER_HEAPSIZE""m"
  fi
elif [ "$COMMAND" = "mradmin" ] \
    || [ "$COMMAND" = "jobtracker" ] \
    || [ "$COMMAND" = "tasktracker" ] \
    || [ "$COMMAND" = "groups" ] ; then
  echo "Sorry, the $COMMAND command is no longer supported."
  echo "You may find similar functionality with the \"yarn\" shell command."
  print_usage
  exit 1
elif [ "$COMMAND" = "distcp" ] ; then
  CLASS=org.apache.hadoop.tools.DistCp
  CLASSPATH=${CLASSPATH}:${TOOL_PATH}
  HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"
elif [ "$COMMAND" = "archive" ] ; then
  CLASS=org.apache.hadoop.tools.HadoopArchives
  CLASSPATH=${CLASSPATH}:${TOOL_PATH}
  HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"
elif [ "$COMMAND" = "hsadmin" ] ; then
  CLASS=org.apache.hadoop.mapreduce.v2.hs.client.HSAdmin
  HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"
else
  echo $COMMAND - invalid command
  print_usage
  exit 1
fi

# for developers, add mapred classes to CLASSPATH
if [ -d "$HADOOP_MAPRED_HOME/build/classes" ]; then
  CLASSPATH=${CLASSPATH}:$HADOOP_MAPRED_HOME/build/classes
fi
if [ -d "$HADOOP_MAPRED_HOME/build/webapps" ]; then
  CLASSPATH=${CLASSPATH}:$HADOOP_MAPRED_HOME/build
fi
if [ -d "$HADOOP_MAPRED_HOME/build/test/classes" ]; then
  CLASSPATH=${CLASSPATH}:$HADOOP_MAPRED_HOME/build/test/classes
fi
if [ -d "$HADOOP_MAPRED_HOME/build/tools" ]; then
  CLASSPATH=${CLASSPATH}:$HADOOP_MAPRED_HOME/build/tools
fi

# for releases, add core mapred jar & webapps to CLASSPATH
if [ -d "$HADOOP_PREFIX/${MAPRED_DIR}/webapps" ]; then
  CLASSPATH=${CLASSPATH}:$HADOOP_PREFIX/${MAPRED_DIR}
fi
for f in $HADOOP_MAPRED_HOME/${MAPRED_DIR}/*.jar; do
  CLASSPATH=${CLASSPATH}:$f;
done

# Need YARN jars also
for f in $HADOOP_YARN_HOME/${YARN_DIR}/*.jar; do
  CLASSPATH=${CLASSPATH}:$f;
done

# add libs to CLASSPATH
for f in $HADOOP_MAPRED_HOME/${MAPRED_LIB_JARS_DIR}/*.jar; do
  CLASSPATH=${CLASSPATH}:$f;
done

# add modules to CLASSPATH
for f in $HADOOP_MAPRED_HOME/modules/*.jar; do
  CLASSPATH=${CLASSPATH}:$f;
done

if [ "$COMMAND" = "classpath" ] ; then
  if [ "$#" -gt 0 ]; then
    CLASS=org.apache.hadoop.util.Classpath
  else
    if $cygwin; then
      CLASSPATH=$(cygpath -p -w "$CLASSPATH" 2>/dev/null)
    fi
    echo $CLASSPATH
    exit 0
  fi
fi

# cygwin path translation
if $cygwin; then
  CLASSPATH=$(cygpath -p -w "$CLASSPATH" 2>/dev/null)
  HADOOP_LOG_DIR=$(cygpath -w "$HADOOP_LOG_DIR" 2>/dev/null)
  HADOOP_PREFIX=$(cygpath -w "$HADOOP_PREFIX" 2>/dev/null)
  HADOOP_CONF_DIR=$(cygpath -w "$HADOOP_CONF_DIR" 2>/dev/null)
  HADOOP_COMMON_HOME=$(cygpath -w "$HADOOP_COMMON_HOME" 2>/dev/null)
  HADOOP_HDFS_HOME=$(cygpath -w "$HADOOP_HDFS_HOME" 2>/dev/null)
  HADOOP_YARN_HOME=$(cygpath -w "$HADOOP_YARN_HOME" 2>/dev/null)
  HADOOP_MAPRED_HOME=$(cygpath -w "$HADOOP_MAPRED_HOME" 2>/dev/null)
fi

HADOOP_OPTS="$HADOOP_OPTS -Dhadoop.security.logger=${HADOOP_SECURITY_LOGGER:-INFO,NullAppender}"
HADOOP_OPTS_JMX="$HADOOP_OPTS $MAPR_JMX_OPTS"

export CLASSPATH
exec "$JAVA" -Dproc_$COMMAND $JAVA_HEAP_MAX $HADOOP_OPTS_JMX $CLASS "$@"
