/* * Copyright (C) 2009 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.exoplatform.jcr.backupconsole; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; /** * Created by The eXo Platform SAS. <br>Date: * * @author <a href="karpenko.sergiy@gmail.com">Karpenko Sergiy</a> * @version $Id: BackupConsole.java 111 2008-11-11 11:11:11Z serg $ */ public class BackupConsole { /** * Incorrect parameter string. */ private static final String INCORRECT_PARAM = "Incorrect parameter: "; /** * Too many parameters string. */ private static final String TOO_MANY_PARAMS = "Too many parameters."; /** * Login password string. */ private static final String LOGIN_PASS_SPLITTER = ":"; /** * Force close session parameter string. */ private static final String FORCE_CLOSE = "force-close-session"; /** * Help string. */ private static final String HELP_INFO = "Help info:\n" + " <url_basic_authentication>|<url form authentication> <cmd> \n" + " <url_basic_authentication> : http(s)//login:password@host:port/<context> \n\n" + " <url form authentication> : http(s)//host:port/<context> \"<form auth parm>\" \n" + " <form auth parm> : form <method> <form path>\n" + " <method> : POST or GET\n" + " <form path> : /path/path?<paramName1>=<paramValue1>&<paramName2>=<paramValue2>...\n" + " Example to <url form authentication> : http://127.0.0.1:8080/portal/rest form POST \"/portal/login?initialURI=/portal/private&username=root&password=gtn\"\n\n" //NOSONAR + " <cmd> : start <repo[/ws]> <backup_dir> [<incr>] \n" + " stop <backup_id> \n" + " status <backup_id> \n" + " restores <repo[/ws]> \n" + " restore [remove-exists] {{<backup_id>|<backup_set_path>} | {<repo[/ws]> {<backup_id>|<backup_set_path>} [<pathToConfigFile>]}} \n" //NOSONAR + " list [completed] \n" + " info \n" + " drop [force-close-session] <repo[/ws]> \n" + " help \n\n" + " start - start backup of repository or workspace \n" + " stop - stop backup \n" + " status - information about the current or completed backup by 'backup_id' \n" + " restores - information about the last restore on specific repository or workspace \n" + " restore - restore the repository or workspace from specific backup \n" + " list - information about the current backups (in progress) \n" + " list completed - information about the completed (ready to restore) backups \n" + " info - information about the service backup \n" + " drop - delete the repository or workspace \n" + " help - print help information about backup console \n\n" + " <repo[/ws]> - /<reponsitory-name>[/<workspace-name>] the repository or workspace \n" + " <backup_dir> - path to folder for backup on remote server \n" + " <backup_id> - the identifier for backup \n" + " <backup_set_dir> - path to folder with backup set on remote server\n" + " <incr> - incemental job period \n" + " <pathToConfigFile> - path (local) to repository or workspace configuration \n" + " remove-exists - remove fully (db, value storage, index) exists repository/workspace \n" + " force-close-session - close opened sessions on repository or workspace. \n\n" + " All valid combination of parameters for command restore: \n" + " 1. restore remove-exists <repo/ws> <backup_id> <pathToConfigFile> \n" + " 2. restore remove-exists <repo> <backup_id> <pathToConfigFile> \n" + " 3. restore remove-exists <repo/ws> <backup_set_path> <pathToConfigFile> \n" + " 4. restore remove-exists <repo> <backup_set_path> <pathToConfigFile> \n" + " 5. restore remove-exists <backup_id> \n" + " 6. restore remove-exists <backup_set_path> \n" + " 7. restore <repo/ws> <backup_id> <pathToConfigFile> \n" + " 8. restore <repo> <backup_id> <pathToConfigFile> \n" + " 9. restore <repo/ws> <backup_set_path> <pathToConfigFile> \n" + " 10. restore <repo> <backup_set_path> <pathToConfigFile> \n" + " 11. restore <backup_id> \n" + " 12. restore <backup_set_path> \n"; /** * Main. * * @param args - * arguments used as parameters for execute backup server commands. */ public static void main(String[] args) { int curArg = 0; if (curArg == args.length) { System.out.println(INCORRECT_PARAM + "There is no any parameters."); //NOSONAR return; } // help if (args[curArg].equalsIgnoreCase("help")) { System.out.println(HELP_INFO); //NOSONAR return; } // url String sUrl = args[curArg]; curArg++; URL url; try { url = new URL(sUrl); } catch (MalformedURLException e) { System.out.println(INCORRECT_PARAM + "There is no url parameter."); //NOSONAR return; } String urlPath = null; if (!("".equals(url.getPath()))) urlPath = url.getPath(); // try form String form = null; if (curArg < args.length) { if (args[curArg].equals("form")) { form = args[curArg++]; if (url.getUserInfo() != null) { System.out //NOSONAR .println(INCORRECT_PARAM + "Parameters Login:Password should not be specified in url parameter to form authentication - " + sUrl); return; } } } // login:password String login = url.getUserInfo(); FormAuthentication formAuthentication = null; if (form != null && form.equals("form")) { //check POST or GET if (curArg == args.length) { System.out.println(INCORRECT_PARAM + "No specified POST or GET parameter to form parameter."); //NOSONAR return; } String method = args[curArg++]; if (!method.equalsIgnoreCase("GET") && !method.equalsIgnoreCase("POST")) { System.out.println(INCORRECT_PARAM //NOSONAR + "Method to form authentication shulde be GET or POST to form parameter - " + method); return; } //url to form authentication if (curArg == args.length) { System.out.println(INCORRECT_PARAM + "No specified url and form properties to form parameter."); //NOSONAR return; } String[] params = args[curArg++].split("[?]"); if (params.length != 2) { System.out //NOSONAR .println(INCORRECT_PARAM + "From parameters is not spacified to form parameter - " + args[curArg]); return; } String formUrl = params[0]; // parameters to form String[] formParams = params[1].split("&"); if (formParams.length < 2) { System.out.println(INCORRECT_PARAM //NOSONAR + "From parameters shoulde be conatains at least two (for login and for pasword) parameters - " //NOSONAR + params[1]); //NOSONAR return; } HashMap<String, String> mapFormParams = new HashMap<String, String>(); for (String fParam : formParams) { String[] para = fParam.split("="); if (para.length != 2) { System.out.println(INCORRECT_PARAM + "From parameters is incorect, shoulde be as \"name=value\" - " //NOSONAR + fParam); return; } mapFormParams.put(para[0], para[1]); } formAuthentication = new FormAuthentication(method, formUrl, mapFormParams); } else { if (login == null) { System.out.println(INCORRECT_PARAM + "There is no specific Login:Password in url parameter - " + sUrl); //NOSONAR return; } else if (!login.matches("[^:]+:[^:]+")) { System.out.println(INCORRECT_PARAM + "There is incorrect Login:Password parameter - " + login); //NOSONAR return; } } String host = url.getHost() + ":" + url.getPort(); // initialize transport and backup client ClientTransport transport; BackupClient client; if (formAuthentication != null) { transport = new ClientTransportImpl(formAuthentication, host, url.getProtocol()); client = new BackupClientImpl(transport, formAuthentication, urlPath); } else { String[] lp = login.split(LOGIN_PASS_SPLITTER); transport = new ClientTransportImpl(lp[0], lp[1], host, url.getProtocol()); client = new BackupClientImpl(transport, urlPath); } // commands if (curArg == args.length) { System.out.println(INCORRECT_PARAM + "There is no command parameter."); //NOSONAR return; } String command = args[curArg++]; try { if (command.equalsIgnoreCase("start")) { String pathToWS = getRepoWS(args, curArg++); if (pathToWS == null) return; String repositoryName = getRepositoryName(pathToWS); String workspaceName = (pathToWS.split("/").length == 3 ? getWorkspaceName(pathToWS) : null); String backupDir; if (curArg == args.length) { backupDir = null; } else { //check is incremental job period if (args[curArg].matches("[0-9]+")) { backupDir = null; } else { backupDir = args[curArg++]; } } if (curArg == args.length) { System.out.println(client.startBackUp(repositoryName, workspaceName, backupDir)); //NOSONAR } else { // incremental job period String incr = args[curArg++]; long inc = 0; try { inc = Long.parseLong(incr); } catch (NumberFormatException e) { System.out.println(INCORRECT_PARAM + "Incemental job period is not didgit - " + e.getMessage()); //NOSONAR return; } if (curArg < args.length) { System.out.println(TOO_MANY_PARAMS); //NOSONAR return; } System.out.println(client.startIncrementalBackUp(repositoryName, workspaceName, backupDir, inc)); //NOSONAR } } else if (command.equalsIgnoreCase("stop")) { if (curArg == args.length) { System.out.println(INCORRECT_PARAM + "There is no backup identifier parameter."); //NOSONAR return; } String backupId = args[curArg++]; if (curArg < args.length) { System.out.println(TOO_MANY_PARAMS); //NOSONAR return; } System.out.println(client.stop(backupId)); //NOSONAR } else if (command.equalsIgnoreCase("drop")) { if (curArg == args.length) { System.out.println(INCORRECT_PARAM + "There is no path to workspace or force-session-close parameter."); //NOSONAR return; } String param = args[curArg++]; boolean isForce = true; if (!param.equalsIgnoreCase(FORCE_CLOSE)) { curArg--; isForce = false; } String pathToWS = getRepoWS(args, curArg++); if (pathToWS == null) return; String repositoryName = getRepositoryName(pathToWS); String workspaceName = (pathToWS.split("/").length == 3 ? getWorkspaceName(pathToWS) : null); if (curArg < args.length) { System.out.println(TOO_MANY_PARAMS); //NOSONAR return; } System.out.println(client.drop(isForce, repositoryName, workspaceName)); //NOSONAR } else if (command.equalsIgnoreCase("status")) { if (curArg == args.length) { System.out.println(INCORRECT_PARAM + "There is no backup identifier parameter."); //NOSONAR return; } String backupId = args[curArg++]; if (curArg < args.length) { System.out.println(TOO_MANY_PARAMS); //NOSONAR return; } System.out.println(client.status(backupId)); //NOSONAR } else if (command.equalsIgnoreCase("info")) { if (curArg < args.length) { System.out.println(TOO_MANY_PARAMS); //NOSONAR return; } System.out.println(client.info()); //NOSONAR } else if (command.equalsIgnoreCase("restores")) { String pathToWS = getRepoWS(args, curArg++); if (pathToWS == null) return; String repositoryName = getRepositoryName(pathToWS); String workspaceName = (pathToWS.split("/").length == 3 ? getWorkspaceName(pathToWS) : null);; if (curArg < args.length) { System.out.println(TOO_MANY_PARAMS); //NOSONAR return; } System.out.println(client.restores(repositoryName, workspaceName)); //NOSONAR } else if (command.equalsIgnoreCase("list")) { if (curArg == args.length) { System.out.println(client.list()); //NOSONAR } else { String complated = args[curArg++]; if (complated.equalsIgnoreCase("completed")) { if (curArg < args.length) { System.out.println(TOO_MANY_PARAMS); //NOSONAR return; } System.out.println(client.listCompleted()); //NOSONAR } else { System.out.println(INCORRECT_PARAM + "There is no 'completed' parameter - " + complated); //NOSONAR return; } } } else if (command.equalsIgnoreCase("restore")) { /* All valid combination of parameters for command restore. 1. restore remove-exists <repo/ws> <backup_id> <pathToConfigFile> 2. restore remove-exists <repo> <backup_id> <pathToConfigFile> 3. restore remove-exists <repo/ws> <backup_set_path> <pathToConfigFile> 4. restore remove-exists <repo> <backup_set_path> <pathToConfigFile> 5. restore remove-exists <backup_id> 6. restore remove-exists <backup_set_path> 7. restore <repo/ws> <backup_id> <pathToConfigFile> 8. restore <repo> <backup_id> <pathToConfigFile> 9. restore <repo/ws> <backup_set_path> <pathToConfigFile> 10. restore <repo> <backup_set_path> <pathToConfigFile> 11. restore <backup_id> 12. restore <backup_set_path> */ boolean removeExists = false; String backupSetPath = null; String backupId = null; String pathToWS = null; String repositoryName = null; String workspaceName = null; String parameter = args[curArg++]; //check remove-exists if (parameter.equals("remove-exists")) { removeExists = true; if (curArg == args.length) { System.out.println(INCORRECT_PARAM + "Should be more parameters."); //NOSONAR return; } } if (removeExists) { parameter = args[curArg++]; } //check backup_id if (isBackupId(parameter)) { backupId = parameter; curArg++; if (curArg < args.length) { System.out.println(TOO_MANY_PARAMS); //NOSONAR return; } //5. restore remove-exists <backup_id> //11. restore <backup_id> System.out.println(client.restore(repositoryName, workspaceName, backupId, null, backupSetPath, //NOSONAR removeExists)); return; } //check /repo/ws or /repo else if (isRepoWS(parameter)) { pathToWS = getRepoWS(args, curArg - 1); if (pathToWS == null) return; repositoryName = getRepositoryName(pathToWS); workspaceName = (pathToWS.split("/").length == 3 ? getWorkspaceName(pathToWS) : null); } // this is backup_set_path else { backupSetPath = parameter; if (curArg < args.length) { System.out.println(INCORRECT_PARAM + "Should be less parameters : " + parameter); //NOSONAR return; } //6. restore remove-exists <backup_set_path> //12. restore <backup_set_path> System.out.println(client.restore(repositoryName, workspaceName, backupId, null, backupSetPath, //NOSONAR removeExists)); return; } // check backup_id or backup_set_path if (curArg == args.length) { System.out.println(INCORRECT_PARAM + "There is no backup identifier or backup set path parameter."); //NOSONAR return; } parameter = args[curArg++]; if (isBackupId(parameter)) { backupId = parameter; } else { backupSetPath = parameter; } if (curArg == args.length) { System.out.println(INCORRECT_PARAM + "The path to the configuration file is missing."); //NOSONAR return; } String pathToConf = args[curArg++]; File conf = new File(pathToConf); if (!conf.exists()) { System.out.println(" File " + pathToConf + " do not exist. Check the path."); //NOSONAR return; } if (curArg < args.length) { System.out.println(TOO_MANY_PARAMS); //NOSONAR return; } /* 1. restore remove-exists <repo/ws> <backup_id> <pathToConfigFile> 2. restore remove-exists <repo> <backup_id> <pathToConfigFile> 3. restore remove-exists <repo/ws> <backup_set_path> <pathToConfigFile> 4. restore remove-exists <repo> <backup_set_path> <pathToConfigFile> 7. restore <repo/ws> <backup_id> <pathToConfigFile> 8. restore <repo> <backup_id> <pathToConfigFile> 9. restore <repo/ws> <backup_set_path> <pathToConfigFile> 10. restore <repo> <backup_set_path> <pathToConfigFile> */ System.out.println(client.restore(repositoryName, workspaceName, backupId, new FileInputStream(conf), //NOSONAR backupSetPath, removeExists)); } else { System.out.println("Unknown command <" + command + ">"); //NOSONAR } } catch (IOException e) { System.out.println("ERROR: " + e.getMessage()); //NOSONAR e.printStackTrace(); //NOSONAR } catch (BackupExecuteException e) { System.out.println("ERROR: " + e.getMessage()); //NOSONAR e.printStackTrace(); //NOSONAR } System.exit(0); } /** * Check is "/repo" or "/repo/ws" parameter. * * @param parameter * String, parameter. * @return Boolean * return "true" if it "/repo" or "/repo/ws" parameter */ private static boolean isRepoWS(String parameter) { String repWS = parameter; repWS = repWS.replaceAll("\\\\", "/"); if ( !repWS.matches("[/][^/]+") && !repWS.matches("[/][^/]+[/][^/]+")) { return false; } else { return true; } } /** * Check is backip_id parameter. * * @param firstParameter * String, parameter. * @return Boolean * return "true" if it backup identifier parameter */ private static boolean isBackupId(String parameter) { return parameter.matches("[0-9abcdef]+") && parameter.length() == 32; } /** * getWorkspaceName. * * @param pathToWS * the /<repository-name>/<workspace name> * @return String return the workspace name */ private static String getWorkspaceName(String pathToWS) { return pathToWS.split("/")[2]; } /** * getRepositoryName. * * @param pathToWS * the /<repository-name>/<workspace name> * @return String return the repository name */ private static String getRepositoryName(String pathToWS) { return pathToWS.split("/")[1]; } /** * Get parameter from argument list, check it and return as valid path to repository and * workspace. * * @param args * list of arguments. * @param curArg * argument index. * @return String valid path. */ private static String getRepoWS(String[] args, int curArg) { if (curArg == args.length) { System.out.println(INCORRECT_PARAM + "There is no path to workspace parameter."); //NOSONAR return null; } // make correct path String repWS = args[curArg]; repWS = repWS.replaceAll("\\\\", "/"); if ( !repWS.matches("[/][^/]+") && !repWS.matches("[/][^/]+[/][^/]+")) { System.out.println(INCORRECT_PARAM + "There is incorrect path to workspace parameter: " + repWS); //NOSONAR return null; } else { return repWS; } } }