坚持自己写工具,不管是构建还是测试打包上传更新.就是不用复杂的东西来解决简单的问题

#!/bin/bash
########################################################
### java project builder tools                       ###
### 自制java unix shell环境下build工具                     ###
### create date 2009-04-02                           ###
### last modify 2009-07-23                           ###
### version 1.2.5                                    ###
########################################################
##log级别定义
DEBUG_LEVEL_INFO=1
DEBUG_LEVEL_DEBUG=2
DEBUG_LEVEL_WARN=3
DEBUG_LEVEL_ERROR=4
##########################################################################################################################################
##                                                        项目定义部分 开始                                                                            ##
##########################################################################################################################################

###############################################
## 定义项目基本结构	(必要)                        ##
###############################################
## 项目的名字
PROJECT_NAME=ezweb-core
## 项目的版本号
PROJECT_VERSION=2.0
## 定义项目路径
PROJECT_HOME=.
## 定义源代码根路径
JAVA_SRC_DIR=$PROJECT_HOME/src
## 定义测试源代码根路径
JAVA_TEST_SRC_DIR=$PROJECT_HOME/test
## 定义jar包输出路径
JAVA_PACKAGE_TARGET_DIR=$PROJECT_HOME/target
## 定义测试输出路径
JAVA_TEST_TARGET_DIR=$PROJECT_HOME/target/classes
## 定义编译输出路径
DEST_BIN_OUTPUT_DIR=$PROJECT_HOME/bin
## 定义api文档输出路径
JAVA_DOC_OUTPUT_DIR=$PROJECT_HOME/docs
## 定义编译输出路径
DEP_LIB_DIR=$PROJECT_HOME/lib
## 定义log目录
BUILD_LOG_OUTPUT_DIR=$PROJECT_HOME/log
## 定义运行的log级别
DEBUG_LEVEL=1

###############################################
## 定义项目构建任务	(可选)                        ##
###############################################
## 定义默认的任务 init_env , clear , compile , copy_resources_files, default_build, java_doc
## 默认的任务default_build 编译项目,拷贝资源文件到输出路径
DEFAULT_RUN_TASK_NAME="default_build"
## 定义需要执行的java类
#RUN_JAVA_CLASS_NAME=com.ergal.ezweb.core.AllTest
## 定义需要执行的java类 的参数
#RUN_JAVA_ARGUMENTS=arg0


###############################################
## 定义java运行环境和参数(必要)                   ##
###############################################
## 定义java jdk所在的根目录
JAVA_HOME=/opt/sun-jdk-1.6.0.13
## 定义java运行时的内存参数
JAVA_OPTS="-Xms64m -Xmx256m"
## PATH
PATH=$JAVA_HOME/bin:$PATH
## CLASSPATH 当然包含 编译好的工程的包
CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:"$DEST_BIN_OUTPUT_DIR/":"$JAVA_TEST_TARGET_DIR/":"$JAVA_SRC_DIR"
## 系统的字符编码
export LANG=zh_CN.UTF-8
## 任务执行的时候的锁
BUILD_TASK_LOCK_DIR=$PROJECT_HOME/.lock


###############################################
## 接收和定义命令行传来的参数                         ##
###############################################
## 定义个数组来储存参数
declare -a para_args_array
## 定义参数下标
args_index=1
for arg in "$@"
    do
        para_args_array[$args_index]=$arg
        let "args_index+=1"
    done
    
    
##########################################################################################################################################
##                                                        项目定义部分 结束                                                                            ##
##########################################################################################################################################

##########################################################################################################################################
##                                                       主要build任务函数 开始                                                                       ##
##########################################################################################################################################

