在此只写了一个8583报文的拆包,组包其实也差不多的。

不多说直接上文件,

具体思路过程,在解析类里面写的有。

其中包含了四个文件

8583resp.txt报文

ISO8583medata配置文件

Bean8583Factory.java 8583配置文件解析类

Parse8583.java 8583报文解析类

8583报文

29 01 30 34 31 30 30 30 30 30 30 30 30 30 30 30
30 30 30 30 30 30 30 30 30 30 30 30 00 00 00 00
30 38 34 31 30 31 36 32 00 30 32 31 30 F2 3E 40
81 8E F0 80 00 00 00 00 00 10 00 00 E1 31 36 35
32 33 39 35 39 30 30 30 30 31 34 31 32 32 38 30
30 30 30 30 30 30 30 30 30 30 30 30 39 38 37 36
31 30 39 30 38 31 34 35 33 33 34 34 31 30 31 36
32 31 34 35 33 33 34 30 39 30 38 33 30 30 38 30
31 30 35 36 30 31 33 30 30 30 38 36 33 30 34 30
32 35 30 30 38 36 33 30 34 30 30 30 30 30 30 30
30 30 30 34 31 30 31 36 32 35 35 35 33 32 32 30
30 37 37 37 37 37 37 37 37 30 32 38 30 30 30 30
31 30 39 20 20 20 20 20 B4 FA C0 ED C6 F3 D2 B5
CD F8 D2 F8 D7 A8 D3 C3 B2 E2 CA D4 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
32 35 30 30 30 30 30 30 30 30 30 30 30 30 30 30
30 30 30 30 30 30 30 30 30 30 30 31 35 36 30 38
36 33 30 34 30 30 30 30 30 30 30 30 31 38 20 20
20 20 20 20 20 20 20 20 20 20 B2 E2 CA D4 31 34
30 39 35 4E 20 20 30 30 30 31 30 31 39 35 33 37
37 30 30 30 30 30 30 35 30 30 30 30 20 20 30 30
30 30 30 30 20 20 30 30 32 20 2D 30 30 35 34 36
37 32 35 31 30 30 30 30 30 30 30 30 30 30 30 30
30 30 30 30 30 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
31 30 33 43 34 44 45 44 33 37

8583配置文件

