/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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.
*/
package com.alibaba.antx.config;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.alibaba.antx.config.descriptor.ConfigDescriptor;
import com.alibaba.antx.config.entry.ConfigEntry;
import com.alibaba.antx.config.entry.ConfigEntryFactory;
import com.alibaba.antx.config.entry.ConfigEntryFactoryImpl;
import com.alibaba.antx.config.props.PropertiesResource;
import com.alibaba.antx.config.props.PropertiesSet;
import com.alibaba.antx.config.wizard.text.ConfigWizardLoader;
import com.alibaba.antx.util.CharsetUtil;
import com.alibaba.antx.util.PatternSet;
import com.alibaba.antx.util.StringUtil;
public class ConfigRuntimeImpl implements ConfigRuntime {
private BufferedReader in;
private PrintWriter out;
private PrintWriter err;
private String charset;
private String mode;
private String interactiveMode;
private String type;
private PatternSet descriptorPatterns;
private PatternSet packagePatterns;
private String[] dests;
private String[] outputs;
private File[] destFiles;
private File[] outputFiles;
private PropertiesSet props;
private boolean verbose;
private File tempdir;
private ConfigEntryFactory configEntryFactory = new ConfigEntryFactoryImpl(this);
public ConfigRuntimeImpl() {
this(System.in, System.out, System.err, null);
}
public ConfigRuntimeImpl(InputStream inputStream, OutputStream outStream, OutputStream errStream, String charset) {
this.interactiveMode = ConfigConstant.INTERACTIVE_AUTO;
boolean charsetSpecified = !StringUtil.isEmpty(charset);
this.charset = charsetSpecified ? charset : CharsetUtil.detectedSystemCharset();
try {
in = new BufferedReader(new InputStreamReader(inputStream, this.charset));
out = new PrintWriter(new OutputStreamWriter(outStream, this.charset), true);
err = new PrintWriter(new OutputStreamWriter(errStream, this.charset), true);
} catch (UnsupportedEncodingException e) {
throw new ConfigException(e); // 不应发生
}
if (!charsetSpecified) {
out.println("Detected system charset encoding: " + this.charset);
out.println("If your can't read the following text, specify correct one like this: ");
out.println(" autoconfig -c mycharset");
out.println();
}
}
public BufferedReader getIn() {
return in;
}
public PrintWriter getOut() {
return out;
}
public PrintWriter getErr() {
return err;
}
public String getCharset() {
return charset;
}
public PatternSet getDescriptorPatterns() {
return descriptorPatterns;
}
public PatternSet getPackagePatterns() {
return packagePatterns;
}
public String getInteractiveMode() {
return interactiveMode;
}
public String getMode() {
return mode;
}
public File[] getDestFiles() {
return destFiles;
}
public File[] getOutputFiles() {
return outputFiles;
}
public PropertiesSet getPropertiesSet() {
if (props == null) {
props = new PropertiesSet(getIn(), getOut());
}
return props;
}
public boolean isVerbose() {
return verbose;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public ConfigEntryFactory getConfigEntryFactory() {
return configEntryFactory;
}
public void setDescriptorPatterns(String includes, String excludes) {
this.descriptorPatterns = new PatternSet(includes, excludes);
}
public void setDescriptorPatterns(String[] includes, String[] excludes) {
this.descriptorPatterns = new PatternSet(includes, excludes);
}
public void setPackagePatterns(String includes, String excludes) {
this.packagePatterns = new PatternSet(includes, excludes);
}
public void setPackagePatterns(String[] includes, String[] excludes) {
this.packagePatterns = new PatternSet(includes, excludes);
}
public void setInteractiveMode(String mode) {
if (ConfigConstant.INTERACTIVE_AUTO.equals(mode) || ConfigConstant.INTERACTIVE_ON.equals(mode)
|| ConfigConstant.INTERACTIVE_OFF.equals(mode)) {
this.interactiveMode = mode;
}
}
public void setGuiMode() {
mode = ConfigConstant.MODE_GUI;
}
public void setTextMode() {
mode = ConfigConstant.MODE_TEXT;
}
public void setDests(String[] dests) {
this.dests = dests;
}
public void setDestFiles(File[] destFiles) {
this.destFiles = destFiles.clone();
}
public void setOutputs(String[] outputs) {
this.outputs = outputs;
}
public void setOutputFiles(File[] outputFiles) {
this.outputFiles = outputFiles.clone();
}
public void setUserPropertiesFile(String userPropertiesFile, String charset) {
PropertiesSet props = getPropertiesSet();
props.setUserPropertiesFile(userPropertiesFile);
props.getUserPropertiesFile().setCharset(charset);
}
public void setSharedPropertiesFiles(String[] sharedPropertiesFiles, String name, String charset) {
getPropertiesSet().setSharedPropertiesFiles(sharedPropertiesFiles);
getPropertiesSet().setSharedPropertiesFilesName(name);
PropertiesResource[] resources = getPropertiesSet().getSharedPropertiesFiles();
for (PropertiesResource resource : resources) {
resource.setCharset(charset);
}
if (!StringUtil.isEmpty(name) || sharedPropertiesFiles != null && sharedPropertiesFiles.length > 0) {
this.interactiveMode = ConfigConstant.INTERACTIVE_ON;
}
}
public void setVerbose() {
this.verbose = true;
}
private void init() {
// tempdir
if (tempdir == null) {
tempdir = new File("");
}
tempdir = tempdir.getAbsoluteFile();
// dests
if (dests != null && dests.length > 0) {
destFiles = new File[dests.length];
for (int i = 0; i < dests.length; i++) {
destFiles[i] = new File(dests[i]).getAbsoluteFile();
}
} else {
destFiles = new File[0];
}
// outputs
if (outputs != null && outputs.length > 0) {
outputFiles = new File[outputs.length];
for (int i = 0; i < outputs.length; i++) {
if (outputs[i] != null) {
outputFiles[i] = new File(outputs[i]).getAbsoluteFile();
}
}
} else {
outputFiles = new File[destFiles.length];
}
if (outputFiles.length != destFiles.length) {
throw new IllegalArgumentException("Mismatched output files and dest files");
}
// user properties file
getPropertiesSet().init();
info("User-defined properties: " + getPropertiesSet().getUserPropertiesFile().getURI() + "\n");
}
public void debug(String message) {
if (verbose) {
getOut().println(message);
}
}
public void info(String message) {
getOut().println(message);
}
public void warn(String message) {
getOut().println(message);
}
public void error(String message) {
error(message, null);
}
public void error(Throwable cause) {
error(null, cause);
}
public void error(String message, Throwable cause) {
if (StringUtil.isBlank(message) && cause != null) {
message = "ERROR: " + cause.getMessage();
}
getErr().println(message);
if (verbose) {
cause.printStackTrace(getErr());
getErr().println();
}
}
public boolean start() {
return start(null);
}
public boolean start(ConfigDescriptor inlineDescriptor) {
init();
if (inlineDescriptor == null && ConfigConstant.MODE_GUI.equals(mode)) {
// MainWindow.run(this);
throw new UnsupportedOperationException("GUI mode currently unsupported");
} else if (inlineDescriptor == null) {
// 扫描所有文件或目录,取得要配置的entries
List entries = scan(false);
if (entries.isEmpty() && !ConfigConstant.INTERACTIVE_ON.equals(interactiveMode)) {
info("Nothing to configure");
return true;
}
ConfigWizardLoader wizard = new ConfigWizardLoader(this, entries);
// 交互式编辑props文件
wizard.loadAndStart();
// 生成配置文件
boolean allSuccess = true;
for (Iterator i = entries.iterator(); i.hasNext(); ) {
ConfigEntry entry = (ConfigEntry) i.next();
allSuccess &= entry.generate();
}
return allSuccess;
} else {
ConfigWizardLoader wizard = new ConfigWizardLoader(this, inlineDescriptor);
// 交互式编辑props文件
wizard.loadAndStart();
return true;
}
}
public List scan(boolean includeEmptyEntries) {
List entries = new ArrayList(destFiles.length);
for (int i = 0; i < destFiles.length; i++) {
File destFile = destFiles[i];
File outputFile = outputFiles[i];
ConfigEntry entry = getConfigEntryFactory().create(new ConfigResource(destFile), outputFile, type);
entry.scan();
if (includeEmptyEntries || !entry.isEmpty()) {
entries.add(entry);
}
}
return entries;
}
}