/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat, Inc., and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.jboss.narayana.blacktie.jatmibroker.core.conf;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* XMLEnvHandler extends DefaultHandler to Environment Info
*/
public class XMLEnvHandler extends DefaultHandler {
private static final Logger log = LogManager.getLogger(XMLEnvHandler.class);
private final static String envVarPatStr = "(.*)\\$\\{(.*)\\}(.*)";
private static java.util.regex.Pattern pattern;
private final String DOMAIN = "DOMAIN";
private final String BUFFER = "BUFFER";
private final String ATTRIBUTE = "ATTRIBUTE";
private final String SERVER_NAME = "SERVER";
private final String SERVICE_NAME = "SERVICE";
private final String ORB = "ORB";
private final String MQ = "MQ";
private final String SOCKETSERVER = "SOCKETSERVER";
private final String MACHINE = "MACHINE";
private final String MACHINE_REF = "MACHINE-REF";
private Properties prop;
private String value;
private String serverName;
private String serviceName;
private List<String> servers = new ArrayList<String>();
private Map<String, BufferStructure> buffers = new HashMap<String, BufferStructure>();
private Map<String, Machine> machines = new HashMap<String, Machine>();
private List<Server> serverLaunchers = new ArrayList<Server>();
private String currentBufferName;
static int CHAR_SIZE = 1;
static int LONG_SIZE = 8;
static int INT_SIZE = 4;
static int SHORT_SIZE = 2;
static int FLOAT_SIZE = 4;
static int DOUBLE_SIZE = 8;
XMLEnvHandler(Properties prop) {
this.prop = prop;
prop.put("blacktie.domain.servers", servers);
prop.put("blacktie.domain.buffers", buffers);
prop.put("blacktie.domain.serverLaunchers", serverLaunchers);
prop.setProperty("blacktie.domain.version", "5.6.0.Final-SNAPSHOT");
if (pattern == null) {
pattern = java.util.regex.Pattern.compile(envVarPatStr);
}
}
public XMLEnvHandler() {
this(new Properties());
}
public void characters(char[] ch, int start, int length) throws SAXException {
String strValue = new String(ch, start, length);
value += strValue;
}
/**
* Search inputStr for sequences of the form ${VAR} and replace them with the result of System.getenv("VAR"); If the
* enviromment variable VAR is not set then the literal text "VAR" is used instead.
*
* @param inputStr the pattern to match against
* @return the same string with sequences of the form ${VAR} replaced by the result of System.getenv("VAR") or "VAR" if that
* returns null
*/
public String getenv(CharSequence inputStr) {
String[] matches = new String[3];
matches[0] = "";
matches[2] = "";
java.util.regex.Matcher matcher = pattern.matcher(inputStr);
//matcher.reset(inputStr);
if (matcher.find()) {
StringBuilder sb = new StringBuilder();
boolean expanded = false;
for (int i = 0; i < matcher.groupCount(); i++) {
if (i < matches.length) {
String val = matcher.group(i + 1);
if (val != null && val.length() > 0) {
String env = System.getenv(val);
if (env == null) {
env = System.getProperty(val);
}
if (env == null) {
if (val.equals("jboss.bind.address.management")) {
env = "localhost";
}
matches[i] = val;
} else {
matches[i] = env;
expanded = true;
}
}
}
}
if (!expanded)
log.error("There is an unset environment variable within the configuration element/attribute: " + inputStr);
for (int i = 0; i < matches.length; i++)
sb.append(matches[i]);
return sb.toString();
}
return inputStr.toString();
}
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
String avalue;
value = "";
if (SERVER_NAME.equals(localName)) {
serverName = atts.getValue(0);
if (servers.contains(serverName)) {
throw new SAXException("Duplicate server detected: " + serverName);
}
servers.add(serverName);
serverLaunchers.add(new Server(serverName));
} else if (MACHINE_REF.equals(localName)) {
Machine machine = null;
avalue = getenv(atts.getValue(0));
// Get the machine out of the list
machine = machines.get(avalue);
if (machine == null) {
throw new SAXException("Machine did not exist: " + avalue);
}
// This will be the last server added
Server server = serverLaunchers.get(serverLaunchers.size() - 1);
server.addMachine(machine);
// Make sure to record the administration services as not
// conversational
String ad_key = "blacktie.." + server.getName() + machine.getId() + ".conversational";
prop.put(ad_key, false);
} else if (BUFFER.equals(localName)) {
currentBufferName = atts.getValue(0);
BufferStructure buffer = buffers.get(currentBufferName);
if (buffer != null) {
throw new SAXException("Duplicate buffer detected: " + currentBufferName);
}
buffer = new BufferStructure();
buffer.name = currentBufferName;
buffer.wireSize = 0;
buffer.memSize = 0;
buffer.lastPad = 0;
buffers.put(currentBufferName, buffer);
} else if (ATTRIBUTE.equals(localName)) {
BufferStructure buffer = buffers.get(currentBufferName);
AttributeStructure attribute = new AttributeStructure();
attribute.id = null;
attribute.type = null;
attribute.count = 0;
attribute.length = 0;
attribute.wirePosition = 0;
attribute.memPosition = 0;
String type = null;
for (int i = 0; i < atts.getLength(); i++) {
if (atts.getLocalName(i).equals("id")) {
attribute.id = atts.getValue(i);
} else if (atts.getLocalName(i).equals("type")) {
type = atts.getValue(i);
} else if (atts.getLocalName(i).equals("arrayCount")) {
attribute.count = Integer.parseInt(atts.getValue(i));
} else if (atts.getLocalName(i).equals("arrayLength")) {
attribute.length = Integer.parseInt(atts.getValue(i));
}
}
int typeSize = -1;
boolean contains = buffer.attributeNames.contains(attribute.id);
boolean fail = false;
if (!contains) {
// short, int, long, float, double, char
if (type.equals("short")) {
typeSize = SHORT_SIZE;
attribute.instanceSize = SHORT_SIZE;
attribute.type = short.class;
} else if (type.equals("int")) {
typeSize = INT_SIZE;
attribute.instanceSize = INT_SIZE;
attribute.type = int.class;
} else if (type.equals("long")) {
typeSize = LONG_SIZE;
attribute.instanceSize = LONG_SIZE;
attribute.type = long.class;
} else if (type.equals("float")) {
typeSize = FLOAT_SIZE;
attribute.instanceSize = FLOAT_SIZE;
attribute.type = float.class;
} else if (type.equals("double")) {
typeSize = DOUBLE_SIZE;
attribute.instanceSize = DOUBLE_SIZE;
attribute.type = double.class;
} else if (type.equals("char")) {
typeSize = CHAR_SIZE;
attribute.instanceSize = CHAR_SIZE;
attribute.type = byte.class;
} else if (type.equals("char[]")) {
if (attribute.length == 0) {
attribute.length = 1;
}
typeSize = CHAR_SIZE;
attribute.instanceSize = CHAR_SIZE * attribute.length;
attribute.type = byte[].class;
} else if (type.equals("short[]")) {
if (attribute.length == 0) {
attribute.length = 1;
}
typeSize = SHORT_SIZE;
attribute.instanceSize = SHORT_SIZE * attribute.length;
attribute.type = short[].class;
} else if (type.equals("int[]")) {
if (attribute.length == 0) {
attribute.length = 1;
}
typeSize = INT_SIZE;
attribute.instanceSize = INT_SIZE * attribute.length;
attribute.type = int[].class;
} else if (type.equals("long[]")) {
if (attribute.length == 0) {
attribute.length = 1;
}
typeSize = LONG_SIZE;
attribute.instanceSize = LONG_SIZE * attribute.length;
attribute.type = long[].class;
} else if (type.equals("float[]")) {
if (attribute.length == 0) {
attribute.length = 1;
}
typeSize = FLOAT_SIZE;
attribute.instanceSize = FLOAT_SIZE * attribute.length;
attribute.type = float[].class;
} else if (type.equals("double[]")) {
if (attribute.length == 0) {
attribute.length = 1;
}
typeSize = DOUBLE_SIZE;
attribute.instanceSize = DOUBLE_SIZE * attribute.length;
attribute.type = double[].class;
} else if (type.equals("char[][]")) {
if (attribute.length == 0) {
attribute.length = 1;
}
if (attribute.count == 0) {
attribute.count = 1;
}
typeSize = CHAR_SIZE;
attribute.instanceSize = CHAR_SIZE * attribute.length * attribute.count;
attribute.type = byte[][].class;
} else {
log.error("Unknown attribute type: " + attribute.type);
fail = true;
}
if (!fail) {
buffer.attributes.add(attribute);
// Extend the buffer by the required extra buffer size
if (buffer.lastPad < typeSize) {
buffer.lastPad = typeSize;
}
buffer.memSize = buffer.memSize + (buffer.memSize % typeSize);
attribute.memPosition = buffer.memSize;
attribute.wirePosition = buffer.wireSize;
buffer.wireSize = buffer.wireSize + attribute.instanceSize;
buffer.memSize = buffer.memSize + attribute.instanceSize;
}
} else {
log.error("Duplicate attribute detected: " + attribute.id);
}
} else if (ORB.equals(localName)) {
for (int j = 0; j < atts.getLength(); j++) {
if (atts.getLocalName(j).equals("OPT")) {
String[] argv = atts.getValue(j).split(" ");
int orbargs = 0;
boolean lookForInterface = false;
for (int i = 0; i < argv.length; i++) {
String arg = "blacktie.orb.arg." + (i + 1);
String toSet = getenv(argv[i]);
if (toSet.equals("-ORBListenEndpoints")) {
lookForInterface = true;
} else if (lookForInterface) {
// " iiop://${JBOSSAS_IP_ADDR}:0"
int startOfHostname = toSet.indexOf("//") + 2;
int portIndex = toSet.indexOf(":", startOfHostname);
String interfaceAddress = toSet.substring(startOfHostname, portIndex);
String interfacePort = toSet.substring(portIndex + 1);
prop.setProperty("blacktie.orb.interface", interfaceAddress);
prop.setProperty("blacktie.orb.interface.port", interfacePort);
} else {
prop.setProperty(arg, toSet);
log.debug(arg + " is " + toSet);
orbargs++;
}
}
log.debug("blacktie.orb.args is " + orbargs);
prop.setProperty("blacktie.orb.args", Integer.toString(orbargs));
} else if (atts.getLocalName(j).equals("TRANS_FACTORY_ID")) {
prop.setProperty("blacktie.trans.factoryid", atts.getValue(j));
}
}
} else if (MQ.equals(localName)) {
for (int i = 0; i < atts.getLength(); i++) {
avalue = getenv(atts.getValue(i));
if (atts.getLocalName(i).equals("USER")) {
prop.setProperty("StompConnectUsr", avalue);
} else if (atts.getLocalName(i).equals("PASSWORD")) {
prop.setProperty("StompConnectPwd", avalue);
} else if (atts.getLocalName(i).equals("DESTINATION_TIMEOUT")) {
prop.setProperty("DestinationTimeout", avalue);
} else if (atts.getLocalName(i).equals("RECEIVE_TIMEOUT")) {
prop.setProperty("ReceiveTimeout", avalue);
} else if (atts.getLocalName(i).equals("TIME_TO_LIVE")) {
prop.setProperty("TimeToLive", avalue);
} else if (atts.getLocalName(i).equals("NAMING_URL")) {
prop.setProperty("java.naming.provider.url", avalue);
} else if (atts.getLocalName(i).equals("HOST")) {
prop.setProperty("StompConnectHost", avalue);
} else if (atts.getLocalName(i).equals("PORT")) {
prop.setProperty("StompConnectPort", avalue);
}
}
} else if(SOCKETSERVER.equals(localName)) {
for (int i = 0; i < atts.getLength(); i++) {
avalue = getenv(atts.getValue(i));
if (atts.getLocalName(i).equals("PORT")) {
prop.setProperty("blacktie.java.socketserver.port", avalue);
} else if (atts.getLocalName(i).equals("HOST")) {
prop.setProperty("blacktie.java.socketserver.host", avalue);
}
}
} else if (MACHINE.equals(localName)) {
Machine machine = new Machine();
for (int i = 0; i < atts.getLength(); i++) {
avalue = getenv(atts.getValue(i));
if (atts.getLocalName(i).equals("id")) {
machine.setId(avalue);
} else if (atts.getLocalName(i).equals("hostname")) {
machine.setHostname(avalue);
} else if (atts.getLocalName(i).equals("ipAddress")) {
machine.setIpAddress(avalue);
} else if (atts.getLocalName(i).equals("pathToExecutable")) {
machine.setPathToExecutable(avalue);
} else if (atts.getLocalName(i).equals("workingDirectory")) {
machine.setWorkingDirectory(avalue);
} else if (atts.getLocalName(i).equals("serverId")) {
machine.setServerId(Integer.parseInt(avalue));
} else if (atts.getLocalName(i).equals("argLine")) {
machine.setArgLine(avalue);
}
}
machines.put(machine.getId(), machine);
} else if (SERVICE_NAME.equals(localName)) {
for (int i = 0; i < atts.getLength(); i++) {
String attsLocalName = atts.getLocalName(i);
if (attsLocalName.equals("name")) {
serviceName = atts.getValue(i);
String serviceServer = (String) prop.get("blacktie." + serviceName + ".server");
String type = (String) prop.get("blacktie." + serviceName + ".type");
if (serviceServer != null && !type.equals("topic")) {
log.warn("service " + serviceName + " has already been defined in " + serviceName);
throw new SAXException("Can not define the same service: " + serviceName);
}
if (serviceName.equals("BTStompAdmin") || serviceName.equals("BTDomainAdmin")) {
throw new SAXException("Can not define service: " + serviceName);
}
prop.put("blacktie." + serviceName + ".server", serverName);
} else if (attsLocalName.equals("function_name")) {
String func_key = "blacktie." + serviceName + ".function_name";
String function_name = atts.getValue(i);
prop.put(func_key, function_name);
} else if (attsLocalName.equals("java_class_name")) {
String java_key = "blacktie." + serviceName + ".java_class_name";
String java_class_name = atts.getValue(i);
prop.put(java_key, java_class_name);
} else if (attsLocalName.equals("library_name")) {
String lib_key = "blacktie." + serviceName + ".library_name";
String library_name = atts.getValue(i);
prop.put(lib_key, library_name);
} else if (attsLocalName.equals("advertised")) {
String advertised = atts.getValue(i);
String ad_key = "blacktie." + serviceName + ".advertised";
prop.put(ad_key, advertised);
if (advertised.equals("true")) {
String skey = "blacktie." + serverName + ".services";
String object = (String) prop.get(skey);
if (object == null) {
object = serviceName;
} else {
object = new String(object + "," + serviceName);
}
prop.put(skey, object);
}
} else if (attsLocalName.equals("conversational")) {
String conversational = atts.getValue(i);
String ad_key = "blacktie." + serviceName + ".conversational";
prop.put(ad_key, new Boolean(conversational));
} else if (attsLocalName.equals("size")) {
String sizeKey = "blacktie." + serviceName + ".size";
String sizeVal = atts.getValue(i);
prop.setProperty(sizeKey, sizeVal);
} else if (attsLocalName.equals("externally-managed-destination")) {
String external = atts.getValue(i);
String ad_key = "blacktie." + serviceName + ".externally-managed-destination";
prop.put(ad_key, new Boolean(external));
} else if (attsLocalName.equals("type")) {
String type = atts.getValue(i);
String type_key = "blacktie." + serviceName + ".type";
prop.setProperty(type_key, type);
} else if (attsLocalName.equals("coding_type")) {
String coding_type = atts.getValue(i);
String coding_key = "blacktie." + serviceName + ".coding_type";
prop.setProperty(coding_key, coding_type);
}
}
// If type was not defined above
String type_key = "blacktie." + serviceName + ".type";
if (prop.get(type_key) == null) {
prop.put(type_key, "queue");
}
// If conversational was not defined above
String ad_key = "blacktie." + serviceName + ".conversational";
if (prop.get(ad_key) == null) {
prop.put(ad_key, false);
}
String ex_key = "blacktie." + serviceName + ".externally-managed-destination";
if (prop.get(ex_key) == null) {
prop.put(ex_key, false);
}
log.trace("Externally managed: " + prop.get("blacktie." + serviceName + ".externally-managed-destination"));
log.trace("Added the service: " + serviceName);
log.trace("Adding for: " + serviceName + " "
+ prop.get("blacktie." + serviceName + ".externally-managed-destination"));
}
}
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
if (DOMAIN.equals(localName)) {
prop.setProperty("blacktie.domain.name", getenv(value));
} else if (SERVICE_NAME.equals(localName)) {
serviceName = null;
}
}
}