<?xml version="1.0" encoding="utf-8"?>
<sdoroot package_type="iso8583" store-mode="GBK">
<H1 type="string" length="1" isHeader="true" encoding="GBK" isBCD="true"/>
<H2 type="string" length="1" isHeader="true" encoding="GBK" isBCD="true"/>
<H3 type="string" length="4" isHeader="true" encoding="GBK"/>
<H4 type="string" length="11" isHeader="true" encoding="GBK"/>
<H5 type="string" length="11" isHeader="true" encoding="GBK"/>
<H6 type="string" length="3" isHeader="true" encoding="GBK" isBCD="true"/>
<H7 type="string" length="1" isHeader="true" encoding="GBK" isBCD="true"/>
<H8 type="string" length="8" isHeader="true" encoding="GBK" />
<H9 type="string" length="1" isHeader="true" encoding="GBK" isBCD="true"/>
<MsgType type="string" length="4" encoding="GBK"/>
<bitmap1 length="8" type="bitmap"/>
<bitmap2 length="8" type="bitmap"/>
<F2 type="string" length="19" variable_flag="2" field_index="2" encoding="GBK"/>
<F3 type="string" length="6" field_index="3" encoding="GBK"/>
<F4 type="string" length="12" field_index="4" encoding="GBK"/>
<F6 type="string" length="12" field_index="6" encoding="GBK"/>
<F7 type="string" length="10" field_index="7" encoding="GBK"/>
<F10 type="string" length="8" field_index="10" encoding="GBK"/>
<F11 type="string" length="6" field_index="11" encoding="GBK"/>
<F12 type="string" length="6" field_index="12" encoding="GBK"/>
<F13 type="string" length="4" field_index="13" encoding="GBK"/>
<F14 type="string" length="4" field_index="14" encoding="GBK"/>
<F15 type="string" length="4" field_index="15" encoding="GBK"/>
<F18 type="string" length="4" field_index="18" encoding="GBK"/>
<F22 type="string" length="3" field_index="22" encoding="GBK"/>
<F23 type="string" length="3" field_index="23" encoding="GBK"/>
<F25 type="string" length="2" field_index="25" encoding="GBK"/>
<F26 type="string" length="2" field_index="26" encoding="GBK"/>
<F28 type="string" length="9" field_index="28" encoding="GBK"/>
<F32 type="string" length="11" variable_flag="2" field_index="32" encoding="GBK"/>
<F33 type="string" length="11" variable_flag="2" field_index="33" encoding="GBK"/>
<F35 type="string" length="37" variable_flag="2" field_index="35" encoding="GBK"/>
<F36 type="string" length="104" variable_flag="3" field_index="36" encoding="GBK"/>
<F37 type="string" length="12" field_index="37" encoding="GBK"/>
<F38 type="string" length="6" field_index="38" encoding="GBK"/>
<F39 type="string" length="2" field_index="39" encoding="GBK"/>
<F41 type="string" length="8" field_index="41" encoding="GBK"/>
<F42 type="string" length="15" field_index="42" encoding="GBK"/>
<F43 type="string" length="40" field_index="43" encoding="GBK"/>
<F44 type="string" length="25" variable_flag="2" field_index="44" encoding="GBK"/>
<F47 type="string" length="100" variable_flag="3" field_index="47" encoding="GBK"/>
<F48 type="string" length="400" variable_flag="3" field_index="48" encoding="GBK"/>
<F49 type="string" length="3" field_index="49" encoding="GBK"/>
<F51 type="string" length="3" field_index="51" encoding="GBK"/>
<F52 type="string" length="8" field_index="52" encoding="GBK"/>
<F53 type="string" length="16" field_index="53" encoding="GBK"/>
<F54 type="string" length="40" variable_flag="3" field_index="54" encoding="GBK" />
<F55 type="string" length="300" variable_flag="3" field_index="55" encoding="GBK" />
<F57 type="string" length="100" variable_flag="3" field_index="57" encoding="GBK" />
<F60 type="string" length="100" variable_flag="3" field_index="60" encoding="GBK"/>
<F61 type="string" length="200" variable_flag="3" field_index="61" encoding="GBK"/>
<F62 type="string" length="200" variable_flag="3" field_index="62" encoding="GBK"/>
<F70 type="string" length="3" field_index="70" encoding="GBK"/>
<F90 type="string" length="42" field_index="90" encoding="GBK"/>
<F91 type="string" length="1" field_index="91" encoding="GBK"/>
<F96 type="string" length="8" field_index="96" encoding="GBK"/>
<F100 type="string" length="11" variable_flag="2" field_index="100" encoding="GBK"/>
<F102 type="string" length="32" variable_flag="2" field_index="102" encoding="GBK"/>
<F103 type="string" length="32" variable_flag="2" field_index="103" encoding="GBK"/>
<F108 type="string" length="32" variable_flag="3" field_index="108" encoding="GBK"/>
<F121 type="string" length="100" variable_flag="3" field_index="121" encoding="GBK"/>
<F122 type="string" length="50" variable_flag="3" field_index="122" encoding="GBK"/>
<F123 type="string" length="400" variable_flag="3" field_index="123" encoding="GBK"/>
<F128 type="string" length="8" field_index="128" encoding="GBK"/>
</sdoroot>

