#############################
# This is a Jython 2.1 script
# Features:
#   - java compilation
#   - java web app deployment
#   - java web app reload with Tomcat
#############################
import sys
import os, os.path
import shutil
import urllib, base64
import re


class WebAppTask:
    def __init__(self):
        self.web_dirs = ['../site','WebContent']
        self.webapp_name = 'mubot'
        self.tomcat_dir = 'c:/java/Tomcat 5.5'
        self.tomcat_host = "localhost:80"
        self.tomcat_user = 'michelin'
        self.tomcat_password = 'michelin'
        self.compile_target = 'WebContent/WEB-INF/classes'
        self.compile_source = 'JavaSource'
        self.compile_libdirs = ['WebContent/WEB-INF/lib','external-libs']

    def copy_resources(self):
        return self

    def build(self):
        cp = JavaClassPath().addLocation(self.compile_target)
        for libdir in self.compile_libdirs:
            cp.addLibDir(libdir)
            cp.addLibDir(libdir)
        files = JavaFinder().addJavaDir(self.compile_source)
        compile_command = "javac -cp %s -d %s -sourcepath %s %s" % (cp,self.compile_target,self.compile_source,files)
        print "executing %s" % compile_command
        result = os.system(compile_command)
        if not result == 0:
            print 'compilation failed with %s' % compile_command
        else:
            print 'compilation successful'
        return self
    
    def deploy(self):
        target_dir = self.tomcat_dir+'/webapps'+'/'+self.webapp_name
        copier=LatestTreeCopier()
        for web_dir in self.web_dirs:
            copier.copytree(web_dir,target_dir)
        print "copied %s file(s) to %s" % (copier.count,target_dir)
        return self

    def reload(self):
        url = 'http://'+self.tomcat_host+"/manager/reload?path=/"+self.webapp_name
        base64string = base64.encodestring("%s:%s"%(self.tomcat_user,self.tomcat_password))[:-1]
        opener = urllib.URLopener()
        opener.addheader('Authorization',"Basic %s"%base64string)
        h = opener.open(url)
        print h.read()
        h.close()
        return self

    def main(self):
        if (len(sys.argv)) >= 2:
            methods = sys.argv[1:]
            for m in methods:
                method = 'self.'+m+'()'
                print "launching %s" % method
                eval(method)
        else:
            self.deploy()
            self.reload()

class JavaClassPath:
    
    def __init__(self):
        self.items = []
        self.computeSeparator()

    def computeSeparator(self):
        choice = os.name
        if choice == 'posix' or choice == 'mac':
            self.separator=':'
        elif choice == 'nt':
            self.separator=';'
        elif choice == 'java':
            from java.lang import System
            self.separator = System.getProperty("path.separator")
        return self.separator
            
    def addLocation(self, location):
        self.items.append(location)
        return self

    def addLibDir(self, dir):
        names = os.listdir(dir)
        fullNames = []
        for name in names:
            if re.compile('(jar|zip)$').search(name):
                fullNames.append(os.path.join(dir,name))
        self.items.extend(fullNames)
        return self
    
    def __add__(self,other):
        addLocation(self,other)
    
    def __str__(self):
        return self.separator.join(self.items)
    
class JavaFinder:
    def __init__(self):
        self.files = []
        
    def addJavaDir(self, dir):
        names = os.listdir(dir)
        for name in names:
            fullname = os.path.join(dir,name)
            if os.path.isdir(fullname):
                self.addJavaDir(fullname)
            elif re.compile('java$').search(fullname):
                self.files.append(fullname)
        return self

    def __str__(self):
        return ' '.join(self.files)
    
class TreeCopier:
    def __init__(self):
        self.count = 0

    def filter(self, srcname, dstname):
        return true

    def filterDir(self, srcname):
        return true

    def copytree(self, src, dst, symlinks=0):
        """Recursively copy a directory tree using copy2().
        """
        names = os.listdir(src)
        if not os.path.exists(dst):
            os.mkdir(dst)
        count = 0
        for name in names:
            srcname = os.path.join(src, name)
            dstname = os.path.join(dst, name)
            try:
                if symlinks and os.path.islink(srcname):
                    linkto = os.readlink(srcname)
                    os.symlink(linkto, dstname)
                elif os.path.isdir(srcname):
                    if self.filterDir(srcname):
                        #print "copying "+srcname
                        self.copytree(srcname, dstname, symlinks)
                else:
                    if self.filter(srcname, dstname):
                        shutil.copy2(srcname, dstname)
                        print srcname
                        count += 1
# XXX What about devices, sockets etc.
            except (IOError), why:
                print "Can't copy %s to %s: %s" % ('srcname', 'dstname', str(why))
        self.count += count
        #print("copied %s file(s) to %s"% (count,dst))

class LatestTreeCopier(TreeCopier):
    def __init__(self):
        self.count = 0
        self.excludePattern = re.compile('(^\.svn.*|.*\.swp$|.*\.bak$|.*~$|.*\.swo$)',re.I)
        self.excludeDirPattern = re.compile('^\.svn.*',re.I)

    def filter(self, srcname, dstname):
        result = (not self.excludePattern.match(os.path.basename(srcname)))
        if result and os.path.exists(dstname):
            result = (os.path.getmtime(srcname) > os.path.getmtime(dstname))
        return result 

    def filterDir(self, srcname):
        #print 'dir ='+os.path.basename(srcname)
        return (not self.excludeDirPattern.match(os.path.basename(srcname)))

if __name__ == "__main__":
    WebAppTask().main()