/*
* Copyright 2004,2005 The Apache Software Foundation.
*
* 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 org.wso2.carbon.server.transports;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.securevault.SecretResolver;
import org.wso2.securevault.SecretResolverFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.wso2.carbon.utils.ServerConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
/**
* This class is reponsible for starting up the transports when Carbon is running
* in standalone mode
*/
public class TransportManager {
private static Map<String, Transport> transports = new HashMap<String, Transport>();
private static final Log log = LogFactory.getLog(TransportManager.class);
private static String hostAddress = "127.0.0.1";
/**
* Initialize the TransportManager. This will load all the transports.
*
* @throws Exception If an error occurs while initializing TransportManager
*/
public static void init() throws Exception {
String transportsFile = getTransportsFilePath();
File file = new File(transportsFile);
if (!file.exists()) {
log.error("Cannot initialize TransportManager. " +
file.getAbsolutePath() + " does not exist.");
return;
}
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(file);
doc.getDocumentElement().normalize();
Element rootEle = doc.getDocumentElement();
Attr hostNameAttr = rootEle.getAttributeNode("hostName");
if (hostNameAttr != null) {
String hostNameAttrValue = hostNameAttr.getValue();
if (hostNameAttrValue != null && hostNameAttrValue.length() != 0) {
hostAddress = hostNameAttrValue;
}
}
SecretResolver secretResolver = SecretResolverFactory.create(rootEle, false);
NodeList childNodes = rootEle.getElementsByTagName("transport");
for (int i = 0; i < childNodes.getLength(); i++) {
Element transportEle = (Element) childNodes.item(i);
NamedNodeMap transportAttribs = transportEle.getAttributes();
//Create the password manager
Node nameAttrib = transportAttribs.getNamedItem("name");
String transportName;
if (nameAttrib == null ||
(transportName = nameAttrib.getNodeValue()) == null ||
transportName.trim().length() == 0) {
throw new RuntimeException("Required attribute, transport name is not specified.");
}
Node classAttrib = transportAttribs.getNamedItem("class");
String clazz;
if (classAttrib == null ||
(clazz = classAttrib.getNodeValue()) == null ||
clazz.trim().length() == 0) {
throw new RuntimeException("Required attribute, transport class is not specified.");
}
Transport transportImpl = (Transport) Class.forName(clazz).newInstance();
transports.put(transportName, transportImpl);
Map<String, TransportParameter> transportParameters =
new HashMap<String, TransportParameter>();
NodeList parameterList = transportEle.getElementsByTagName("parameter");
for (int j = 0; j < parameterList.getLength(); j++) {
Element paramEle = (Element) parameterList.item(j);
String value = null;
NodeList values = paramEle.getChildNodes();
for (int k = 0; k < values.getLength(); k++) {
Node node = values.item(k);
if ((value = node.getNodeValue().trim()).length() != 0) {
break;
}
}
String paramName = paramEle.getAttribute("name");
if (secretResolver != null && secretResolver.isInitialized() &&
secretResolver.isTokenProtected("transports." + transportName + "." + paramName)) {
value = secretResolver.resolve("transports." + transportName + "." + paramName);
}
value = replaceSystemProperty(value);
transportParameters.put(paramName, new TransportParameter(paramName, value));
}
transportImpl.setName(transportName);
transportImpl.init(transportParameters);
}
}
private static String replaceSystemProperty(String text) {
int indexOfStartingChars;
int indexOfClosingBrace;
// The following condition deals with properties.
// Properties are specified as ${system.property},
// and are assumed to be System properties
if ((indexOfStartingChars = text.indexOf("${")) != -1 &&
(indexOfClosingBrace = text.indexOf("}")) != -1) { // Is a property used?
String sysProp = text.substring(indexOfStartingChars + 2,
indexOfClosingBrace);
String propValue = System.getProperty(sysProp);
if (propValue != null) {
text = text.substring(0, indexOfStartingChars) + propValue +
text.substring(indexOfClosingBrace + 1);
}
if (sysProp.equals(ServerConstants.CARBON_HOME)) {
if (System.getProperty(ServerConstants.CARBON_HOME).equals(".")) {
text = new File(".").getAbsolutePath() + File.separator + text;
}
}
}
return text;
}
private static String getTransportsFilePath() {
String transportsPath = System.getProperty(ServerConstants.CARBON_HOME) + File.separator +
"repository" + File.separator + "conf" + File.separator + "mgt-transports.xml";
try {
String tranportsProperty = System.getProperty(ServerConstants.TRANSPORTS_XML_PATH);
new File(tranportsProperty);
//should check whether the file present, but should accomodate
//for the special case of this running as a war
transportsPath = tranportsProperty;
} catch (Exception e) {
//the property is invalid does not exist keep using the default file path
}
return transportsPath;
}
/**
* Get the transport port
*
* @param transport The transport
* @return The port corresponding to the transport. If the transport is not available, or there
* is no port for the transport, returns -1
*/
public int getPort(String transport) {
Transport transportImpl = transports.get(transport);
if (transportImpl != null) {
return transportImpl.getPort();
}
return -1;
}
/**
* Get the transport proxy port
*
* @param transport The transport
* @return The proxy port corresponding to the transport. If the transport is not available, or there
* is no proxy port for the transport, returns -1
*/
public int getProxyPort(String transport) {
Transport transportImpl = transports.get(transport);
if (transportImpl != null) {
return transportImpl.getProxyPort();
}
return -1;
}
public void startTransport(String transport) throws Exception {
Transport transportImpl = transports.get(transport);
if (transportImpl != null) {
transportImpl.start();
} else {
if (!System.getProperty(ServerConstants.REPO_WRITE_MODE, "false").equals("true")) {
throw new RuntimeException("Transport " + transport + " not found");
}
}
}
public void startTransport(Transport transport) throws Exception {
if (transport != null) {
transport.start();
} else {
if (!System.getProperty(ServerConstants.REPO_WRITE_MODE, "false").equals("true")) {
throw new RuntimeException("Transport is null");
}
}
}
public void stopTransport(String transport) throws Exception {
stopTransport(transports.get(transport));
}
public void stopTransport(Transport transport) throws Exception {
if (transport != null) {
transport.stop();
} else {
if (!System.getProperty(ServerConstants.REPO_WRITE_MODE, "false").equals("true")) {
throw new RuntimeException("Transport not found");
}
}
}
public void startTransports() throws Exception {
for (Transport transport : transports.values()) {
startTransport(transport);
}
}
/**
* Returns the ip address to be used for the replyto epr
* CAUTION:
* This will go through all the available network interfaces and will try to return an ip address.
* First this will try to get the first IP which is not loopback address (127.0.0.1). If none is found
* then this will return this will return 127.0.0.1.
* This will <b>not<b> consider IPv6 addresses.
* <p/>
*
* @return Returns String.
* @throws java.net.SocketException SocketException
*/
public static String getIpAddress() throws SocketException {
if (!hostAddress.equals("127.0.0.1")) {
Enumeration e = NetworkInterface.getNetworkInterfaces();
while (e.hasMoreElements()) {
NetworkInterface netface = (NetworkInterface) e.nextElement();
Enumeration addresses = netface.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress ip = (InetAddress) addresses.nextElement();
if (!ip.isLoopbackAddress()) {
return ip.getHostAddress();
}
}
}
}
return hostAddress;
}
}