8583配置类

 package com.handle8583;

 import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader; public class Bean8583Factory { private static Map<String,Properties> map = new HashMap<String, Properties>(); private static Bean8583Factory instance = null; private static Log log = LogFactory.getLog(Bean8583Factory.class); public static Bean8583Factory getInstance(){
if(null == instance){
map.clear();
instance = new Bean8583Factory();
}
return instance;
} private Bean8583Factory(){
init();
} public void init() {
System.out.println("加载8583配置开始"); File f = new File("D:/workspace/springweb/src/com/handle8583/ISO8583medata.xml");
if ((f.exists()) && (f.isFile())) {
SAXReader reader = new SAXReader();
try {
Iterator<Node> iterator2;
Document doc = reader.read(f);
List obj = doc.getRootElement().elements();
if (obj == null) {
return;
}
Iterator<Node> iterator = obj.iterator();
while (iterator.hasNext()) {
Node imetadata = iterator.next();
Properties pop = new Properties(); Node isHeader = imetadata.selectSingleNode("@isHeader");
if(null != isHeader){
pop.setProperty("isHeader", isHeader.getText());
} Node isBCD = imetadata.selectSingleNode("@isBCD");
if(null != isBCD){
pop.setProperty("isBCD", isBCD.getText());
} Node type = imetadata.selectSingleNode("@type");
if(null != type){
pop.setProperty("type", type.getText());
} Node length = imetadata.selectSingleNode("@length");
if(null != length){
pop.setProperty("length", length.getText());
} Node variable_flag = imetadata.selectSingleNode("@variable_flag");
if(null != variable_flag){
pop.setProperty("variable_flag", variable_flag.getText());
} Node field_index = imetadata.selectSingleNode("@field_index");
if(null != field_index){
pop.setProperty("field_index", field_index.getText());
} Node encoding = imetadata.selectSingleNode("@encoding");
if(null != encoding){
pop.setProperty("encoding", encoding.getText());
} pop.setProperty("name", imetadata.getName());
map.put(imetadata.getName(),pop); }
} catch (DocumentException e) {
e.printStackTrace();
System.out.println("加载8583配置异常");
}
}
System.out.println("加载8583配置完成");
} public Map<String, Properties> getMap() {
return map;
} public Properties getFieldPropertie(String fieldName) {
return map.get(fieldName);
} public String getFieldPropertieVal(String fieldName,String propertieName) {
return map.get(fieldName).getProperty(propertieName);
} }

8583解析类

 package com.handle8583;

 import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set; import com.parseToString.FileTools;
