| New file |
| | |
| | | #!/usr/bin/env ruby |
| | | |
| | | require 'fileutils' |
| | | |
| | | # |
| | | # Automate code replacements using regular expressions |
| | | # |
| | | # To define a new replacement, add a new constant like VALIDATOR. |
| | | # |
| | | # It should be a ruby Hash with three mandatory keys and one optional key: |
| | | # |
| | | # :dirs => a list of directory to run replacements. All subdirs are processed. |
| | | # :extensions => a list of file extensions. Only file with these extensions are processed. |
| | | # :replacements => a list of replacements, lines are processed 2 by 2 |
| | | # - first line gives the pattern to replace, as a ruby regexp (see http://rubular.com/ for help and tool) |
| | | # - second line gives the replacement string, using \1, \2, ... to insert matching groups. This is a string, |
| | | # use simple quote if no special char is inserted, or use double quote if using special char like \n |
| | | # Don't forget to put a comma at end of each line, this is the array element separator. |
| | | # It is ok to leave a new line to separate each pair of line for readability. |
| | | # It is ok to use a comment in the array (use # as first non blank character of line). |
| | | # |
| | | # The optional key is :stopwords => a list of stopword. If any word in this list appears in a file name, the file |
| | | # is not processed. Use it to exclude some files or directory that must not be processed. |
| | | # |
| | | # Once you have define your replacement, add the constant in REPLACEMENTS array. it will be taken into account when |
| | | # running the program (run it at root of project) with command: ./replace.rb |
| | | # |
| | | class Replace |
| | | |
| | | # All directories that contains java code |
| | | JAVA_DIRS = ["src/server", "src/quicksetup", "src/ads", "src/guitools", "tests/unit-tests-testng/src"] |
| | | |
| | | # Replacement for Validator |
| | | # Modify 88 files, for a total of 227 replacements - leaves 21 compilation errors |
| | | VALIDATOR = { |
| | | :dirs => JAVA_DIRS, |
| | | :extensions => ["java"], |
| | | :replacements => |
| | | [ |
| | | /import org.opends.server.util.\*;/, |
| | | "import org.opends.server.util.*;\nimport org.forgerock.util.Reject;", |
| | | |
| | | /import static org.opends.server.util.Validator.ensureNotNull;/, |
| | | 'import static org.forgerock.util.Reject.ifNull;', |
| | | |
| | | /import static org.opends.server.util.Validator.ensureTrue;/, |
| | | 'import static org.forgerock.util.Reject.ifFalse;', |
| | | |
| | | /import static org.opends.server.util.Validator.\*;/, |
| | | 'import static org.forgerock.util.Reject.*;', |
| | | |
| | | /import org.opends.server.util.Validator;/, |
| | | 'import org.forgerock.util.Reject;', |
| | | |
| | | /(Validator\.| )ensureNotNull\((.*)$/, |
| | | '\1ifNull(\2', |
| | | |
| | | /(Validator\.| )ensureTrue\((.*)$/, |
| | | '\1ifFalse(\2', |
| | | |
| | | / Validator\./, |
| | | ' Reject.' |
| | | ] |
| | | } |
| | | |
| | | # Replacement for messages |
| | | # Modify 1052 files, for a total of 2366 replacements - leaves 10274 compilation errors mostly due to generated messages |
| | | MESSAGES = { |
| | | :dirs => JAVA_DIRS, |
| | | :extensions => ["java"], |
| | | :replacements => |
| | | [ |
| | | /import org.opends.messages.Message;/, |
| | | 'import org.forgerock.i18n.LocalizableMessage;', |
| | | |
| | | /([ <(])Message([ >)(.]|$)/, |
| | | '\1LocalizableMessage\2', |
| | | |
| | | /import org.opends.messages.MessageBuilder;/, |
| | | 'import org.forgerock.i18n.LocalizableMessageBuilder;', |
| | | |
| | | /([ <(])MessageBuilder([ >)(.]|$)/, |
| | | '\1LocalizableMessageBuilder\2' |
| | | ] |
| | | } |
| | | |
| | | # Replacement for types |
| | | # Modify 688 files, for a total of 783 replacements - leaves 7605 compilation errors |
| | | TYPES = { |
| | | :dirs => JAVA_DIRS, |
| | | :extensions => ["java"], |
| | | :replacements => |
| | | [ |
| | | /import org.opends.server.types.(DN|RDN|Attribute|ByteString|Entry|ResultCode);/, |
| | | 'import org.forgerock.opendj.ldap.\1;', |
| | | |
| | | /import org.opends.server.(types|api).(AttributeType|MatchingRule);/, |
| | | 'import org.forgerock.opendj.ldap.schema.\2;', |
| | | |
| | | ] |
| | | } |
| | | |
| | | # Replacement for exceptions |
| | | # Modify 36 files, for a total of 134 replacements - leaves 1277 compilation errors but mostly from generated config |
| | | EXCEPTIONS = { |
| | | :dirs => JAVA_DIRS, |
| | | :extensions => ["java"], |
| | | :replacements => |
| | | [ |
| | | /import org.opends.server.admin.client.AuthorizationException;/, |
| | | 'import org.forgerock.opendj.ldap.ErrorResultException;', |
| | | |
| | | /\bAuthorizationException\b/, |
| | | 'ErrorResultException', |
| | | |
| | | /import org.opends.server.admin.client.CommunicationException;\n/, |
| | | '', |
| | | |
| | | /throws CommunicationException\b, /, |
| | | 'throws ', |
| | | |
| | | /, CommunicationException\b(, )?/, |
| | | '\1', |
| | | |
| | | /\bCommunicationException\b/, |
| | | 'ErrorResultException', |
| | | ] |
| | | } |
| | | |
| | | # Replacement for loggers |
| | | # Modify 454 files, for a total of 2427 replacements - leaves 72 compilation errors |
| | | # TODO: add I18N loggers |
| | | LOGGERS = { |
| | | :dirs => JAVA_DIRS, |
| | | :stopwords => ['src/server/org/opends/server/loggers', 'DebugLogPublisher'], |
| | | :extensions => ["java"], |
| | | :replacements => |
| | | [ |
| | | /import org.opends.server.loggers.debug.DebugTracer;/, |
| | | "import org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;", |
| | | |
| | | /import java.util.logging.Logger;/, |
| | | "import org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;", |
| | | |
| | | /import java.util.logging.Level;\n/, |
| | | '', |
| | | |
| | | /import org.opends.server.types.DebugLogLevel;\n/, |
| | | '', |
| | | |
| | | /import (static )?org.opends.server.loggers.debug.DebugLogger.*;\n/, |
| | | '', |
| | | |
| | | /DebugTracer TRACER = (DebugLogger.)?getTracer\(\)/, |
| | | "Logger debugLogger = LoggerFactory.getLogger({CLASSNAME}.class)", |
| | | |
| | | /^\s*\/\*\*\n.*The tracer object for the debug logger.\n\s*\*\/$\n/, |
| | | '', |
| | | |
| | | /^\s*\/\/\s*The tracer object for the debug logger.$\n/, |
| | | '', |
| | | |
| | | /if \(debugEnabled\(\)\)\s*{\s* TRACER.debugCaught\(DebugLogLevel.ERROR, (\b.*\b)\);\s*\n\s*}$/, |
| | | 'debugLogger.trace("Error", \1);', |
| | | |
| | | /TRACER\.debugCaught\(DebugLogLevel.ERROR, (\b.*\b)\);/, |
| | | 'debugLogger.trace("Error", \1);', |
| | | |
| | | /TRACER.debug[^(]+\(/, |
| | | 'debugLogger.trace(', |
| | | |
| | | /debugLogger.trace\(DebugLogLevel.\b\w+\b, ?/, |
| | | 'debugLogger.trace(', |
| | | |
| | | /debugLogger.trace\(e\)/, |
| | | 'debugLogger.trace("Error", e)', |
| | | |
| | | /(DebugLogger\.|\b)debugEnabled\(\)/, |
| | | 'debugLogger.isTraceEnabled()', |
| | | |
| | | /(LOG|logger).log\((Level.)?WARNING, ?/, |
| | | '\1.warn(', |
| | | |
| | | /(LOG|logger).log\((Level.)?CONFIG, ?/, |
| | | '\1.info(', |
| | | |
| | | /(LOG|logger).log\((Level.)?INFO, ?/, |
| | | '\1.debug(', |
| | | |
| | | /(LOG|logger).log\((Level.)?SEVERE, ?/, |
| | | '\1.error(', |
| | | |
| | | /(LOG|logger).log\((Level.)?FINE, ?/, |
| | | '\1.trace(', |
| | | |
| | | /Logger.getLogger\((\n\s+)?(\b\w+\b).class.getName\(\)\);/, |
| | | 'LoggerFactory.getLogger(\2.class);', |
| | | ] |
| | | } |
| | | |
| | | # List of replacements to run |
| | | REPLACEMENTS = [ VALIDATOR ] |
| | | #REPLACEMENTS = [ VALIDATOR, MESSAGES, TYPES, EXCEPTIONS, LOGGERS ] |
| | | |
| | | # Run replacements |
| | | def run |
| | | REPLACEMENTS.each { |repl| |
| | | puts "Replacing " + Replace.constants.find{ |name| Replace.const_get(name)==repl }.to_s |
| | | stopwords = repl[:stopwords] || ["--nostopword--"] |
| | | replace_dirs(repl[:replacements], repl[:dirs], stopwords, repl[:extensions]) |
| | | } |
| | | end |
| | | |
| | | def replace_dirs(replacements, dirs, stopwords, extensions) |
| | | count_files = 0 |
| | | count_total = 0 |
| | | dirs.each { |directory| |
| | | files = files_under_directory(directory, extensions) |
| | | files.each { |file| |
| | | exclude_file = stopwords.any? { |stopword| file.include?(stopword) } |
| | | next if exclude_file |
| | | count = replace_file(file, replacements) |
| | | if count > 0 |
| | | count_files += 1 |
| | | count_total += count |
| | | end |
| | | } |
| | | } |
| | | puts "Replaced in #{count_files} files, for a total of #{count_total} replacements" |
| | | end |
| | | |
| | | def replace_file(file, replacements) |
| | | count = 0 |
| | | File.open(file) { |source| |
| | | contents = source.read |
| | | (0..replacements.size-1).step(2).each { |index| |
| | | pattern, replace = replacements[index], replacements[index+1] |
| | | replace = replace.gsub('{CLASSNAME}', classname(file)) |
| | | is_replaced = contents.gsub!(pattern, replace) |
| | | if is_replaced then count += 1 end |
| | | } |
| | | File.open(file + ".copy", "w+") { |f| f.write(contents) } |
| | | } |
| | | FileUtils.mv(file + ".copy", file, :verbose => false) |
| | | count |
| | | end |
| | | |
| | | def classname(file) |
| | | name = file.gsub(/.*\/(.*).java$/, '\1') |
| | | if name.nil? then '' else name end |
| | | end |
| | | |
| | | def files_under_directory(directory, extensions) |
| | | Dir[directory + '/**/*.{' + extensions.join(",") + '}'] |
| | | end |
| | | |
| | | end |
| | | |
| | | # Launch replacement |
| | | Replace.new.run |
| | | |