/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2006-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.collectd; import java.beans.PropertyVetoException; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.lang.reflect.UndeclaredThrowableException; import java.net.URI; import java.net.URISyntaxException; import java.security.NoSuchAlgorithmException; import java.sql.SQLException; import java.text.DecimalFormat; import java.text.NumberFormat; import java.text.ParseException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import javax.net.ssl.SSLContext; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.HttpVersion; import org.apache.http.NameValuePair; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.HttpClient; 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.client.utils.URIUtils; import org.apache.http.client.utils.URLEncodedUtils; 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.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.util.EntityUtils; import org.exolab.castor.xml.MarshalException; import org.exolab.castor.xml.ValidationException; import org.opennms.core.utils.EmptyKeyRelaxedTrustProvider; import org.opennms.core.utils.EmptyKeyRelaxedTrustSSLContext; import org.opennms.core.utils.InetAddressUtils; import org.opennms.core.utils.LogUtils; import org.opennms.core.utils.ParameterMap; import org.opennms.core.utils.ThreadCategory; import org.opennms.core.utils.TimeKeeper; import org.opennms.netmgt.config.DataSourceFactory; import org.opennms.netmgt.config.HttpCollectionConfigFactory; import org.opennms.netmgt.config.collector.AttributeDefinition; import org.opennms.netmgt.config.collector.AttributeGroup; import org.opennms.netmgt.config.collector.AttributeGroupType; import org.opennms.netmgt.config.collector.CollectionAttribute; import org.opennms.netmgt.config.collector.CollectionAttributeType; import org.opennms.netmgt.config.collector.CollectionResource; import org.opennms.netmgt.config.collector.CollectionSet; import org.opennms.netmgt.config.collector.CollectionSetVisitor; import org.opennms.netmgt.config.collector.Persister; import org.opennms.netmgt.config.collector.ServiceParameters; import org.opennms.netmgt.config.httpdatacollection.Attrib; import org.opennms.netmgt.config.httpdatacollection.HttpCollection; import org.opennms.netmgt.config.httpdatacollection.Parameter; import org.opennms.netmgt.config.httpdatacollection.Uri; import org.opennms.netmgt.model.RrdRepository; import org.opennms.netmgt.model.events.EventProxy; /** * Collect data via URI * * @author <a href="mailto:david@opennms.org">David Hustace</a> * @version $Id: $ */ public class HttpCollector implements ServiceCollector { private static final int DEFAULT_RETRY_COUNT = 2; private static final String DEFAULT_SO_TIMEOUT = "3000"; private static final NumberFormat PARSER; private static NumberFormat RRD_FORMATTER; static { PARSER = NumberFormat.getNumberInstance(); ((DecimalFormat)PARSER).setParseBigDecimal(true); RRD_FORMATTER = NumberFormat.getNumberInstance(); RRD_FORMATTER.setMinimumFractionDigits(0); RRD_FORMATTER.setMaximumFractionDigits(Integer.MAX_VALUE); RRD_FORMATTER.setMinimumIntegerDigits(1); RRD_FORMATTER.setMaximumIntegerDigits(Integer.MAX_VALUE); RRD_FORMATTER.setGroupingUsed(false); // Make sure that the {@link EmptyKeyRelaxedTrustSSLContext} algorithm // is available to JSSE java.security.Security.addProvider(new EmptyKeyRelaxedTrustProvider()); } /** {@inheritDoc} */ @Override public CollectionSet collect(CollectionAgent agent, EventProxy eproxy, Map<String, Object> parameters) { HttpCollectionSet collectionSet = new HttpCollectionSet(agent, parameters); collectionSet.setCollectionTimestamp(new Date()); collectionSet.collect(); return collectionSet; } protected static ThreadCategory log() { return ThreadCategory.getInstance(HttpCollector.class); } protected class HttpCollectionSet implements CollectionSet { private CollectionAgent m_agent; private Map<String, Object> m_parameters; private Uri m_uriDef; private int m_status; private List<HttpCollectionResource> m_collectionResourceList; private Date m_timestamp; public Uri getUriDef() { return m_uriDef; } public void setUriDef(Uri uriDef) { m_uriDef = uriDef; } HttpCollectionSet(CollectionAgent agent, Map<String, Object> parameters) { m_agent = agent; m_parameters = parameters; m_status=ServiceCollector.COLLECTION_SUCCEEDED; } public void collect() { String collectionName=ParameterMap.getKeyedString(m_parameters, "collection", null); if(collectionName==null) { //Look for the old configuration style: collectionName=ParameterMap.getKeyedString(m_parameters, "http-collection", null); } if (collectionName==null) { LogUtils.debugf(this, "no collection name found in parameters"); m_status=ServiceCollector.COLLECTION_FAILED; return; } HttpCollection collection = HttpCollectionConfigFactory.getInstance().getHttpCollection(collectionName); m_collectionResourceList = new ArrayList<HttpCollectionResource>(); List<Uri> uriDefs = collection.getUris().getUriCollection(); for (Uri uriDef : uriDefs) { m_uriDef = uriDef; HttpCollectionResource collectionResource = new HttpCollectionResource(m_agent, uriDef); try { doCollection(this, collectionResource); m_collectionResourceList.add(collectionResource); } catch (HttpCollectorException e) { log().error("collect: http collection failed: " + e, e); /* * FIXME: This doesn't make sense since everything is SNMP * collection-centric. Should probably let the exception * pass through. */ m_status=ServiceCollector.COLLECTION_FAILED; } } } public CollectionAgent getAgent() { return m_agent; } public void setAgent(CollectionAgent agent) { m_agent = agent; } public Map<String, Object> getParameters() { return m_parameters; } public void setParameters(Map<String, Object> parameters) { m_parameters = parameters; } public int getStatus() { return m_status; } public void storeResults(List<HttpCollectionAttribute> results, HttpCollectionResource collectionResource) { collectionResource.storeResults(results); } public void visit(CollectionSetVisitor visitor) { visitor.visitCollectionSet(this); for (HttpCollectionResource collectionResource : m_collectionResourceList) { collectionResource.visit(visitor); } visitor.completeCollectionSet(this); } public boolean ignorePersist() { return false; } @Override public Date getCollectionTimestamp() { return m_timestamp; } public void setCollectionTimestamp(Date timestamp) { this.m_timestamp = timestamp; } public int getPort() { // This method has been created to deal with NMS-4886 int port = getUriDef().getUrl().getPort(); // Check for service assigned port if UriDef port is not supplied (i.e., is equal to the default port 80) if (port == 80 && m_parameters.containsKey("port")) { try { port = Integer.parseInt(m_parameters.get("port").toString()); log().debug("getPort: using service provided HTTP port " + port); } catch (Exception e) { log().warn("Malformed HTTP port on service definition."); } } return port; } } /** * Performs HTTP collection. * * Couple of notes to make the implementation of this client library * less obtuse: * * - HostConfiguration class is not created here because the library * builds it when a URI is defined. * * @param collectionSet * @throws HttpCollectorException */ private void doCollection(final HttpCollectionSet collectionSet, final HttpCollectionResource collectionResource) throws HttpCollectorException { DefaultHttpClient client = null; HttpUriRequest method = null; try { HttpParams params = buildParams(collectionSet); client = new DefaultHttpClient(params); if ("https".equals(collectionSet.getUriDef().getUrl().getScheme())) { final SchemeRegistry registry = client.getConnectionManager().getSchemeRegistry(); final Scheme https = registry.getScheme("https"); // Override the trust validation with a lenient implementation final SSLSocketFactory factory = new SSLSocketFactory(SSLContext.getInstance(EmptyKeyRelaxedTrustSSLContext.ALGORITHM), SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); final Scheme lenient = new Scheme(https.getName(), https.getDefaultPort(), factory); // This will replace the existing "https" schema registry.register(lenient); } String key = "retry"; if (collectionSet.getParameters().containsKey("retries")) { key = "retries"; } Integer retryCount = ParameterMap.getKeyedInteger(collectionSet.getParameters(), key, DEFAULT_RETRY_COUNT); client.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(retryCount, false)); method = buildHttpMethod(collectionSet); method.getParams().setParameter(CoreProtocolPNames.USER_AGENT, determineUserAgent(collectionSet, params)); buildCredentials(collectionSet, client, method); log().info("doCollection: collecting for client: "+client+" using method: "+method); HttpResponse response = client.execute(method); //Not really a persist as such; it just stores data in collectionSet for later retrieval persistResponse(collectionSet, collectionResource, client, response); } catch (URISyntaxException e) { throw new HttpCollectorException("Error building HttpClient URI", e); } catch (IOException e) { throw new HttpCollectorException("IO Error retrieving page", e); } catch (NoSuchAlgorithmException e) { throw new HttpCollectorException("Could not find EmptyKeyRelaxedTrustSSLContext to allow connection to untrusted HTTPS hosts", e); } catch (PatternSyntaxException e) { throw new HttpCollectorException("Invalid regex specified in HTTP collection configuration: " + e.getMessage(), e); } catch (Throwable e) { throw new HttpCollectorException("Unexpected exception caught during HTTP collection: " + e.getMessage(), e); } finally { // Do we need to do any cleanup? // if (method != null) method.releaseConnection(); } } class HttpCollectionAttribute extends AbstractCollectionAttribute implements AttributeDefinition { String m_alias; String m_type; Object m_value; HttpCollectionResource m_resource; HttpCollectionAttributeType m_attribType; HttpCollectionAttribute(HttpCollectionResource resource, HttpCollectionAttributeType attribType, String alias, String type, Number value) { super(); m_resource=resource; m_attribType=attribType; m_alias = alias; m_type= type; m_value = value; } HttpCollectionAttribute(HttpCollectionResource resource, HttpCollectionAttributeType attribType, String alias, String type, String value) { super(); m_resource=resource; m_attribType=attribType; m_alias = alias; m_type= type; m_value = value; } public String getName() { return m_alias; } public String getType() { return m_type; } public Object getValue() { return m_value; } public String getNumericValue() { Object val = getValue(); if (val instanceof Number) { return val.toString(); } else { try { return Double.valueOf(val.toString()).toString(); } catch (NumberFormatException nfe) { /* Fall through */ } } if (log().isDebugEnabled()) { log().debug("Value for attribute " + this.toString() + " does not appear to be a number, skipping"); } return null; } public String getStringValue() { return getValue().toString(); } public String getValueAsString() { if (m_value instanceof Number) { return RRD_FORMATTER.format(m_value); } else { return m_value.toString(); } } @Override public boolean equals(Object obj) { if (obj instanceof HttpCollectionAttribute) { HttpCollectionAttribute other = (HttpCollectionAttribute)obj; return getName().equals(other.getName()); } return false; } public CollectionAttributeType getAttributeType() { return m_attribType; } public CollectionResource getResource() { return m_resource; } public boolean shouldPersist(ServiceParameters params) { return true; } @Override public int hashCode() { return getName().hashCode(); } @Override public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append("HttpAttribute: "); buffer.append(getName()); buffer.append(":"); buffer.append(getType()); buffer.append(":"); buffer.append(getValueAsString()); return buffer.toString(); } } private List<HttpCollectionAttribute> processResponse(final String responseBodyAsString, final HttpCollectionSet collectionSet, HttpCollectionResource collectionResource) { log().debug("processResponse:"); log().debug("responseBody = " + responseBodyAsString); log().debug("getmatches = " + collectionSet.getUriDef().getUrl().getMatches()); List<HttpCollectionAttribute> butes = new LinkedList<HttpCollectionAttribute>(); int flags = 0; if (collectionSet.getUriDef().getUrl().getCanonicalEquivalence()) flags |= Pattern.CANON_EQ; if (collectionSet.getUriDef().getUrl().getCaseInsensitive()) flags |= Pattern.CASE_INSENSITIVE; if (collectionSet.getUriDef().getUrl().getComments()) flags |= Pattern.COMMENTS; if (collectionSet.getUriDef().getUrl().getDotall()) flags |= Pattern.DOTALL; if (collectionSet.getUriDef().getUrl().getLiteral()) flags |= Pattern.LITERAL; if (collectionSet.getUriDef().getUrl().getMultiline()) flags |= Pattern.MULTILINE; if (collectionSet.getUriDef().getUrl().getUnicodeCase()) flags |= Pattern.UNICODE_CASE; if (collectionSet.getUriDef().getUrl().getUnixLines()) flags |= Pattern.UNIX_LINES; log().debug("flags = " + flags); Pattern p = Pattern.compile(collectionSet.getUriDef().getUrl().getMatches(), flags); Matcher m = p.matcher(responseBodyAsString); final boolean matches = m.matches(); if (matches) { log().debug("processResponse: found matching attributes: "+matches); List<Attrib> attribDefs = collectionSet.getUriDef().getAttributes().getAttribCollection(); AttributeGroupType groupType = new AttributeGroupType(collectionSet.getUriDef().getName(),"all"); for (Attrib attribDef : attribDefs) { if (! attribDef.getType().matches("^([Oo](ctet|CTET)[Ss](tring|TRING))|([Ss](tring|TRING))$")) { try { Number num = NumberFormat.getNumberInstance().parse(m.group(attribDef.getMatchGroup())); HttpCollectionAttribute bute = new HttpCollectionAttribute( collectionResource, new HttpCollectionAttributeType(attribDef, groupType), attribDef.getAlias(), attribDef.getType(), num); log().debug("processResponse: adding found numeric attribute: "+bute); butes.add(bute); } catch (IndexOutOfBoundsException e) { log().error("IndexOutOfBoundsException thrown while trying to find regex group, your regex does not contain the following group index: " + attribDef.getMatchGroup()); log().error("Regex statement: " + collectionSet.getUriDef().getUrl().getMatches()); } catch (ParseException e) { log().error("attribute "+attribDef.getAlias()+" failed to match a parsable number! Matched \""+m.group(attribDef.getMatchGroup())+"\" instead."); } } else { HttpCollectionAttribute bute = new HttpCollectionAttribute( collectionResource, new HttpCollectionAttributeType(attribDef, groupType), attribDef.getAlias(), attribDef.getType(), m.group(attribDef.getMatchGroup())); log().debug("processResponse: adding found string attribute: " + bute); butes.add(bute); } } } else { log().debug("processResponse: found matching attributes: "+matches); } return butes; } public class HttpCollectorException extends RuntimeException { private static final long serialVersionUID = 4413332529546573490L; HttpCollectorException(String message) { super(message); } HttpCollectorException(String message, Throwable e) { super(message); } @Override public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(super.toString()); buffer.append(": client URL: "); return buffer.toString(); } } private void persistResponse(final HttpCollectionSet collectionSet, HttpCollectionResource collectionResource, final HttpClient client, final HttpResponse method) throws IOException { String responseString = EntityUtils.toString(method.getEntity()); if (responseString != null && !"".equals(responseString)) { List<HttpCollectionAttribute> attributes = processResponse(responseString, collectionSet, collectionResource); if (attributes.isEmpty()) { log().warn("doCollection: no attributes defined by the response: " + responseString.trim()); throw new HttpCollectorException("No attributes specified were found: "); } //put the results into the collectionset for later collectionSet.storeResults(attributes, collectionResource); } } private static void buildCredentials(final HttpCollectionSet collectionSet, final DefaultHttpClient client, final HttpUriRequest method) { if (collectionSet.getUriDef().getUrl().getUserInfo() != null) { String userInfo = collectionSet.getUriDef().getUrl().getUserInfo(); String[] streetCred = userInfo.split(":", 2); if (streetCred.length == 2) { client.getCredentialsProvider().setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(streetCred[0], streetCred[1])); } else { log().warn("Illegal value found for username/password HTTP credentials: " + userInfo); } } } private static HttpParams buildParams(final HttpCollectionSet collectionSet) { HttpParams params = new BasicHttpParams(); params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, computeVersion(collectionSet.getUriDef())); params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, Integer.parseInt(ParameterMap.getKeyedString(collectionSet.getParameters(), "timeout", DEFAULT_SO_TIMEOUT))); params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, Integer.parseInt(ParameterMap.getKeyedString(collectionSet.getParameters(), "timeout", DEFAULT_SO_TIMEOUT))); params.setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY); //review the httpclient code, looks like virtual host is checked for null //and if true, sets Host to the connection's host property String virtualHost = collectionSet.getUriDef().getUrl().getVirtualHost(); if (virtualHost != null) { params.setParameter( ClientPNames.VIRTUAL_HOST, new HttpHost(virtualHost, collectionSet.getPort()) ); } return params; } private static String determineUserAgent(final HttpCollectionSet collectionSet, final HttpParams params) { String userAgent = collectionSet.getUriDef().getUrl().getUserAgent(); return (String) (userAgent == null ? params.getParameter(CoreProtocolPNames.USER_AGENT) : userAgent); } private static HttpVersion computeVersion(final Uri uri) { return new HttpVersion(Integer.parseInt(uri.getUrl().getHttpVersion().substring(0, 1)), Integer.parseInt(uri.getUrl().getHttpVersion().substring(2))); } private static HttpUriRequest buildHttpMethod(final HttpCollectionSet collectionSet) throws URISyntaxException { HttpUriRequest method; URI uri = buildUri(collectionSet); if ("GET".equals(collectionSet.getUriDef().getUrl().getMethod())) { method = buildGetMethod(uri, collectionSet); } else { method = buildPostMethod(uri, collectionSet); } return method; } private static HttpPost buildPostMethod(final URI uri, final HttpCollectionSet collectionSet) { HttpPost method = new HttpPost(uri); List<NameValuePair> postParams = buildRequestParameters(collectionSet); try { UrlEncodedFormEntity entity = new UrlEncodedFormEntity(postParams, "UTF-8"); method.setEntity(entity); } catch (UnsupportedEncodingException e) { // Should never happen } return method; } private static HttpGet buildGetMethod(final URI uri, final HttpCollectionSet collectionSet) { URI uriWithQueryString = null; List<NameValuePair> queryParams = buildRequestParameters(collectionSet); try { StringBuffer query = new StringBuffer(); query.append(URLEncodedUtils.format(queryParams, "UTF-8")); if (uri.getQuery() != null && uri.getQuery().length() > 0) { if (query.length() > 0) { query.append("&"); } query.append(uri.getQuery()); } uriWithQueryString = URIUtils.createURI( uri.getScheme(), uri.getHost(), uri.getPort(), uri.getPath(), query.length() > 0 ? query.toString() : null, uri.getFragment() ); return new HttpGet(uriWithQueryString); } catch (URISyntaxException e) { log().warn(e.getMessage(), e); return new HttpGet(uri); } } private static List<NameValuePair> buildRequestParameters(final HttpCollectionSet collectionSet) { List<NameValuePair> retval = new ArrayList<NameValuePair>(); if (collectionSet.getUriDef().getUrl().getParameters() == null) return retval; List<Parameter> parameters = collectionSet.getUriDef().getUrl().getParameters().getParameterCollection(); for (Parameter p : parameters) { retval.add(new BasicNameValuePair(p.getKey(), p.getValue())); } return retval; } private static URI buildUri(final HttpCollectionSet collectionSet) throws URISyntaxException { HashMap<String,String> substitutions = new HashMap<String,String>(); substitutions.put("ipaddr", InetAddressUtils.str(collectionSet.getAgent().getInetAddress())); substitutions.put("nodeid", Integer.toString(collectionSet.getAgent().getNodeId())); return URIUtils.createURI(collectionSet.getUriDef().getUrl().getScheme(), substituteKeywords(substitutions, collectionSet.getUriDef().getUrl().getHost(), "getHost"), collectionSet.getPort(), substituteKeywords(substitutions, collectionSet.getUriDef().getUrl().getPath(), "getURL"), substituteKeywords(substitutions, collectionSet.getUriDef().getUrl().getQuery(), "getQuery"), substituteKeywords(substitutions, collectionSet.getUriDef().getUrl().getFragment(), "getFragment")); } private static String substituteKeywords(final HashMap<String,String> substitutions, final String urlFragment, final String desc) { String newFragment = urlFragment; if (newFragment != null) { for (String key : substitutions.keySet()) { newFragment = newFragment.replaceAll("\\$\\{" + key + "\\}", substitutions.get(key)); } if (log().isDebugEnabled() && newFragment.compareTo(urlFragment) != 0) { log().debug("doSubs: "+desc+" substituted as \""+newFragment+"\""); } } return newFragment; } /** {@inheritDoc} * @throws CollectionInitializationException */ @Override public void initialize(Map<String, String> parameters) throws CollectionInitializationException { log().debug("initialize: Initializing HttpCollector."); initHttpCollectionConfig(); initDatabaseConnectionFactory(); initializeRrdRepository(); } private static void initHttpCollectionConfig() { try { log().debug("initialize: Initializing collector: " + HttpCollector.class.getSimpleName()); HttpCollectionConfigFactory.init(); } catch (MarshalException e) { log().fatal("initialize: Error marshalling configuration.", e); throw new UndeclaredThrowableException(e); } catch (ValidationException e) { log().fatal("initialize: Error validating configuration.", e); throw new UndeclaredThrowableException(e); } catch (FileNotFoundException e) { log().fatal("initialize: Error locating configuration.", e); throw new UndeclaredThrowableException(e); } catch (IOException e) { log().fatal("initialize: Error reading configuration", e); throw new UndeclaredThrowableException(e); } } private static void initializeRrdRepository() throws CollectionInitializationException { log().debug("initializeRrdRepository: Initializing RRD repo from HttpCollector..."); initializeRrdDirs(); } private static void initializeRrdDirs() throws CollectionInitializationException { /* * If the RRD file repository directory does NOT already exist, create * it. */ StringBuffer sb; File f = new File(HttpCollectionConfigFactory.getInstance().getRrdPath()); if (!f.isDirectory()) { if (!f.mkdirs()) { sb = new StringBuffer(); sb.append("initializeRrdDirs: Unable to create RRD file repository. Path doesn't already exist and could not make directory: "); sb.append(HttpCollectionConfigFactory.getInstance().getRrdPath()); log().error(sb.toString()); throw new CollectionInitializationException(sb.toString()); } } } private static void initDatabaseConnectionFactory() { try { DataSourceFactory.init(); } catch (IOException e) { log().fatal("initDatabaseConnectionFactory: IOException getting database connection", e); throw new UndeclaredThrowableException(e); } catch (MarshalException e) { log().fatal("initDatabaseConnectionFactory: Marshall Exception getting database connection", e); throw new UndeclaredThrowableException(e); } catch (ValidationException e) { log().fatal("initDatabaseConnectionFactory: Validation Exception getting database connection", e); throw new UndeclaredThrowableException(e); } catch (SQLException e) { log().fatal("initDatabaseConnectionFactory: Failed getting connection to the database.", e); throw new UndeclaredThrowableException(e); } catch (PropertyVetoException e) { log().fatal("initDatabaseConnectionFactory: Failed getting connection to the database.", e); throw new UndeclaredThrowableException(e); } catch (ClassNotFoundException e) { log().fatal("initDatabaseConnectionFactory: Failed loading database driver.", e); throw new UndeclaredThrowableException(e); } } /** {@inheritDoc} */ @Override public void initialize(CollectionAgent agent, Map<String, Object> parameters) { log().debug("initialize: Initializing HTTP collection for agent: "+agent); // Add any initialization here } /** * <p>release</p> */ @Override public void release() { // TODO Auto-generated method stub } /** {@inheritDoc} */ @Override public void release(CollectionAgent agent) { // TODO Auto-generated method stub } class HttpCollectionResource implements CollectionResource { CollectionAgent m_agent; AttributeGroup m_attribGroup; HttpCollectionResource(CollectionAgent agent, Uri uriDef) { m_agent=agent; m_attribGroup=new AttributeGroup(this, new AttributeGroupType(uriDef.getName(), "all")); } public void storeResults(List<HttpCollectionAttribute> results) { for(HttpCollectionAttribute attrib: results) { m_attribGroup.addAttribute(attrib); } } //A rescan is never needed for the HttpCollector public boolean rescanNeeded() { return false; } public boolean shouldPersist(ServiceParameters params) { return true; } public String getOwnerName() { return m_agent.getHostAddress(); } public File getResourceDir(RrdRepository repository) { return new File(repository.getRrdBaseDir(), Integer.toString(m_agent.getNodeId())); } public void visit(CollectionSetVisitor visitor) { visitor.visitResource(this); m_attribGroup.visit(visitor); visitor.completeResource(this); } public int getType() { return -1; //Is this right? } public String getResourceTypeName() { return "node"; //All node resources for HTTP; nothing of interface or "indexed resource" type } public String getInstance() { return null; } public String getLabel() { return null; } public String getParent() { return Integer.toString(m_agent.getNodeId()); } public TimeKeeper getTimeKeeper() { return null; } } class HttpCollectionAttributeType implements CollectionAttributeType { Attrib m_attribute; AttributeGroupType m_groupType; protected HttpCollectionAttributeType(Attrib attribute, AttributeGroupType groupType) { m_groupType=groupType; m_attribute=attribute; } public AttributeGroupType getGroupType() { return m_groupType; } public void storeAttribute(CollectionAttribute attribute, Persister persister) { if(m_attribute.getType().equals("string")) { persister.persistStringAttribute(attribute); } else { persister.persistNumericAttribute(attribute); } } public String getName() { return m_attribute.getAlias(); } public String getType() { return m_attribute.getType(); } } /** {@inheritDoc} */ public RrdRepository getRrdRepository(String collectionName) { return HttpCollectionConfigFactory.getInstance().getRrdRepository(collectionName); } }