/*
* @description:
* 准备包含8583报文头、报文类型标识、位图、报文体各域的ISO8583metadata.xml配置文件
* 准备8583十六进制报文
* 使用SAXReader读取ISO8583metadata.xml文件,将文件中的内容解析成Map<String,Properties>
* 使用文件输入流读取8583十六进制报文到字节数组输出流,字节数组输出流转换为字节数组
* 将字节数组转换成字符串,此刻字符串的内容与十六进制里的内容完全一致,并将字符串换行、空去掉
* 将字符串转换成字节数组(即将十六进制转换成十进制的字节数组)
* 解析报文头(根据ISO8583metadata.xml中:isBCD确定编码、length确定长度、encoding确定编码、name作为标签名。现根据长度截取,再判断isBCD编码,根据相应的编码解码。)
* 解析报文类型标识(根据长度,byte子数组,根绝对应的encoding编码进行解码)
* 解析位图(判断第一个字节的二进制最高位是否为1,为1则使用扩展位图,为0则不使用扩展位图;根据长度获取byte字数组,转换成对应的二进制;根据二进制判断存在哪些域有值)
* 解析报文体(将存在的域循环进行处理:判断是否变长,如果变长,先获取变长所表示的长度值,比如n..11(LLVAR)为两位变长,有两个字节表示长度,先拿两个字节计算本域所占几个字节,再获取相应字节数,再根据encoding编码进行解码;如果非变长,直接根据length获取长度,再根据encoding编码进行解码)
* 将解析完成的8583报文信息所在的Map排序,便于打印阅览(此处不再说明,看代码即可)
*
* @warn注意点
* 对于0~9的数字
* 十六进制转换成十进制,相应于BCD码转换成十进制
* 一个十六进制相当于一个byte,相当于两个[0,9]
*
* @see
* 8583报文拆组包关键点:
* 报文头各域、表问类型标识、位图或者报文体域所使用的编码方式,比如BCD编码还是普通的十六进制
* 位图的使用
* 报文体域的变长处理
*
* @see
* 拆组包8583报文需要对于编码和解码、进制转换、字符集有一个充分和系统的了解
*/
public class Parse8583 {
static int currentIndex = 0;
static Map<String, Properties> map = Bean8583Factory.getInstance().getMap();
public static void main(String[] args) throws UnsupportedEncodingException {
//获取8583报文
byte[] resp = FileTools.readContent("D:/workspace/springweb/src/com/handle8583/8583resp.txt");
String str = new String(resp).trim().replace("\r\n", "").replace("\r","").replace("\n", "").replace(" ", "");
//将报文解析成字节数组
byte[] retByte = parseTo8583bytes(str);
//解析8583报文体
Map<String,String> fieldMap = parse8583(retByte);
//获取有序的keys
List<String> keyList = getKeyList(fieldMap);
//输出各域信息
for(String key:keyList){
System.out.println("["+key+"] = "+fieldMap.get(key));
}
} // 报文处理函数
private static Map<String, String> parse8583(byte[] byteArr)
throws UnsupportedEncodingException {
Map<String,String> fieldMap = new HashMap<String,String>();
//获取报文头信息
parseHeaders(byteArr, fieldMap);
// 获取MsgType
parseMsgType(byteArr, fieldMap);
// 获取位图
String bitMap1_value = getBitMap(byteArr);
fieldMap.put("F1", bitMap1_value);
// 根据位图判断存在哪些域及获取域的值
parseFields(byteArr, fieldMap, bitMap1_value);
// 返回
return fieldMap;
}
//获取报文头信息
private static void parseHeaders(byte[] byteArr,Map<String, String> fieldMap)
throws UnsupportedEncodingException {
for(int i=1;i<=10;i++){
Properties headProperties = map.get("H"+i);
if(headProperties == null) continue; int head_length = Integer.parseInt(headProperties.getProperty("length"));
byte[] head_value_byte = new byte[head_length];
System.arraycopy(byteArr, currentIndex, head_value_byte, 0, head_length);
currentIndex += head_length; String isBCD = headProperties.getProperty("isBCD");
if("true".equals(isBCD)){
String head_value = bcd_bytes_to_String(head_value_byte);
fieldMap.put(headProperties.getProperty("name"), head_value);
}else{
String head_value = new String(head_value_byte, headProperties.getProperty("encoding"));
fieldMap.put(headProperties.getProperty("name"), head_value);
}
}
}
//bcd_bytes_to_String
private static String bcd_bytes_to_String(byte[] bytes){
StringBuffer sb = new StringBuffer(bytes.length*2);
for(int i=0;i<bytes.length;i++){
sb.append(String.valueOf((int)bytes[i]));
}
return sb.toString();
}
//解析各个域
private static void parseFields(byte[] byteArr,Map<String, String> fieldMap,String bitMap1_value_2) throws UnsupportedEncodingException {
List<Integer> exitFieldList = getExitField(bitMap1_value_2);
// 获取各域值
for(int i=0;i<exitFieldList.size();i++){
int field = exitFieldList.get(i);
Properties fieldProperties = map.get("F"+field);
//如果不存在,跳过
if(fieldProperties == null)continue; String field_variable_flag = fieldProperties.getProperty("variable_flag");
if(field_variable_flag == null || "".equals(field_variable_flag)){
int field_length = Integer.parseInt(fieldProperties.getProperty("length"));
byte[] field_value_byte = new byte[field_length];
System.arraycopy(byteArr, currentIndex, field_value_byte, 0, field_length);
currentIndex += field_length;
String field_value = new String(field_value_byte, fieldProperties.getProperty("encoding"));
fieldMap.put(fieldProperties.getProperty("name"), field_value);
}else{
//先获取变长域的长度值
int variable_flag_length = Integer.parseInt(field_variable_flag);
byte[] variable_flag_byte = new byte[variable_flag_length];
System.arraycopy(byteArr, currentIndex, variable_flag_byte, 0, variable_flag_length);
currentIndex += variable_flag_length;
String variable_flag_value = new String(variable_flag_byte, fieldProperties.getProperty("encoding"));
//再获取变长域的真实值
int field_length = Integer.parseInt(variable_flag_value);
byte[] field_value_byte = new byte[field_length];
System.arraycopy(byteArr, currentIndex, field_value_byte, 0, field_length);
currentIndex += field_length;
String field_value = new String(field_value_byte, fieldProperties.getProperty("encoding"));
fieldMap.put(fieldProperties.getProperty("name"), field_value);
}
}
}
//获取二进制位图字符串
private static String getBitMap(byte[] byteArr) {
Properties bitMap1 = map.get("bitmap1");
int bitMap1_length = Integer.parseInt(bitMap1.getProperty("length"));
byte[] bitMap1_value_byte = new byte[bitMap1_length];
System.arraycopy(byteArr, currentIndex, bitMap1_value_byte, 0,bitMap1_length);
currentIndex += bitMap1_length;
String bitMap1_value_2 = binary(bitMap1_value_byte, 2);
if (bitMap1_value_2.startsWith("1")) {
Properties bitMap2 = map.get("bitmap2");
int bitMap2_length = Integer.parseInt(bitMap2.getProperty("length"));
byte[] bitMap2_value_byte = new byte[bitMap2_length];
System.arraycopy(byteArr, currentIndex, bitMap2_value_byte, 0,bitMap2_length);
currentIndex += bitMap2_length;
String bitMap2_value_2 = binary(bitMap2_value_byte, 2);
bitMap1_value_2 += bitMap2_value_2;
}
return bitMap1_value_2;
}
//解析MsgType
private static void parseMsgType(byte[] byteArr,Map<String, String> mapRet)
throws UnsupportedEncodingException {
Properties msgType = map.get("MsgType");
int msgType_length = Integer.parseInt(msgType.getProperty("length"));
byte[] msgType_value_byte = new byte[msgType_length];
System.arraycopy(byteArr, currentIndex, msgType_value_byte, 0,msgType_length);
currentIndex += msgType_length;
String msgType_value = new String(msgType_value_byte, msgType.getProperty("encoding"));
mapRet.put("F0", msgType_value);
}
//根据二进制位图字符串获取存在的域
private static List<Integer> getExitField(String bitMap2String) {
List<Integer> exitFieldList = new ArrayList<Integer>();
for (int i=2;i<=bitMap2String.length();i++) {
int field_index = Integer.parseInt(String.valueOf(bitMap2String.charAt(i-1)));
if (field_index == 1) {
exitFieldList.add(i);
}
}
return exitFieldList;
}
//将报文解析成字节数组
private static byte[] parseTo8583bytes(String str) {
String value = null;
byte[] retByte = new byte[str.length() / 2];
for (int i = 0; i < str.length(); i = i + 2) {
value = str.substring(i, i + 2);
retByte[i / 2] = (byte) Integer.parseInt(value, 16);
}
return retByte;
}
//获取有序的keys
private static List<String> getKeyList(Map<String, String> fieldMap) {
Set<String> keySet = fieldMap.keySet();
List<String> keyList = new ArrayList<String>(keySet);
Collections.sort(keyList, new Comparator<String>(){
@Override
public int compare(String str1, String str2) {
// TODO Auto-generated method stub
Integer value1 = Integer.parseInt(str1.substring(1));
Integer value2 = Integer.parseInt(str2.substring(1));
return value1.compareTo(value2);
}});
Collections.sort(keyList, new Comparator<String>(){
@Override
public int compare(String str1, String str2) {
// TODO Auto-generated method stub
char value1 = str1.charAt(0);
char value2 = str2.charAt(0);
return value1 < value2 ? 1 : 0;
}});
return keyList;
}
//将字节数组转换成二进制字符串
private static String binary(byte[] bytes, int radix) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(byteToBit(b));
}
return sb.toString();
}
/**
* Byte转Bit
*/
private static String byteToBit(byte b) {
return "" + (byte) ((b >> 7) & 0x1) + (byte) ((b >> 6) & 0x1)
+ (byte) ((b >> 5) & 0x1) + (byte) ((b >> 4) & 0x1)
+ (byte) ((b >> 3) & 0x1) + (byte) ((b >> 2) & 0x1)
+ (byte) ((b >> 1) & 0x1) + (byte) ((b >> 0) & 0x1);
} }

