Java tutorial
/* * ***** BEGIN LICENSE BLOCK ***** * Zimbra Collaboration Suite Server * Copyright (C) 2009, 2010, 2013, 2014, 2015, 2016 Synacor, Inc. * * This program 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, * version 2 of the License. * * 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 <https://www.gnu.org/licenses/>. * ***** END LICENSE BLOCK ***** */ package com.zimbra.common.localconfig; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.GnuParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.dom4j.DocumentException; import com.zimbra.common.service.ServiceException; import com.zimbra.common.util.CliUtil; import com.zimbra.common.util.ZimbraLog; public abstract class LocalConfigUpgrade { private static String O_HELP = "h"; private static String O_BUG = "b"; private static String O_CONFIG = "c"; private static String O_TAG = "t"; private static Options getAllOptions() { Options options = new Options(); options.addOption(O_HELP, "help", false, "print usage"); options.addOption(O_CONFIG, "config", true, "path to localconfig.xml"); options.addOption(O_TAG, "tag", true, "backup and tag with this suffix"); Option bugOpt = new Option(O_BUG, "bug", true, "bug number this upgrade is for (multiple allowed)"); bugOpt.setArgs(Option.UNLIMITED_VALUES); options.addOption(bugOpt); return options; } private static String getCommandUsage() { return "com.zimbra.common.localconfig.LocalConfigUpgrade <options>"; } static void usage(String error) { if (error != null) System.out.println("Error: " + error); Options opts = getAllOptions(); PrintWriter pw = new PrintWriter(System.out, true); HelpFormatter formatter = new HelpFormatter(); formatter.printHelp(pw, formatter.getWidth(), getCommandUsage(), null, opts, formatter.getLeftPadding(), formatter.getDescPadding(), null); pw.flush(); if (error != null) { System.exit(1); } else { System.exit(0); } } private final String mBug; private final String mShortName; LocalConfigUpgrade(String bug, String shortName) { mBug = bug; mShortName = shortName; sUpgrades.put(bug, this); } protected abstract void upgrade(LocalConfig lc) throws ConfigException; private static final boolean TRACE = false; private static boolean hasOption(String option, String value) { if (TRACE) System.out.println("hasOption: option=" + option); if (TRACE) System.out.println("hasOption: value=" + value); // option is in the middle String mre = "^.*\\s+\\Q" + value + "\\E\\s+.*$"; if (option.matches(mre)) { if (TRACE) System.out.println("hasOption: matched mre=" + mre); return true; } // option is in the end String ere = "^.*\\s+\\Q" + value + "\\E\\s*$"; if (option.matches(ere)) { if (TRACE) System.out.println("hasOption: matched ere=" + ere); return true; } // option is in the beginning String bre = "^\\s*\\Q" + value + "\\E\\s+.*$"; if (option.matches(bre)) { if (TRACE) System.out.println("hasOption: matched bre=" + bre); return true; } if (TRACE) System.out.println("hasOption: matched none"); return false; } private static boolean hasOptionThatBeginsWith(String option, String value) { if (TRACE) System.out.println("hasOptionBegins: option=" + option); if (TRACE) System.out.println("hasOptionBegins: value=" + value); // at middle or end String moere = "^.*\\s+\\Q" + value + "\\E.*$"; if (option.matches(moere)) { if (TRACE) System.out.println("hasOptionBegins: matched moere=" + moere); return true; } // at beginning String ere = "^\\s*\\Q" + value + "\\E.*$"; if (option.matches(ere)) { if (TRACE) System.out.println("hasOptionBegins: matched ere=" + ere); return true; } if (TRACE) System.out.println("hasOptionBegins: matched none"); return false; } private static String appendOptionIfNotPresent(String mjo, String option) { if (hasOption(mjo, option)) { return mjo; } return mjo + " " + option; } private static String prependOption(String mjo, String option) { if (hasOption(mjo, option)) { return mjo; } return option + " " + mjo; } private static String appendOptionIfNoOptionBeginsWith(String mjo, String match, String option) { if (hasOptionThatBeginsWith(mjo, match)) { return mjo; } return mjo + " " + option; } private static String removeOption(String mjo, String option) { // option is in the middle mjo = mjo.replaceAll("\\s+\\Q" + option + "\\E\\s+", " "); // option is in the end mjo = mjo.replaceAll("\\s+\\Q" + option + "\\E\\s*$", ""); // option is in the beginning mjo = mjo.replaceAll("^\\s*\\Q" + option + "\\E\\s+", ""); // only option is present mjo = mjo.replaceAll("^\\s*\\Q" + option + "\\E\\s*$", ""); return mjo; } private static String removeOptionWithValue(String mjo, String option) { return mjo.replaceAll("\\s*\\Q" + option + "=\\E\\w+", ""); } private static class LocalConfigUpgradeSwitchToCMS extends LocalConfigUpgrade { LocalConfigUpgradeSwitchToCMS(String bug) { super(bug, "SwitchToCMS"); } public static void main(String[] args) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < args.length; i++) { sb.append(args[i]); if (i < (args.length - 1)) { sb.append(' '); } } String mjo = sb.toString(); System.out.println("before: " + mjo); System.out.println("after: " + new LocalConfigUpgradeSwitchToCMS("testbug").modify(mjo)); } @Override protected void upgrade(LocalConfig lc) throws ConfigException { String key = LC.mailboxd_java_options.key(); String mjo = lc.getRaw(key); System.out.println("Old " + key + "=" + mjo); mjo = modify(mjo); System.out.println("New " + key + "=" + mjo); lc.set(key, mjo); } private String modify(String mjo) { mjo = removeOption(mjo, "-XX:+UseParallelGC"); mjo = removeOptionWithValue(mjo, "-XX:NewRatio"); mjo = appendOptionIfNotPresent(mjo, "-XX:+UseConcMarkSweepGC"); mjo = appendOptionIfNotPresent(mjo, "-verbose:gc"); mjo = appendOptionIfNotPresent(mjo, "-XX:+PrintGCDetails"); mjo = appendOptionIfNotPresent(mjo, "-XX:+PrintGCTimeStamps"); mjo = appendOptionIfNotPresent(mjo, "-XX:+PrintGCApplicationStoppedTime"); mjo = appendOptionIfNoOptionBeginsWith(mjo, "-XX:SoftRefLRUPolicyMSPerMB=", "-XX:SoftRefLRUPolicyMSPerMB=1"); return mjo; } } private static class LocalConfigUpgradeSwitchToServerJVM extends LocalConfigUpgrade { LocalConfigUpgradeSwitchToServerJVM(String bug) { super(bug, "SwitchToServerJVM"); } public static void main(String[] args) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < args.length; i++) { sb.append(args[i]); if (i < (args.length - 1)) { sb.append(' '); } } String mjo = sb.toString(); System.out.println("before: " + mjo); System.out.println("after: " + new LocalConfigUpgradeSwitchToServerJVM("testme").modify(mjo)); } @Override protected void upgrade(LocalConfig lc) throws ConfigException { String key = LC.mailboxd_java_options.key(); String mjo = lc.getRaw(key); System.out.println("Old " + key + "=" + mjo); mjo = modify(mjo); System.out.println("New " + key + "=" + mjo); lc.set(key, mjo); } private String modify(String mjo) { mjo = removeOption(mjo, "-client"); mjo = removeOption(mjo, "-server"); mjo = prependOption(mjo, "-server"); return mjo; } } private static class LocalConfigUpgradeUnsetMailboxdJavaHome extends LocalConfigUpgrade { public LocalConfigUpgradeUnsetMailboxdJavaHome(String bug) { super(bug, "UnsetMailboxdJavaHome"); } @Override protected void upgrade(LocalConfig lc) { lc.remove("mailboxd_java_home"); } } private final static HashMap<String, LocalConfigUpgrade> sUpgrades; static { sUpgrades = new HashMap<String, LocalConfigUpgrade>(); new LocalConfigUpgradeSwitchToCMS("37842"); new LocalConfigUpgradeSwitchToServerJVM("37844"); new LocalConfigUpgradeUnsetMailboxdJavaHome("37802"); } public static void main(String[] args) throws ServiceException { CliUtil.toolSetup(); CommandLine cl = null; try { CommandLineParser parser = new GnuParser(); Options options = getAllOptions(); cl = parser.parse(options, args); if (cl == null) throw new ParseException(""); } catch (ParseException pe) { usage(pe.getMessage()); } if (cl.hasOption(O_HELP)) { usage(null); } if (!cl.hasOption(O_BUG)) { usage("no bug specified"); } if (!cl.hasOption(O_TAG)) { usage("no backup suffix tag specified"); } LocalConfig lc = null; try { lc = new LocalConfig(cl.getOptionValue("c")); lc.backup(cl.getOptionValue("t")); } catch (DocumentException de) { ZimbraLog.misc.error("failed reading config file", de); System.exit(1); } catch (ConfigException ce) { ZimbraLog.misc.error("failed reading config file", ce); System.exit(2); } catch (IOException ioe) { ZimbraLog.misc.error("failed to backup config file", ioe); System.exit(3); } String[] bugs = cl.getOptionValues(O_BUG); for (String bug : bugs) { if (!sUpgrades.containsKey(bug)) { ZimbraLog.misc.warn("local config upgrade can't handle bug " + bug); continue; } LocalConfigUpgrade lcu = sUpgrades.get(bug); System.out.println("== Running local config upgrade for bug " + lcu.mBug + " (" + lcu.mShortName + ")"); try { lcu.upgrade(lc); System.out .println("== Done local config upgrade for bug " + lcu.mBug + " (" + lcu.mShortName + ")"); } catch (ConfigException e) { // TODO Auto-generated catch block e.printStackTrace(); } } try { lc.save(); } catch (IOException ioe) { ZimbraLog.misc.error("failed writing config file", ioe); System.exit(1); } catch (ConfigException ce) { ZimbraLog.misc.error("failed writing config file", ce); System.exit(1); } } }