###############################################
## 初始化环境变量CLASSPATH                      ##
###############################################
init_env()
{
	build_log_task "launch initialize task"
	## 进入项目目录
	cd $PROJECT_HOME
	## 把lib里的jar包加入到CLASSPATH里
	for jar in `ls $DEP_LIB_DIR/*.jar`
    do
        CLASSPATH="$CLASSPATH:""$jar"
    done
	build_log_output_info "JAVA_HOME" "$JAVA_HOME"
	build_log_output_info "CLASSPATH" "$CLASSPATH"
	build_log_output_info "PATH" "$PATH"
}
###############################################
## 清空编译目录                                      ##
###############################################
clear()
{
	build_log_task "launch clear task"
	# 源代码输出目录
    if [ -e $DEST_BIN_OUTPUT_DIR ] ; then
        rm -rf "$DEST_BIN_OUTPUT_DIR"
        mkdir -p "$DEST_BIN_OUTPUT_DIR"
    else
        mkdir -p "$DEST_BIN_OUTPUT_DIR"
    fi	
    # 测试代码输出目录
    if [ -e $JAVA_TEST_TARGET_DIR ] ; then
        rm -rf "$JAVA_TEST_TARGET_DIR"
        mkdir -p "$JAVA_TEST_TARGET_DIR"
    else
        mkdir -p "$JAVA_TEST_TARGET_DIR"
    fi	
}
###############################################
## 编译java源文件                                   ##
###############################################
compile()
{   
	# 先清空目录
	clear
	# 初始化环境
	init_env
	build_log_task "launch compile task"
    # 初始化一个数组储存存放java源文件的所有的文件夹
    declare -a java_source_folder_array
    folder_number=0 
    # 循环查找所有java文件
    for java_source_name in ` find $JAVA_SRC_DIR/ -type f -name  '*.java' `
        do
        	# 去掉java的文件名和/  剩下就是文件夹路径 比如 "./src/com/google/inject"
            java_sources_forlder_name=${java_source_name%/*.java}
            # 判断数组里是否含有此文件夹
            has_it_flag=0
            for i in ${#java_source_folder_array[@]}
	        do
                   if [ "${java_source_folder_array[$i]}" = "$java_sources_forlder_name" ] ; then
                       has_it_flag=1
                   elif [ "$java_sources_forlder_name" = "$JAVA_SRC_DIR/" ] ; then
                       has_it_flag=1
                   fi
	        done
	        # 如果没有此文件夹 加数组里
            if [ "$has_it_flag" = 0 ] ; then 
                let "folder_number+=1"
                java_source_folder_array[$folder_number]="$java_sources_forlder_name"        
            fi
        done
    build_log_task "start to compile java source ......"
    build_log_output_info "total package count " "$[folder_number]"
    build_log_output_info "total java source count " ` find $JAVA_SRC_DIR/ -name *.java |wc -l `
    # 得到所有的java 源文件
    java_source_files=""
    for (( a=1 ; a <= $[folder_number] ; a++ ))
        do
             java_source_files="$java_source_files ""${java_source_folder_array[$a]}""/*.java"
        done
    # 编译源文件到指定的目录
    javac -encoding "UTF-8" -nowarn -d $DEST_BIN_OUTPUT_DIR  $java_source_files
    build_log_output_info "total class file  count " ` find $DEST_BIN_OUTPUT_DIR/ -name *.class |wc -l `
}
###############################################
## 编译test源文件                                   ##
###############################################
compile_test()
{   
	build_log_task "launch compile test task"
    # 初始化一个数组储存存放java源文件的所有的文件夹
    declare -a java_source_folder_array
    folder_number=0 
    # 循环查找所有java文件
    for java_source_name in ` find $JAVA_TEST_SRC_DIR/ -type f -name  '*.java' `
        do
        	# 去掉java的文件名和/  剩下就是文件夹路径 比如 "./src/com/google/inject"
            java_sources_forlder_name=${java_source_name%/*.java}
            # 判断数组里是否含有此文件夹
            has_it_flag=0
            for i in ${#java_source_folder_array[@]}
	        do
                   if [ "${java_source_folder_array[$i]}" = "$java_sources_forlder_name" ] ; then
                       has_it_flag=1
                   elif [ "$java_sources_forlder_name" = "$JAVA_TEST_SRC_DIR/" ] ; then
                       has_it_flag=1
                   fi
	        done
	        # 如果没有此文件夹 加数组里
            if [ "$has_it_flag" = 0 ] ; then 
                let "folder_number+=1"
                java_source_folder_array[$folder_number]="$java_sources_forlder_name"        
            fi
        done
    build_log_task "start to compile java source ......"
    build_log_output_info "total test package count " "$[folder_number]"
    build_log_output_info "total java test source count " ` find $JAVA_TEST_SRC_DIR/ -name *.java |wc -l `
    # 得到所有的java 源文件
    java_source_files=""
    for (( a=1 ; a <= $[folder_number] ; a++ ))
        do
             java_source_files="$java_source_files ""${java_source_folder_array[$a]}""/*.java"
        done
    # 编译源文件到指定的目录
    javac -encoding "UTF-8" -nowarn -d $JAVA_TEST_TARGET_DIR  $java_source_files
    build_log_output_info "total test class file  count " ` find $JAVA_TEST_TARGET_DIR/ -name *.class |wc -l `
}
###############################################
## 运行单元测试                                      ##
###############################################
java_test()
{
	build_log_task "start to run java junit test!!!"
    # 在java测试源文件目录 查找所有java文件并循环出来
    for java_source_name in ` find $JAVA_TEST_SRC_DIR/ -type f -name  '*.java' `
        do
           # 去掉文件夹名
           java_test_source_file_name=${java_source_name#"$JAVA_TEST_SRC_DIR/"}
           # 去掉.java
           java_test_source_class_name=${java_test_source_file_name%.java}
           # 把com/ohergal/guice/test/TestGuiceMain.java 去掉斜线 换成. 变成com.ohergal.guice.test.TestGuiceMain
           java_test_class=${java_test_source_class_name/.}
           # 测试
           java org.junit.runner.JUnitCore $java_test_class
        done
}
###############################################
## 生成javadoc                                ##
###############################################
java_doc()
{
	#初始化java环境
	init_env
	build_log_task "launch javadoc task"
	# 清空目录 并重建
	if [ -e $JAVA_DOC_OUTPUT_DIR ] ; then
        rm -rf "$JAVA_DOC_OUTPUT_DIR"
        mkdir "$JAVA_DOC_OUTPUT_DIR"
    else
        mkdir "$JAVA_DOC_OUTPUT_DIR"
    fi	
    
    # 初始化一个数组储存存放java源文件的所有的文件夹
    declare -a java_source_folder_array
    folder_number=0 
    # 循环查找所有java文件
    for java_source_name in ` find $JAVA_SRC_DIR/ -type f -name  '*.java' `
        do
        	# 去掉java的文件名和/  剩下就是文件夹路径 比如 "./src/com/google/inject"
            java_sources_forlder_name=${java_source_name%/*.java}
            # 判断数组里是否含有此文件夹
            has_it_flag=0
            for i in ${#java_source_folder_array[@]}
	        do
                   if [ "${java_source_folder_array[$i]}" = "$java_sources_forlder_name" ] ; then
                       has_it_flag=1
                   elif [ "$java_sources_forlder_name" = "$JAVA_SRC_DIR/" ] ; then
                       has_it_flag=1
                   fi
	        done
	        # 如果没有此文件夹 加数组里
            if [ "$has_it_flag" = 0 ] ; then 
                let "folder_number+=1"
                java_source_folder_array[$folder_number]="$java_sources_forlder_name"        
            fi
        done
	# 得到所有的java 源文件的包
	java_source_files=""
    for (( a=1 ; a <= $[folder_number] ; a++ ))
        do
             java_source_files="$java_source_files ""${java_source_folder_array[$a]}""/*.java"
        done
    # 生成文档api
    build_log_output_info "all the java packages " "$java_source_files"
    javadoc -encoding UTF-8 -charset UTF-8 -d $JAVA_DOC_OUTPUT_DIR -sourcepath $java_source_files
    
}

###############################################
## 打jar包                                          ##
###############################################
jar_package()
{
	build_log_task "launch jar task"
	# 定义jar包路径和名字 
	package_name=$PROJECT_NAME"-"$PROJECT_VERSION".jar"
	if [ -e $package_name ] ; then
		rm -rf $package_name
	fi
    jar -cf $JAVA_PACKAGE_TARGET_DIR/$package_name -C $DEST_BIN_OUTPUT_DIR .
    build_log_output_info "create a packge" "$JAVA_PACKAGE_TARGET_DIR/$package_name"
}
###############################################
## 拷贝所有项目源代码里的配置文件和资源文件            ##
###############################################
copy_resources_files()
{   
    build_log_task "launch copy resource file task"
    for resources_file_name in `find $JAVA_SRC_DIR/  /( -type f  -name '**.java*' -o -type d -o -path  '*.svn*' /)  -o -print`
        do
            # 去掉前缀的路径 不包含所在的项目下的源文件路径
            resource_file_name_nsp=${resources_file_name#"$JAVA_SRC_DIR/"}
	    	build_log_output_info "copy resource file " $resource_file_name_nsp
            # 拷贝到编译输出目录中
	    	cp -fu $resources_file_name "$DEST_BIN_OUTPUT_DIR""/$resource_file_name_nsp"
	    	# 拷贝到测试输出目录中
	    	cp -fu $resources_file_name "$JAVA_TEST_TARGET_DIR""/$resource_file_name_nsp"
        done
}
###############################################
## 默认的构建方法 编译和copy资源                     ##
###############################################
default_build()
{
	compile
	compile_test
    copy_resources_files
    java_test
    #jar_package
}

##########################################################################################################################################
##                                                       主要build任务函数 结束                                                                       ##
##########################################################################################################################################

##########################################################################################################################################
##                                                       脚本工具函数部分 开始                                                                         ##
##########################################################################################################################################

###############################################
## 输出调试信息的方法                                ##
###############################################
## 打印提示信息标题 1个参数 标题信息  
build_log_title()
{
	if (( DEBUG_LEVEL <= DEBUG_LEVEL_DEBUG )) ; then
		if [[ ! -z $1 ]] ; then
			echo -e '/E[31;48m'"/033[1m ****************************        $1        **************************** /033[0m"
		fi
	fi
}
## 输出调试变量信息 2个参数  参数名 和参数值
build_log_output_info()
{
	if (( DEBUG_LEVEL <= DEBUG_LEVEL_DEBUG )) ; then
		if [[ ! -z $1 && ! -z $2 ]] ; then
			echo -e '/E[32;48m'"/033[1m $1 : /033[0m" $2
		fi
	fi
}
## 打印提示信息标题 1个参数 标题信息  
build_log_task()
{
	if (( DEBUG_LEVEL <= DEBUG_LEVEL_DEBUG )) ; then
		if [[ ! -z $1 ]] ; then
			echo -e '/E[33;48m'"/033[1m $1 /033[0m"
		fi
	fi
}
## 打印错误提示信息
build_log_error()
{
	if [[ ! -z $1 ]] ; then
		echo -e '/E[31;48m'"/033[1m $1 /033[0m"
	fi
}
###############################################
## 锁住任务方法                                      ##
###############################################
lock_build_task()
{
	# 任务名称
	task_name=$1
	# 如果不存在.lock文件夹 先创建文件夹
	if [ ! -e $BUILD_TASK_LOCK_DIR ] ; then
        mkdir "$BUILD_TASK_LOCK_DIR"
    fi	
    # 检查是否有任务执行
    if [[ -z $task_name ]] ; then
    	build_log_error "no task run !! please check it!!!"
    	return 2
    else
    	# 有任务名 那么检查此任务是否在进行中 如果在 返回错误  如果不在进行中 加锁 并开始执行
    	task_lock_file="$BUILD_TASK_LOCK_DIR"/"$task_name"
    	if [  -e $task_lock_file ] ; then
        	build_log_error "the last $task_name is running !! please wait!!!"
        	return 1
        else
        	touch $task_lock_file
        	return 0
    	fi
    fi
}
###############################################
## 任务解锁方法                                      ##
###############################################
unlock_build_task()
{
	# 任务名称
	task_name=$1
	# 如果不存在.lock文件夹 先创建文件夹
	if [ ! -e $BUILD_TASK_LOCK_DIR ] ; then
        mkdir "$BUILD_TASK_LOCK_DIR"
    fi	
    # 检查是否有任务执行
    if [[ -z $task_name ]] ; then
    	build_log_error "no task run !! please check it!!!"
    	return 2
    else
    	# 有任务名 如果存在锁 删除锁
    	task_lock_file="$BUILD_TASK_LOCK_DIR"/"$task_name"
    	if [  -e $task_lock_file ] ; then
        	rm -rf $task_lock_file
        	return 0
        else
        	build_log_error "no task lock will be unlock !! please check it!!!"
        	return 1
    	fi
    fi	
}
###############################################
## 检查执行任务合法性方法                             ##
###############################################
check_build_task()
{
	if [[ $1 = "default_build" ]] ; then
        return 0
    elif [[ $1 = "compile" ]] ; then 
    	return 0
    elif [[ $1 = "copy_resources_files" ]] ; then 
    	return 0
    elif [[ $1 = "clear" ]] ; then 
    	return 0
    elif [[ $1 = "init_env" ]] ; then 
    	return 0
    elif [[ $1 = "java_doc" ]] ; then 
    	return 0
    else
    	build_log_error "no task named $1 please check it!!!"
    	return 1
    fi
}
###############################################
## 脚本的执行入口方法                                ##
###############################################
start()
{
	build_log_title "build $PROJECT_NAME start"
	run_task=${para_args_array[1]}
	# 如果没有别的参数 就直接执行配置的默认任务
    if [ -z $run_task ] ; then
    	lock_build_task $DEFAULT_RUN_TASK_NAME
    	if (( $?==0  )) ; then
    		# 执行任务
    		$DEFAULT_RUN_TASK_NAME
    		# 解锁
    		unlock_build_task $DEFAULT_RUN_TASK_NAME
    	fi
    else
   		# 检查任务合法性
    	check_build_task $run_task
    	if (( $?==0  )) ; then
    		lock_build_task $run_task
	    	if (( $?==0  )) ; then
	    		# 执行任务
	    		$run_task
	    		# 解锁
	    		unlock_build_task $run_task
	    	fi
    	fi
    	
    fi
    build_log_title "build $PROJECT_NAME end"
}
##########################################################################################################################################
##                                                       脚本工具函数部分 结束                                                                         ##
##########################################################################################################################################

###开始执行任务
start
exit 0 
## 版本更新记录
## 1.2.0 重构所有结构 模块化各个任务
## 1.2.3 增加java doc
## 1.2.4 增加junit单元测试
## 1.2.5 增加jar任务
## 需要改进的地方
## 1 任务之间协调麻烦 需要有个执行状态 解决循环依赖的问题