ISO8583报文解析的更多相关文章

  1. [性能测试]:ISO8583报文解析实例

    现在我们有ISO8583报文如下(十六进制表示法): 60 00 03 00 00 60 31 00 31 07 30 02 00 30 20 04 C0 20 C0 98 11 00 00 00 0 ...

  2. 【8583】ISO8583报文解析

    ISO8583报文(简称8583包)又称8583报文,是一个国际标准的包格式,最多由128个字段域组成,每个域都有统一的规定,并有定长与变长之分. [报文格式] POS终端上送POS中心的消息报文结构 ...

  3. 银联ISO8583报文解析过程

    主密钥: aabbccddeeff11223344556677889900 1.从签到报文中获取工作密钥,包括MACKEY明文,PINKEY明文 签到: 12-03-31 16:38:09----&g ...

  4. (转载)解析ISO8583报文实例

    本篇文章参考了中国银联POS终端规范,所以如有不明白的可以去我的资源里面下载. 现在我们有ISO8583报文如下(十六进制表示法): 60 00 03 00 00(前五个字节为TPDU) 60 31 ...

  5. 解析ISO8583报文实例

    http://www.cnblogs.com/1971ruru/archive/2012/12/10/2811549.html 本篇文章参考了中国银联POS终端规范,所以如有不明白的可以去我的资源里面 ...

  6. ISO8583报文协议

    最开始时,金融系统只有IBM这些大的公司来提供设备,象各种主机与终端等.在各个计算机设备之间,需要交换数据.我们知道数据是通过网络来传送的,而在网络上传送的数据都是基于0或1这样的二进制数据,如果没有 ...

  7. 轻松掌握ISO8583报文协议

    http://www.itpub.net/thread-419521-1-1.html 我刚进入金融行业时,就知道了IS08583报文协议,我想可能我还没进入这个行业都已经听过了,可知ISO8583的 ...

  8. 报文解析及CRC类

    /// <summary> /// 报文解析转换类 /// </summary> public class DatagramConvert { public static En ...

  9. 基于DPI(深度报文解析)的应用识别

    一.概述 1.DPI(Deep packet inspection,深度报文解析) 所谓“深度”是和普通的报文分析层次相比较而言的,“普通报文检测”仅分析IP包4 层以下的内容,包括源地址.目的地址. ...

