# Copyright 2012 Citrix Systems, Inc. Licensed under the # Apache License, Version 2.0 (the "License"); you may not use this # file except in compliance with the License. Citrix Systems, Inc. # reserves all rights not expressly granted by 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. # # Automatically generated by addcopyright.py at 04/03/2012 from optparse import OptionParser import sys import os, os.path import fnmatch import time class CopyRightDetecter(object): def isCopyRightLine(self, txt): return False class KeyWordCopyRightDetecter(CopyRightDetecter): keywords = ['Cloud.com', 'Copyright', '(C)', '2011', 'Citrix', 'Systems', 'Inc', 'All', 'rights', 'reserved', 'This', 'software', 'is', 'licensed', 'under', 'the', 'GNU', 'General', 'Public', 'License', 'v3', 'or', 'later', 'It', 'is', 'free', 'software:', 'you', 'can', 'redistribute', 'it', 'and/or', 'modify', 'it', 'under', 'the', 'terms', 'of', 'the', 'GNU', 'General', 'Public', 'License', 'as', 'published', 'by', 'the', 'Free', 'Software', 'Foundation', 'either', 'version', '3', 'of', 'the', 'License', 'or', 'any', 'later', 'version', 'This', 'program', 'is', 'distributed', 'in', 'the', 'hope', 'that', 'it', 'will', 'be', 'useful', 'but', 'WITHOUT', 'ANY', 'WARRANTY;', 'without', 'even', 'the', 'implied', 'warranty', 'of', 'MERCHANTABILITY', 'or', 'FITNESS', 'FOR', 'A', 'PARTICULAR', 'PURPOSE', 'See', 'the', 'GNU', 'General', 'Public', 'License', 'for', 'more', 'details', 'You', 'should', 'have', 'received', 'a', 'copy', 'of', 'the', 'GNU', 'General', 'Public', 'License', 'along', 'with', 'this', 'program', 'If', 'not', 'see', '', 'Version', '2', 'only', '("GPL")', 'Common', 'Development', 'and', 'Distribution', 'License("CDDL")', '(collectively', 'License").', 'language', 'governing', 'permissions', 'limitations', 'License.', '-', 'When', 'distributing', 'include', 'Header', 'Notice', 'each', 'file', 'at', 'glassfish/bootstrap/legal/LICENSE.txt.', 'Sun', 'designates', 'particular', 'subject', 'to', 'Classpath', 'exception', 'provided', 'GPL', 'section', 'accompanied', 'code.', 'applicable', 'add', 'following', 'below', 'fields', 'enclosed', 'brackets', 'replaced', 'your', 'own', 'identifying', 'information', 'Portions', 'Copyrighted', 'year', 'name', 'copyright', 'owner]', 'Contributor(s)', 'indicate', 'decision', 'adding', '[Contributor', 'elects', 'distribution', 'CDDL', 'license.', "don't", 'single', 'choice', 'license', 'recipient', 'has', 'option', 'distribute', 'extend', 'its', 'licensees', 'above.', 'However', 'if', 'code', 'therefore', 'elected', 'then', 'applies', 'new', 'made', 'such', 'holder.'] def isCopyRightLine(self, txt): words = [ c.strip().strip('.').strip('\n').strip(',').strip() for c in txt.split(" ") ] total = len(words) if total == 0: return False numKeyWord = 0 for w in words: if w == "": continue if w in self.keywords: numKeyWord+=1 if float(numKeyWord)/float(total) >= float(1)/float(2): return True return False copyRightDetectingFactory = {"KeyWord":KeyWordCopyRightDetecter.__name__} logfd = open("/tmp/addcopyright.log", 'w') class Logger(object): @staticmethod def info(msg): sys.stdout.write("INFO: %s"%msg) sys.stdout.write("\n") sys.stdout.flush() @staticmethod def debug(msg): logfd.write("DEBUG: %s"%msg) logfd.write("\n") @staticmethod def warn(msg): sys.stdout.write("WARNNING: %s"%msg) sys.stdout.write("\n") sys.stdout.flush() @staticmethod def error(msg): sys.stderr.write("ERROR: %s"%msg) sys.stderr.write("\n") sys.stderr.flush() class Adder(object): defaultTxt = '''Copyright 2012 Citrix Systems, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. Citrix Systems, Inc. reserves all rights not expressly granted by 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. ''' copyRightTxt = None targetFile = None fileBody = None decter = None signature = 'Automatically generated by addcopyright.py at %s' % time.strftime("%m/%d/%Y", time.localtime()) COMMENT_NOTATION = "" def __init__(self): self.decter = eval(copyRightDetectingFactory["KeyWord"])() def setTargetFile(self, fpath): self.targetFile = fpath if not os.path.exists(self.targetFile): raise Exception("Cannot find %s"%self.targetFile) def setCopyRightTxt(self, txt): self.copyRightTxt = txt.split("\n") def checkParams(self): assert self.targetFile != None, "Target file not set" if self.copyRightTxt == None: self.copyRightTxt = self.defaultTxt.split("\n") def pasteCopyRight(self): self.fileBody = self.copyRightTxt + self.fileBody file(self.targetFile, 'w').write("".join(self.fileBody)) Logger.info("Added copyright header to %s"%self.targetFile) def composeCopyRight(self): l = self.copyRightTxt l.append(self.signature) l = [ self.COMMENT_NOTATION + " " + line + "\n" for line in l ] self.copyRightTxt = l def getFileBody(self): self.fileBody = file(self.targetFile).readlines() def isCommentLine(self, line): if line.strip().startswith(self.COMMENT_NOTATION): return True return False def removeOldCopyRight(self): newBody = [] removed = False for line in self.fileBody[0:50]: if self.isCommentLine(line) and self.decter.isCopyRightLine(line): removed = True Logger.debug("remove old copyright: %s" % line) continue newBody.append(line) self.fileBody = newBody + self.fileBody[50:] if removed: Logger.info("Removed old copyright header of %s"%self.targetFile) def cleanBlankComment(self): newBody = [] for l in self.fileBody[0:50]: if self.isCommentLine(l) and l.strip().strip(self.COMMENT_NOTATION).strip().strip('\n') == "": Logger.debug("Blank Comment: %s" % l) continue newBody.append(l) self.fileBody = newBody + self.fileBody[50:] def doWork(self): self.checkParams() self.getFileBody() self.removeOldCopyRight() self.composeCopyRight() self.cleanBlankComment() self.pasteCopyRight() class SqlAdder(Adder): def __init__(self): super(SqlAdder, self).__init__() self.COMMENT_NOTATION = "#" class InterpreterAdder(Adder): def __init__(self): super(InterpreterAdder, self).__init__() self.COMMENT_NOTATION = "#" def pasteCopyRight(self): if len(self.fileBody) > 0 and self.isCommentLine(self.fileBody[0]): # Don't cover the first line of interpreter comment self.fileBody = [self.fileBody[0]] + self.copyRightTxt + self.fileBody[1:] else: self.fileBody = self.copyRightTxt + self.fileBody file(self.targetFile, 'w').write("".join(self.fileBody)) Logger.info("Added copyright header to %s"%self.targetFile) class JavaAdder(Adder): commentOn = False def __init__(self): super(JavaAdder, self).__init__() self.COMMENT_NOTATION = '//' def isCommentLine(self, line): if line.strip().startswith('//'): return True elif line.strip().startswith('/*'): self.commentOn = True return True elif self.commentOn == True and line.find('*/') != -1: self.commentOn = False return True elif self.commentOn: return True else: return False def cleanBlankComment(self): #TODO pass copyRightAdderFactory = {".sql":SqlAdder.__name__, ".sh":InterpreterAdder.__name__, ".py":InterpreterAdder.__name__} class CopyRightAdder(object): parser = None options = None args = None targetFiles = None excludeFiles = None copyRightFileTxt = None rootDir = None def errAndExit(self, msg): Logger.error(msg) Logger.info("addcopyright -h for help") sys.exit(1) def __init__(self): usage = '''Usage: addcopyright [file_name_pattern] [--exculdes=file_name_pattern] [--file=copyright_file] [--root=root_dir_of_files_to_add_header] [--replace] Examples: addcopyright addcopyright *.sql addcopyright *.sql --excludes="*.sql~" addcopyright *.sql --file=/root/Citrix.copyright addcopyright *.sql --file=/root/Citrix.copyright --root=~/cloudstack-oss ''' self.parser = OptionParser(usage=usage) self.parser.add_option("", "--excludes", action="store", type="string", dest="excludes", default="", help="Exclude these files when adding copyright header") self.parser.add_option("", "--file", action="store", type="string", dest="copyRightFile", default="", help="Path to copyright header file. Default to Citrix copyright header") self.parser.add_option("", "--root", action="store", type="string", dest="rootDir", default="", help="Root folder where files being added copyright header locate. Default to current directory") (self.options, self.args) = self.parser.parse_args() if len(self.args) > 1: self.errAndExit("Invalid arguments:%s" % self.args) if len(self.args) == 1: self.targetFiles = self.args[0] if self.options.excludes != "": self.excludeFiles = self.options.excludes if self.options.copyRightFile != "": self.copyRightFileTxt = file(self.options.copyRightFile).read() if self.options.rootDir != "": self.rootDir = os.path.expanduser(self.options.rootDir) if not os.path.isdir(self.rootDir): raise Exception("Cannot find directory %s"%self.rootDir) else: self.rootDir = os.getcwd() def createConcreteAdder(self, filename): (x, ext) = os.path.splitext(filename) if not copyRightAdderFactory.has_key(ext): return None return eval(copyRightAdderFactory[ext])() def run(self): for root, dirs, files in os.walk(self.rootDir): for f in files: fpath = os.path.join(root, f) if self.excludeFiles != None and fnmatch.fnmatch(f, self.excludeFiles): Logger.info("Skipping excluded file %s" % fpath) continue if self.targetFiles != None and not fnmatch.fnmatch(f, self.targetFiles): Logger.info("Skipping %s not matching our file name pattern" % fpath) continue adder = self.createConcreteAdder(f) if adder == None: Logger.warn("Cannot find a proper copyright Adder for %s, skip it" % fpath) continue adder.setTargetFile(fpath) if self.copyRightFileTxt != None: adder.setCopyRightTxt(self.copyRightFileTxt) adder.doWork() if __name__ == '__main__': task = CopyRightAdder() task.run()