/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2009-2011 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/
package org.opennms.netmgt.alarmd.northbounder.http;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.opennms.core.utils.EmptyKeyRelaxedTrustProvider;
import org.opennms.core.utils.EmptyKeyRelaxedTrustSSLContext;
import org.opennms.core.utils.HttpResponseRange;
import org.opennms.core.utils.LogUtils;
import org.opennms.netmgt.alarmd.api.NorthboundAlarm;
import org.opennms.netmgt.alarmd.api.NorthbounderException;
import org.opennms.netmgt.alarmd.api.support.AbstractNorthbounder;
import org.opennms.netmgt.alarmd.northbounder.http.HttpNorthbounderConfig.HttpMethod;
/**
* Forwards north bound alarms via HTTP.
* FIXME: Needs lots of work still :(
*
* @author <a mailto:david@opennms.org>David Hustace</a>
*/
public class HttpNorthbounder extends AbstractNorthbounder {
private HttpNorthbounderConfig m_config;
protected HttpNorthbounder() {
super("HttpNorthbounder");
}
//FIXME: This should be wired with Spring but is implmented as was in the PSM
// Make sure that the {@link EmptyKeyRelaxedTrustSSLContext} algorithm
// is available to JSSE
static {
//this is a safe call because the method returns -1 if it is already installed (by PageSequenceMonitor, etc.)
java.security.Security.addProvider(new EmptyKeyRelaxedTrustProvider());
}
@Override
public boolean accepts(NorthboundAlarm alarm) {
if (m_config.getAcceptableUeis() == null || m_config.getAcceptableUeis().contains(alarm.getUei())) {
return true;
}
return false;
}
@Override
public void forwardAlarms(List<NorthboundAlarm> alarms) throws NorthbounderException {
LogUtils.infof(this, "Forwarding %i alarms", alarms.size());
//Need a configuration bean for these
int connectionTimeout = 3000;
int socketTimeout = 3000;
Integer retryCount = Integer.valueOf(3);
HttpVersion httpVersion = determineHttpVersion(m_config.getHttpVersion());
String policy = CookiePolicy.BROWSER_COMPATIBILITY;
URI uri = m_config.getURI();
DefaultHttpClient client = new DefaultHttpClient(buildParams(httpVersion, connectionTimeout,
socketTimeout, policy, m_config.getVirtualHost()));
client.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(retryCount, false));
if ("https".equals(uri.getScheme())) {
final SchemeRegistry registry = client.getConnectionManager().getSchemeRegistry();
final Scheme https = registry.getScheme("https");
// Override the trust validation with a lenient implementation
SSLSocketFactory factory = null;
try {
factory = new SSLSocketFactory(SSLContext.getInstance(EmptyKeyRelaxedTrustSSLContext.ALGORITHM), SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
} catch (Throwable e) {
throw new NorthbounderException(e);
}
final Scheme lenient = new Scheme(https.getName(), https.getDefaultPort(), factory);
// This will replace the existing "https" schema
registry.register(lenient);
}
HttpUriRequest method = null;
if (HttpMethod.POST == (m_config.getMethod())) {
HttpPost postMethod = new HttpPost(uri);
//TODO: need to configure these
List<NameValuePair> postParms = new ArrayList<NameValuePair>();
//FIXME:do this for now
NameValuePair p = new BasicNameValuePair("foo", "bar");
postParms.add(p);
try {
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(postParms, "UTF-8");
postMethod.setEntity(entity);
} catch (UnsupportedEncodingException e) {
throw new NorthbounderException(e);
}
HttpEntity entity = null;
try {
//I have no idea what I'm doing here ;)
entity = new StringEntity("XML HERE", HTTP.DEFAULT_CONTENT_TYPE, HTTP.DEFAULT_CONTENT_CHARSET);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
postMethod.setEntity(entity);
method = postMethod;
} else if (HttpMethod.GET == m_config.getMethod()) {
//TODO: need to configure these
List<NameValuePair> getParms = null;
method = new HttpGet(uri);
}
method.getParams().setParameter(CoreProtocolPNames.USER_AGENT, m_config.getUserAgent());
HttpResponse response = null;
try {
response = client.execute(method);
} catch (ClientProtocolException e) {
throw new NorthbounderException(e);
} catch (IOException e) {
throw new NorthbounderException(e);
}
if (response != null) {
int code = response.getStatusLine().getStatusCode();
HttpResponseRange range = new HttpResponseRange("200-399");
if (!range.contains(code)) {
System.err.println("response code out of range for uri:" + uri + ". Expected " + range + " but received " + code);
throw new NorthbounderException("response code out of range for uri:" + uri + ". Expected " + range + " but received " + code);
}
}
System.err.println(response != null ? response.getStatusLine().getReasonPhrase() : "Response was null");
LogUtils.debugf(this, response != null ? response.getStatusLine().getReasonPhrase() : "Response was null");
}
private HttpVersion determineHttpVersion(String version) {
HttpVersion httpVersion = null;
if (version != "1.0") {
httpVersion = HttpVersion.HTTP_1_1;
} else {
httpVersion = HttpVersion.HTTP_1_0;
}
return httpVersion;
}
private HttpParams buildParams(HttpVersion protocolVersion,
int connectionTimeout, int socketTimeout, String policy,
String vHost) {
HttpParams parms = new BasicHttpParams();
parms.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, protocolVersion);
parms.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, connectionTimeout);
parms.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, socketTimeout);
parms.setParameter(ClientPNames.COOKIE_POLICY, policy);
parms.setParameter(ClientPNames.VIRTUAL_HOST, new HttpHost(vHost, 8080));
return parms;
}
public HttpNorthbounderConfig getConfig() {
return m_config;
}
public void setConfig(HttpNorthbounderConfig config) {
m_config = config;
}
}