随机推荐

  1. Write a program to convert decimal to 32-bit unsigned binary.

    Write a program to convert decimal to 32-bit unsigned binary. Write a program to convert a 32-bit un ...

  2. 【恒天云技术分享系列10】OpenStack块存储技术

    原文:http://www.hengtianyun.com/download-show-id-101.html 块存储,简单来说就是提供了块设备存储的接口.用户需要把块存储卷附加到虚拟机(或者裸机)上 ...

  3. 让sublime text 2更好地支持Python

    SublimeCodeIntel: ~/.codeintel/config里加了python和pythonExtraPaths的路径(Mac): {"Python" : {&quo ...

  4. [现代程序设计]homework-03

    Homework-03 队员: 11061193 薛亚杰 11061192 周敏轩    11061190 李孟 材料阅读 我们三个人将以下材料仔细阅读,觉得十分受益.下面是我们的总结和分享: 1)代 ...

  5. Myeclipse 快捷键设置和自动提示设置

    1.快捷键设置和调整 2.自动提示信息设置与调整

  6. crontab 定时任务格式

    如下内容节选自<Linux Crontab 定时任务 命令详解> 用crontab -e 添加要执行的命令 添加的命令必须以如下格式: * * * * * /command path 前五 ...

  7. (转)UML常用图的几种关系的总结

    在UML的类图中,常见的有以下几种关系: 泛化(Generalization),  实现(Realization), 关联(Association), 聚合(Aggregation), 组合(Comp ...

  8. srcelement、parentElement

    srcElement 是Dom事件中的事件最初指派到的元素. 比如有一个div,里面有一个按钮.你响应div的onclick事件,但实际上,你单击的只是它内部的按钮,那么,srcElement指向的, ...

  9. 微软企业库5.0学习-Security.Cryptography模块

    一.微软企业库加密应用模块提供了两种加密: 1.Hash providers :离散加密,即数据加密后无法解密 2.Symmetric Cryptography Providers:密钥(对称)加密法 ...

  10. mybatis generator配置文件

    <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration ...