📄 saveservice.java
字号:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.jmeter.save;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.nio.charset.Charset;
import org.apache.jmeter.samplers.SampleEvent;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.collections.HashTree;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.jorphan.util.JMeterError;
import org.apache.jorphan.util.JOrphanUtils;
import org.apache.log.Logger;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.XppDriver;
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
import com.thoughtworks.xstream.mapper.Mapper;
import com.thoughtworks.xstream.mapper.MapperWrapper;
import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.DataHolder;
import com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider;
/**
* Handles setting up XStream serialisation.
* The class reads alias definitions from saveservice.properties.
*
*/
public class SaveService {
private static final Logger log = LoggingManager.getLoggerForClass();
public static final String SAMPLE_EVENT_OBJECT = "SampleEvent"; // $NON-NLS-1$
private static final XStream saver = new XStream(new PureJavaReflectionProvider()){
// Override wrapMapper in order to insert the Wrapper in the chain
protected MapperWrapper wrapMapper(MapperWrapper next) {
// Provide our own aliasing using strings rather than classes
return new MapperWrapper(next){
// Translate alias to classname and then delegate to wrapped class
public Class realClass(String alias) {
String fullName = aliasToClass(alias);
return super.realClass(fullName == null ? alias : fullName);
}
// Translate to alias and then delegate to wrapped class
public String serializedClass(Class type) {
if (type == null) {
return super.serializedClass(null); // was type, but that caused FindBugs warning
}
String alias = classToAlias(type.getName());
return alias == null ? super.serializedClass(type) : alias ;
}
};
}
};
// The XML header, with placeholder for encoding, since that is controlled by property
private static final String XML_HEADER = "<?xml version=\"1.0\" encoding=\"<ph>\"?>"; // $NON-NLS-1$
// Default file name
private static final String SAVESERVICE_PROPERTIES_FILE = "/bin/saveservice.properties"; // $NON-NLS-1$
// Property name used to define file name
private static final String SAVESERVICE_PROPERTIES = "saveservice_properties"; // $NON-NLS-1$
// Define file format property names
private static final String FILE_FORMAT = "file_format"; // $NON-NLS-1$
private static final String FILE_FORMAT_TESTPLAN = "file_format.testplan"; // $NON-NLS-1$
private static final String FILE_FORMAT_TESTLOG = "file_format.testlog"; // $NON-NLS-1$
// Define file format versions
private static final String VERSION_2_0 = "2.0"; // $NON-NLS-1$
//NOT USED private static final String VERSION_2_1 = "2.1"; // $NON-NLS-1$
private static final String VERSION_2_2 = "2.2"; // $NON-NLS-1$
// Default to overall format, and then to version 2.2
public static final String TESTPLAN_FORMAT
= JMeterUtils.getPropDefault(FILE_FORMAT_TESTPLAN
, JMeterUtils.getPropDefault(FILE_FORMAT, VERSION_2_2));
public static final String TESTLOG_FORMAT
= JMeterUtils.getPropDefault(FILE_FORMAT_TESTLOG
, JMeterUtils.getPropDefault(FILE_FORMAT, VERSION_2_2));
private static final boolean IS_TESTPLAN_FORMAT_20
= VERSION_2_0.equals(TESTPLAN_FORMAT);
private static final boolean IS_TESTLOG_FORMAT_20
= VERSION_2_0.equals(TESTLOG_FORMAT);
private static final boolean IS_TESTPLAN_FORMAT_22
= VERSION_2_2.equals(TESTPLAN_FORMAT);
// Holds the mappings from the saveservice properties file
private static final Properties aliasToClass = new Properties();
// Holds the reverse mappings
private static final Properties classToAlias = new Properties();
// Version information for test plan header
// This is written to JMX files by ScriptWrapperConverter
// Also to JTL files by ResultCollector
private static final String VERSION = "1.2"; // $NON-NLS-1$
// This is written to JMX files by ScriptWrapperConverter
private static String propertiesVersion = "";// read from properties file; written to JMX files
private static final String PROPVERSION = "2.0";// Expected version $NON-NLS-1$
// Internal information only
private static String fileVersion = ""; // read from properties file// $NON-NLS-1$
private static final String FILEVERSION = "594567"; // Expected value $NON-NLS-1$
private static String fileEncoding = ""; // read from properties file// $NON-NLS-1$
static {
log.info("Testplan (JMX) version: "+TESTPLAN_FORMAT+". Testlog (JTL) version: "+TESTLOG_FORMAT);
initProps();
checkVersions();
}
// Helper method to simplify alias creation from properties
private static void makeAlias(String alias, String clazz) {
aliasToClass.setProperty(alias,clazz);
Object oldval=classToAlias.setProperty(clazz,alias);
if (oldval != null) {
log.error("Duplicate alias detected for "+clazz+": "+alias+" & "+oldval);
}
}
public static Properties loadProperties() throws IOException{
Properties nameMap = new Properties();
FileInputStream fis = null;
try {
fis = new FileInputStream(JMeterUtils.getJMeterHome()
+ JMeterUtils.getPropDefault(SAVESERVICE_PROPERTIES, SAVESERVICE_PROPERTIES_FILE));
nameMap.load(fis);
} finally {
JOrphanUtils.closeQuietly(fis);
}
return nameMap;
}
private static void initProps() {
// Load the alias properties
try {
Properties nameMap = loadProperties();
// now create the aliases
Iterator it = nameMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry me = (Map.Entry) it.next();
String key = (String) me.getKey();
String val = (String) me.getValue();
if (!key.startsWith("_")) {
makeAlias(key, val);
} else {
// process special keys
if (key.equalsIgnoreCase("_version")) { // $NON-NLS-1$
propertiesVersion = val;
log.info("Using SaveService properties version " + propertiesVersion);
} else if (key.equalsIgnoreCase("_file_version")) { // $NON-NLS-1$
fileVersion = extractVersion(val);
log.info("Using SaveService properties file version " + fileVersion);
} else if (key.equalsIgnoreCase("_file_encoding")) { // $NON-NLS-1$
fileEncoding = val;
log.info("Using SaveService properties file encoding " + fileEncoding);
} else {
key = key.substring(1);// Remove the leading "_"
try {
if (val.trim().equals("collection")) { // $NON-NLS-1$
saver.registerConverter((Converter) Class.forName(key).getConstructor(
new Class[] { Mapper.class }).newInstance(
new Object[] { saver.getMapper() }));
} else if (val.trim().equals("mapping")) { // $NON-NLS-1$
saver.registerConverter((Converter) Class.forName(key).getConstructor(
new Class[] { Mapper.class }).newInstance(
new Object[] { saver.getMapper() }));
} else {
saver.registerConverter((Converter) Class.forName(key).newInstance());
}
} catch (IllegalAccessException e1) {
log.warn("Can't register a converter: " + key, e1);
} catch (InstantiationException e1) {
log.warn("Can't register a converter: " + key, e1);
} catch (ClassNotFoundException e1) {
log.warn("Can't register a converter: " + key, e1);
} catch (IllegalArgumentException e1) {
log.warn("Can't register a converter: " + key, e1);
} catch (SecurityException e1) {
log.warn("Can't register a converter: " + key, e1);
} catch (InvocationTargetException e1) {
log.warn("Can't register a converter: " + key, e1);
} catch (NoSuchMethodException e1) {
log.warn("Can't register a converter: " + key, e1);
}
}
}
}
} catch (IOException e) {
log.fatalError("Bad saveservice properties file", e);
throw new JMeterError("JMeter requires the saveservice properties file to continue");
}
}
// For converters to use
public static String aliasToClass(String s){
String r = aliasToClass.getProperty(s);
return r == null ? s : r;
}
// For converters to use
public static String classToAlias(String s){
String r = classToAlias.getProperty(s);
return r == null ? s : r;
}
// Called by Save function
public static void saveTree(HashTree tree, OutputStream out) throws IOException {
// Get the OutputWriter to use
OutputStreamWriter outputStreamWriter = getOutputStreamWriter(out);
writeXmlHeader(outputStreamWriter);
// Use deprecated method, to avoid duplicating code
ScriptWrapper wrapper = new ScriptWrapper();
wrapper.testPlan = tree;
saver.toXML(wrapper, outputStreamWriter);
outputStreamWriter.write('\n');// Ensure terminated properly
outputStreamWriter.close();
}
// Used by Test code
public static void saveElement(Object el, OutputStream out) throws IOException {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -