/*
* Tencent is pleased to support the open source community by making Tinker available.
*
* Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.
*/
package com.tencent.tinker.patch;
import com.tencent.tinker.build.patch.Configuration;
import com.tencent.tinker.build.patch.Runner;
import com.tencent.tinker.build.util.Logger;
import com.tencent.tinker.build.util.TinkerPatchException;
import com.tencent.tinker.build.util.TypedValue;
import org.xml.sax.SAXException;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.xml.parsers.ParserConfigurationException;
/**
* Created by zhangshaowen on 2/27/16.
* do not use Logger here
*/
public class CliMain extends Runner {
private static final String ARG_HELP = "--help";
private static final String ARG_OUT = "-out";
private static final String ARG_CONFIG = "-config";
private static final String ARG_OLD = "-old";
private static final String ARG_NEW = "-new";
protected static String mRunningLocation;
public static void main(String[] args) {
mBeginTime = System.currentTimeMillis();
CliMain m = new CliMain();
setRunningLocation(m);
m.run(args);
}
private static void setRunningLocation(CliMain m) {
mRunningLocation = m.getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
try {
mRunningLocation = URLDecoder.decode(mRunningLocation, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (mRunningLocation.endsWith(".jar")) {
mRunningLocation = mRunningLocation.substring(0, mRunningLocation.lastIndexOf(File.separator) + 1);
}
File f = new File(mRunningLocation);
mRunningLocation = f.getAbsolutePath();
}
private static void printUsage(PrintStream out) {
// TODO: Look up launcher script name!
String command = "tinker.jar"; //$NON-NLS-1$
out.println();
out.println();
out.println("Usage: java -jar " + command + " " + ARG_OLD + " old.apk " + ARG_NEW + " new.apk " + ARG_CONFIG + " tinker_config.xml " + ARG_OUT + " output_path");
out.println("others please contact us");
}
private void run(String[] args) {
if (args.length < 1) {
goToError();
}
try {
ReadArgs readArgs = new ReadArgs(args).invoke();
File configFile = readArgs.getConfigFile();
File outputFile = readArgs.getOutputFile();
File oldApkFile = readArgs.getOldApkFile();
File newApkFile = readArgs.getNewApkFile();
if (oldApkFile == null || newApkFile == null) {
Logger.e("Missing old apk or new apk file argument");
goToError();
} else if (!oldApkFile.exists() || !newApkFile.exists()) {
Logger.e("Old apk or new apk file does not exist");
goToError();
}
if (outputFile == null) {
outputFile = new File(mRunningLocation, TypedValue.PATH_DEFAULT_OUTPUT);
}
loadConfigFromXml(configFile, outputFile, oldApkFile, newApkFile);
Logger.initLogger(config);
tinkerPatch();
} catch (IOException e) {
e.printStackTrace();
goToError();
} finally {
Logger.closeLogger();
}
}
private void loadConfigFromXml(File configFile, File outputFile, File oldApkFile, File newApkFile) {
if (configFile == null) {
configFile = new File(mRunningLocation + File.separator + TypedValue.FILE_CONFIG);
if (!configFile.exists()) {
System.err.printf("the config file %s does not exit\n", configFile.getAbsolutePath());
printUsage(System.err);
System.exit(ERRNO_USAGE);
}
}
try {
config = new Configuration(configFile, outputFile, oldApkFile, newApkFile);
} catch (IOException | ParserConfigurationException | SAXException e) {
e.printStackTrace();
goToError();
} catch (TinkerPatchException e) {
e.printStackTrace();
goToError();
}
}
public void goToError() {
printUsage(System.err);
System.exit(ERRNO_USAGE);
}
private class ReadArgs {
private String[] args;
private File configFile;
private File outputFile;
private File oldApkFile;
private File newApkFile;
ReadArgs(String[] args) {
this.args = args;
}
public File getConfigFile() {
return configFile;
}
public File getOutputFile() {
return outputFile;
}
public File getOldApkFile() {
return oldApkFile;
}
public File getNewApkFile() {
return newApkFile;
}
public ReadArgs invoke() {
for (int index = 0; index < args.length; index++) {
String arg = args[index];
if (arg.equals(ARG_HELP) || arg.equals("-h")) {
goToError();
} else if (arg.equals(ARG_CONFIG)) {
if (index == args.length - 1 || !args[index + 1].endsWith(TypedValue.FILE_XML)) {
System.err.println("Missing XML configuration file argument");
goToError();
}
configFile = new File(args[++index]);
if (!configFile.exists()) {
System.err.println(configFile.getAbsolutePath() + " does not exist");
goToError();
}
System.out.println("special configFile file path:" + configFile.getAbsolutePath());
} else if (arg.equals(ARG_OUT)) {
if (index == args.length - 1) {
System.err.println("Missing output file argument");
goToError();
}
outputFile = new File(args[++index]);
File parent = outputFile.getParentFile();
if (parent != null && (!parent.exists())) {
parent.mkdirs();
}
System.out.printf("special output directory path: %s\n", outputFile.getAbsolutePath());
} else if (arg.equals(ARG_OLD)) {
if (index == args.length - 1) {
System.err.println("Missing old apk file argument");
goToError();
}
oldApkFile = new File(args[++index]);
} else if (arg.equals(ARG_NEW)) {
if (index == args.length - 1) {
System.err.println("Missing new apk file argument");
goToError();
}
newApkFile = new File(args[++index]);
}
}
return this;
}
}
}