diff --git a/base/configobject.cpp b/base/configobject.cpp
index 49b7e529f..793882019 100644
--- a/base/configobject.cpp
+++ b/base/configobject.cpp
@@ -75,6 +75,19 @@ bool ConfigObject::IsLocal(void) const
 	return value;
 }
 
+
+void ConfigObject::SetTemporary(bool value)
+{
+	GetProperties()->SetProperty("__temporary", value ? 1 : 0);
+}
+
+bool ConfigObject::IsTemporary(void) const
+{
+	bool value = false;
+	GetProperties()->GetProperty("__temporary", &value);
+	return value;
+}
+
 void ConfigObject::SetAbstract(bool value)
 {
 	GetProperties()->SetProperty("__abstract", value ? 1 : 0);
diff --git a/base/configobject.h b/base/configobject.h
index 05472ed4b..cbd2fc4cd 100644
--- a/base/configobject.h
+++ b/base/configobject.h
@@ -71,6 +71,9 @@ public:
 	void SetLocal(bool value);
 	bool IsLocal(void) const;
 
+	void SetTemporary(bool value);
+	bool IsTemporary(void) const;
+
 	void SetAbstract(bool value);
 	bool IsAbstract(void) const;
 
diff --git a/base/socket.cpp b/base/socket.cpp
index 97b46c049..b61036688 100644
--- a/base/socket.cpp
+++ b/base/socket.cpp
@@ -163,7 +163,7 @@ void Socket::HandleSocketError(const std::exception& ex)
 {
 	if (!OnError.empty()) {
 		Event::Ptr ev = boost::make_shared<Event>();
-		ev->OnEventDelivered.connect(boost::bind(boost::ref(OnError), GetSelf(), ex));
+		ev->OnEventDelivered.connect(boost::bind(boost::ref(OnError), GetSelf(), runtime_error(ex.what())));
 		Event::Post(ev);
 
 		CloseInternal(false);
diff --git a/components/Makefile.am b/components/Makefile.am
index d2dc2039c..781a6f53f 100644
--- a/components/Makefile.am
+++ b/components/Makefile.am
@@ -3,6 +3,7 @@
 
 SUBDIRS = \
 	checker \
+	compat \
 	configfile \
 	configrpc \
 	delegation \
diff --git a/components/checker/checkercomponent.cpp b/components/checker/checkercomponent.cpp
index 862b7e992..0e414d68e 100644
--- a/components/checker/checkercomponent.cpp
+++ b/components/checker/checkercomponent.cpp
@@ -34,7 +34,7 @@ void CheckerComponent::Start(void)
 	m_CheckerEndpoint->RegisterTopicHandler("checker::ClearServices",
 		boost::bind(&CheckerComponent::ClearServicesRequestHandler, this, _2, _3));
 	m_CheckerEndpoint->RegisterPublication("checker::CheckResult");
-	GetEndpointManager()->RegisterEndpoint(m_CheckerEndpoint);
+	EndpointManager::GetInstance()->RegisterEndpoint(m_CheckerEndpoint);
 
 	m_CheckTimer = boost::make_shared<Timer>();
 	m_CheckTimer->SetInterval(5);
@@ -51,7 +51,7 @@ void CheckerComponent::Start(void)
 
 void CheckerComponent::Stop(void)
 {
-	EndpointManager::Ptr mgr = GetEndpointManager();
+	EndpointManager::Ptr mgr = EndpointManager::GetInstance();
 
 	if (mgr)
 		mgr->UnregisterEndpoint(m_CheckerEndpoint);
@@ -134,6 +134,13 @@ void CheckerComponent::ResultTimerHandler(void)
 		/* update service state */
 		service.ApplyCheckResult(result);
 
+		/* figure out when the next check is for this service */
+		service.UpdateNextCheck();
+
+		/* remove the service from the list of pending services */
+		m_PendingServices.erase(service.GetConfigObject());
+		m_Services.push(service);
+
 		RequestMessage rm;
 		rm.SetMethod("checker::CheckResult");
 
@@ -142,15 +149,12 @@ void CheckerComponent::ResultTimerHandler(void)
 		params.SetProperty("state", static_cast<long>(service.GetState()));
 		params.SetProperty("state_type", static_cast<long>(service.GetStateType()));
 		params.SetProperty("current_attempt", static_cast<long>(service.GetCurrentCheckAttempt()));
+		params.SetProperty("next_check", static_cast<long>(service.GetNextCheck()));
 		params.SetProperty("result", result.GetDictionary());
 
 		rm.SetParams(params);
 
-		GetEndpointManager()->SendMulticastMessage(m_CheckerEndpoint, rm);
-
-		service.SetNextCheck(now + service.GetCheckInterval());
-		m_PendingServices.erase(service.GetConfigObject());
-		m_Services.push(service);
+		EndpointManager::GetInstance()->SendMulticastMessage(m_CheckerEndpoint, rm);
 	}
 
 	if (min_latency > 5) {
@@ -195,7 +199,7 @@ void CheckerComponent::AssignServiceRequestHandler(const Endpoint::Ptr& sender,
 
 		MessagePart result;
 		rm.SetResult(result);
-		GetEndpointManager()->SendUnicastMessage(m_CheckerEndpoint, sender, rm);
+		EndpointManager::GetInstance()->SendUnicastMessage(m_CheckerEndpoint, sender, rm);
 	}
 }
 
diff --git a/components/checker/checkercomponent.h b/components/checker/checkercomponent.h
index d8ed642da..f3c35f6eb 100644
--- a/components/checker/checkercomponent.h
+++ b/components/checker/checkercomponent.h
@@ -35,7 +35,7 @@ public:
 /**
  * @ingroup checker
  */
-class CheckerComponent : public IcingaComponent
+class CheckerComponent : public Component
 {
 public:
 	typedef shared_ptr<CheckerComponent> Ptr;
diff --git a/components/compat/Makefile.am b/components/compat/Makefile.am
new file mode 100644
index 000000000..ea353d109
--- /dev/null
+++ b/components/compat/Makefile.am
@@ -0,0 +1,27 @@
+## Process this file with automake to produce Makefile.in
+
+pkglib_LTLIBRARIES = \
+	compat.la
+
+compat_la_SOURCES = \
+	compatcomponent.cpp \
+	compatcomponent.h \
+	i2-compat.h
+
+compat_la_CPPFLAGS = \
+	$(BOOST_CPPFLAGS) \
+	-I${top_srcdir}/base \
+	-I${top_srcdir}/jsonrpc \
+	-I${top_srcdir}/icinga
+
+compat_la_LDFLAGS = \
+	$(BOOST_LDFLAGS) \
+	-module \
+	-no-undefined \
+	@RELEASE_INFO@ \
+	@VERSION_INFO@
+
+compat_la_LIBADD = \
+	${top_builddir}/base/libbase.la \
+	${top_builddir}/jsonrpc/libjsonrpc.la \
+	${top_builddir}/icinga/libicinga.la
diff --git a/components/compat/compatcomponent.cpp b/components/compat/compatcomponent.cpp
new file mode 100644
index 000000000..a32ee47d1
--- /dev/null
+++ b/components/compat/compatcomponent.cpp
@@ -0,0 +1,208 @@
+/******************************************************************************
+ * Icinga 2                                                                   *
+ * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/)        *
+ *                                                                            *
+ * This program 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 2             *
+ * of the License, or (at your option) any later version.                     *
+ *                                                                            *
+ * This program 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 this program; if not, write to the Free Software Foundation     *
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
+ ******************************************************************************/
+
+#include "i2-compat.h"
+
+using namespace icinga;
+
+/**
+ * Returns the name of the component.
+ *
+ * @returns The name.
+ */
+string CompatComponent::GetName(void) const
+{
+	return "compat";
+}
+
+/**
+ * Starts the component.
+ */
+void CompatComponent::Start(void)
+{
+	m_StatusTimer = boost::make_shared<Timer>();
+	m_StatusTimer->SetInterval(15);
+	m_StatusTimer->OnTimerExpired.connect(boost::bind(&CompatComponent::StatusTimerHandler, this));
+	m_StatusTimer->Start();
+
+	CIB::RequireInformation(CIB_ProgramStatus);
+	CIB::RequireInformation(CIB_ServiceStatus);
+}
+
+/**
+ * Stops the component.
+ */
+void CompatComponent::Stop(void)
+{
+}
+
+void CompatComponent::DumpHostStatus(ofstream& fp, Host host)
+{
+	fp << "hoststatus {" << endl
+	   << "\t" << "host_name=" << host.GetName() << endl
+	   << "\t" << "has_been_checked=1" << endl
+	   << "\t" << "should_be_scheduled=1" << endl
+	   << "\t" << "check_execution_time=0" << endl
+	   << "\t" << "check_latency=0" << endl
+	   << "\t" << "current_state=0" << endl
+	   << "\t" << "last_check=" << time(NULL) << endl
+	   << "\t" << "next_check=" << time(NULL) << endl
+	   << "\t" << "current_attempt=1" << endl
+	   << "\t" << "max_attempts=1" << endl
+	   << "\t" << "active_checks_enabled=1" << endl
+	   << "\t" << "passive_checks_enabled=1" << endl
+	   << "\t" << "}" << endl
+	   << endl;
+}
+
+void CompatComponent::DumpHostObject(ofstream& fp, Host host)
+{
+	fp << "define host {" << endl
+	   << "\t" << "host_name" << "\t" << host.GetName() << endl
+	   << "\t" << "hostgroups" << "\t" << "all-hosts" << endl
+	   << "\t" << "check_interval" << "\t" << 1 << endl
+	   << "\t" << "retry_interval" << "\t" << 1 << endl
+	   << "\t" << "max_check_attempts" << "\t" << 1 << endl
+	   << "\t" << "active_checks_enabled" << "\t" << 1 << endl
+	   << "\t" << "passive_checks_enabled" << "\t" << 1 << endl
+	   << "\t" << "}" << endl
+	   << endl;
+}
+
+void CompatComponent::DumpServiceStatus(ofstream& fp, Service service)
+{
+	Dictionary::Ptr cr;
+	cr = service.GetLastCheckResult();
+
+	string plugin_output;
+	long start_time = -1, end_time = -1;
+	if (cr) {
+		cr->GetProperty("output", &plugin_output);
+		cr->GetProperty("start_time", &start_time);
+		cr->GetProperty("end_time", &end_time);
+	}
+
+	fp << "servicestatus {" << endl
+           << "\t" << "host_name=" << service.GetHost().GetName() << endl
+	   << "\t" << "service_description=" << service.GetDisplayName() << endl
+	   << "\t" << "check_interval=" << service.GetCheckInterval() / 60.0 << endl
+	   << "\t" << "retry_interval=" << service.GetRetryInterval() / 60.0 << endl
+	   << "\t" << "has_been_checked=" << (end_time == -1 ? 0 : 1) << endl
+	   << "\t" << "should_be_scheduled=1" << endl
+	   << "\t" << "check_execution_time=" << end_time - start_time << endl
+	   << "\t" << "check_latency=0" << endl
+	   << "\t" << "current_state=" << service.GetState() << endl
+	   << "\t" << "plugin_output=" << plugin_output << endl
+	   << "\t" << "last_check=" << start_time << endl
+	   << "\t" << "next_check=" << service.GetNextCheck() << endl
+	   << "\t" << "current_attempt=" << service.GetCurrentCheckAttempt() << endl
+	   << "\t" << "max_attempts=" << service.GetMaxCheckAttempts() << endl
+	   << "\t" << "last_state_change=" << service.GetLastStateChange() << endl
+	   << "\t" << "last_hard_state_change=" << service.GetLastHardStateChange() << endl
+	   << "\t" << "last_update=" << time(NULL) << endl
+	   << "\t" << "active_checks_enabled=1" << endl
+	   << "\t" << "passive_checks_enabled=1" << endl
+	   << "\t" << "}" << endl
+	   << endl;
+}
+
+void CompatComponent::DumpServiceObject(ofstream& fp, Service service)
+{
+	fp << "define service {" << endl
+	   << "\t" << "host_name" << "\t" << service.GetHost().GetName() << endl
+	   << "\t" << "service_description" << "\t" << service.GetDisplayName() << endl
+	   << "\t" << "check_command" << "\t" << "check_i2" << endl
+	   << "\t" << "check_interval" << "\t" << service.GetCheckInterval() / 60.0 << endl
+	   << "\t" << "retry_interval" << "\t" << service.GetRetryInterval() / 60.0 << endl
+	   << "\t" << "max_check_attempts" << "\t" << 1 << endl
+	   << "\t" << "active_checks_enabled" << "\t" << 1 << endl
+	   << "\t" << "passive_checks_enabled" << "\t" << 1 << endl
+	   << "\t" << "}" << endl
+	   << endl;
+}
+
+/**
+ * Periodically writes the status.dat and objects.cache files.
+ */
+void CompatComponent::StatusTimerHandler(void)
+{
+	ofstream statusfp;
+	statusfp.open("status.dat.tmp", ofstream::out | ofstream::trunc);
+
+	statusfp << "# Icinga status file" << endl
+		 << "# This file is auto-generated. Do not modify this file." << endl
+		 << endl;
+
+	statusfp << "info {" << endl
+		 << "\t" << "created=" << time(NULL) << endl
+		 << "\t" << "version=2.0" << endl
+		 << "\t" << "}" << endl
+		 << endl;
+
+	ofstream objectfp;
+	objectfp.open("objects.cache.tmp", ofstream::out | ofstream::trunc);
+
+	objectfp << "# Icinga object cache file" << endl
+		 << "# This file is auto-generated. Do not modify this file." << endl
+		 << endl;
+
+	objectfp << "define hostgroup {" << endl
+		 << "\t" << "hostgroup_name" << "\t" << "all-hosts" << endl;
+
+	ConfigObject::TMap::Range range;
+	range = ConfigObject::GetObjects("host");
+
+	ConfigObject::TMap::Iterator it;
+
+	if (range.first != range.second) {
+		objectfp << "\t" << "members" << "\t";
+		for (it = range.first; it != range.second; it++) {
+			Host host(it->second);
+
+			objectfp << host.GetName();
+
+			if (distance(it, range.second) != 1)
+				objectfp << ",";
+		}
+		objectfp << endl;
+	}
+
+	objectfp << "\t" << "}" << endl
+		 << endl;
+
+	for (it = range.first; it != range.second; it++) {
+		DumpHostStatus(statusfp, it->second);
+		DumpHostObject(objectfp, it->second);
+	}
+
+	range = ConfigObject::GetObjects("service");
+
+	for (it = range.first; it != range.second; it++) {
+		DumpServiceStatus(statusfp, it->second);
+		DumpServiceObject(objectfp, it->second);
+	}
+
+	statusfp.close();
+	rename("status.dat.tmp", "status.dat");
+
+	objectfp.close();
+	rename("objects.cache.tmp", "objects.cache");
+}
+
+EXPORT_COMPONENT(compat, CompatComponent);
diff --git a/icinga/icingacomponent.cpp b/components/compat/compatcomponent.h
similarity index 72%
rename from icinga/icingacomponent.cpp
rename to components/compat/compatcomponent.h
index f33f4bb34..ba31359ab 100644
--- a/icinga/icingacomponent.cpp
+++ b/components/compat/compatcomponent.h
@@ -17,22 +17,34 @@
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
  ******************************************************************************/
 
-#include "i2-icinga.h"
+#ifndef COMPATCOMPONENT_H
+#define COMPATCOMPONENT_H
 
-using namespace icinga;
-
-IcingaApplication::Ptr IcingaComponent::GetIcingaApplication(void) const
+namespace icinga
 {
-	Application::Ptr application = Application::GetInstance();
-	return static_pointer_cast<IcingaApplication>(application);
+
+/**
+ * @ingroup compat
+ */
+class CompatComponent : public Component
+{
+public:
+	virtual string GetName(void) const;
+	virtual void Start(void);
+	virtual void Stop(void);
+
+private:
+	Timer::Ptr m_StatusTimer;
+
+	void DumpHostStatus(ofstream& fp, Host host);
+	void DumpHostObject(ofstream& fp, Host host);
+
+	void DumpServiceStatus(ofstream& fp, Service service);
+	void DumpServiceObject(ofstream& fp, Service service);
+
+	void StatusTimerHandler(void);
+};
+
 }
 
-EndpointManager::Ptr IcingaComponent::GetEndpointManager(void) const
-{
-	IcingaApplication::Ptr app = GetIcingaApplication();
-
-	if (!app)
-		return EndpointManager::Ptr();
-
-	return app->GetEndpointManager();
-}
+#endif /* COMPATCOMPONENT_H */
diff --git a/icinga/icingacomponent.h b/components/compat/i2-compat.h
similarity index 79%
rename from icinga/icingacomponent.h
rename to components/compat/i2-compat.h
index 700409353..4ca14d47d 100644
--- a/icinga/icingacomponent.h
+++ b/components/compat/i2-compat.h
@@ -17,24 +17,24 @@
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
  ******************************************************************************/
 
-#ifndef ICINGACOMPONENT_H
-#define ICINGACOMPONENT_H
-
-namespace icinga
-{
+#ifndef I2COMPAT_H
+#define I2COMPAT_H
 
 /**
- * A component that can be loaded into the Icinga application at run-time.
+ * @defgroup compat Compat component
  *
- * @ingroup icinga
+ * The compat component implements compatibility functionality for Icinga 1.x.
  */
-class I2_ICINGA_API IcingaComponent : public Component
-{
-protected:
-	IcingaApplication::Ptr GetIcingaApplication(void) const;
-	EndpointManager::Ptr GetEndpointManager(void) const;
-};
 
-}
+#include <i2-base.h>
+#include <i2-jsonrpc.h>
+#include <i2-icinga.h>
 
-#endif /* ICINGACOMPONENT_H */
+#include <fstream>
+
+using std::ofstream;
+using std::endl;
+
+#include "compatcomponent.h"
+
+#endif /* I2COMPAT_H */
diff --git a/components/configrpc/configrpccomponent.cpp b/components/configrpc/configrpccomponent.cpp
index 4d9f017cb..3b6412f36 100644
--- a/components/configrpc/configrpccomponent.cpp
+++ b/components/configrpc/configrpccomponent.cpp
@@ -28,7 +28,7 @@ string ConfigRpcComponent::GetName(void) const
 
 void ConfigRpcComponent::Start(void)
 {
-	EndpointManager::Ptr endpointManager = GetEndpointManager();
+	EndpointManager::Ptr endpointManager = EndpointManager::GetInstance();
 
 	m_ConfigRpcEndpoint = boost::make_shared<VirtualEndpoint>();
 
@@ -58,7 +58,7 @@ void ConfigRpcComponent::Start(void)
 
 void ConfigRpcComponent::Stop(void)
 {
-	EndpointManager::Ptr mgr = GetEndpointManager();
+	EndpointManager::Ptr mgr = EndpointManager::GetInstance();
 
 	if (mgr)
 		mgr->UnregisterEndpoint(m_ConfigRpcEndpoint);
@@ -78,7 +78,7 @@ void ConfigRpcComponent::SessionEstablishedHandler(const Endpoint::Ptr& endpoint
 	RequestMessage request;
 	request.SetMethod("config::FetchObjects");
 
-	GetEndpointManager()->SendUnicastMessage(m_ConfigRpcEndpoint, endpoint, request);
+	EndpointManager::GetInstance()->SendUnicastMessage(m_ConfigRpcEndpoint, endpoint, request);
 }
 
 RequestMessage ConfigRpcComponent::MakeObjectMessage(const ConfigObject::Ptr& object, string method, bool includeProperties)
@@ -115,7 +115,7 @@ void ConfigRpcComponent::FetchObjectsHandler(const Endpoint::Ptr& sender)
 
 		RequestMessage request = MakeObjectMessage(object, "config::ObjectCreated", true);
 
-		GetEndpointManager()->SendUnicastMessage(m_ConfigRpcEndpoint, sender, request);
+		EndpointManager::GetInstance()->SendUnicastMessage(m_ConfigRpcEndpoint, sender, request);
 	}
 }
 
@@ -124,7 +124,7 @@ void ConfigRpcComponent::LocalObjectCommittedHandler(const ConfigObject::Ptr& ob
 	if (!ShouldReplicateObject(object))
 		return;
 
-	GetEndpointManager()->SendMulticastMessage(m_ConfigRpcEndpoint,
+	EndpointManager::GetInstance()->SendMulticastMessage(m_ConfigRpcEndpoint,
 	    MakeObjectMessage(object, "config::ObjectCreated", true));
 }
 
@@ -133,7 +133,7 @@ void ConfigRpcComponent::LocalObjectRemovedHandler(const ConfigObject::Ptr& obje
 	if (!ShouldReplicateObject(object))
 		return;
 
-	GetEndpointManager()->SendMulticastMessage(m_ConfigRpcEndpoint,
+	EndpointManager::GetInstance()->SendMulticastMessage(m_ConfigRpcEndpoint,
 	    MakeObjectMessage(object, "config::ObjectRemoved", false));
 }
 
diff --git a/components/configrpc/configrpccomponent.h b/components/configrpc/configrpccomponent.h
index ed73370f7..001107ac5 100644
--- a/components/configrpc/configrpccomponent.h
+++ b/components/configrpc/configrpccomponent.h
@@ -26,7 +26,7 @@ namespace icinga
 /**
  * @ingroup configrpc
  */
-class ConfigRpcComponent : public IcingaComponent
+class ConfigRpcComponent : public Component
 {
 public:
 	virtual string GetName(void) const;
diff --git a/components/delegation/delegationcomponent.cpp b/components/delegation/delegationcomponent.cpp
index 95dad7f9f..efc5c9103 100644
--- a/components/delegation/delegationcomponent.cpp
+++ b/components/delegation/delegationcomponent.cpp
@@ -42,15 +42,17 @@ void DelegationComponent::Start(void)
 	m_DelegationEndpoint = boost::make_shared<VirtualEndpoint>();
 	m_DelegationEndpoint->RegisterPublication("checker::AssignService");
 	m_DelegationEndpoint->RegisterPublication("checker::ClearServices");
-	m_DelegationEndpoint->RegisterSubscription("checker::CheckResult");
-	GetEndpointManager()->RegisterEndpoint(m_DelegationEndpoint);
+	m_DelegationEndpoint->RegisterTopicHandler("checker::CheckResult",
+	    boost::bind(&DelegationComponent::CheckResultRequestHandler, this, _2, _3));
+	m_DelegationEndpoint->RegisterPublication("delegation::ServiceStatus");
+	EndpointManager::GetInstance()->RegisterEndpoint(m_DelegationEndpoint);
 
-	GetEndpointManager()->OnNewEndpoint.connect(bind(&DelegationComponent::NewEndpointHandler, this, _2));
+	EndpointManager::GetInstance()->OnNewEndpoint.connect(bind(&DelegationComponent::NewEndpointHandler, this, _2));
 }
 
 void DelegationComponent::Stop(void)
 {
-	EndpointManager::Ptr mgr = GetEndpointManager();
+	EndpointManager::Ptr mgr = EndpointManager::GetInstance();
 
 	if (mgr)
 		mgr->UnregisterEndpoint(m_DelegationEndpoint);
@@ -75,7 +77,7 @@ void DelegationComponent::AssignService(const Endpoint::Ptr& checker, const Serv
 
 	Application::Log(LogDebug, "delegation", "Trying to delegate service '" + service.GetName() + "'");
 
-	GetEndpointManager()->SendUnicastMessage(m_DelegationEndpoint, checker, request);
+	EndpointManager::GetInstance()->SendUnicastMessage(m_DelegationEndpoint, checker, request);
 }
 
 void DelegationComponent::ClearServices(const Endpoint::Ptr& checker)
@@ -86,7 +88,12 @@ void DelegationComponent::ClearServices(const Endpoint::Ptr& checker)
 	MessagePart params;
 	request.SetParams(params);
 
-	GetEndpointManager()->SendUnicastMessage(m_DelegationEndpoint, checker, request);
+	EndpointManager::GetInstance()->SendUnicastMessage(m_DelegationEndpoint, checker, request);
+}
+
+bool DelegationComponent::IsEndpointChecker(const Endpoint::Ptr& endpoint)
+{
+	return (endpoint->HasSubscription("checker::AssignService"));
 }
 
 vector<Endpoint::Ptr> DelegationComponent::GetCheckerCandidates(const Service& service) const
@@ -94,7 +101,7 @@ vector<Endpoint::Ptr> DelegationComponent::GetCheckerCandidates(const Service& s
 	vector<Endpoint::Ptr> candidates;
 
 	EndpointManager::Iterator it;
-	for (it = GetEndpointManager()->Begin(); it != GetEndpointManager()->End(); it++) {
+	for (it = EndpointManager::GetInstance()->Begin(); it != EndpointManager::GetInstance()->End(); it++) {
 		Endpoint::Ptr endpoint = it->second;
 
 		/* ignore disconnected endpoints */
@@ -102,7 +109,11 @@ vector<Endpoint::Ptr> DelegationComponent::GetCheckerCandidates(const Service& s
 			continue;
 
 		/* ignore endpoints that aren't running the checker component */
-		if (!endpoint->HasSubscription("checker::AssignService"))
+		if (!IsEndpointChecker(endpoint))
+			continue;
+
+		/* ignore endpoints that aren't allowed to check this service */
+		if (!service.IsAllowedChecker(it->first))
 			continue;
 
 		candidates.push_back(endpoint);
@@ -117,6 +128,10 @@ void DelegationComponent::NewEndpointHandler(const Endpoint::Ptr& endpoint)
 }
 void DelegationComponent::SessionEstablishedHandler(const Endpoint::Ptr& endpoint)
 {
+	/* ignore this endpoint if it's not a checker */
+	if (!IsEndpointChecker(endpoint))
+		return;
+
 	stringstream msgbuf;
 	msgbuf << "Clearing assigned services for endpoint '" << endpoint->GetIdentity() << "'";
 	Application::Log(LogInformation, "delegation", msgbuf.str());
@@ -139,7 +154,7 @@ void DelegationComponent::DelegationTimerHandler(void)
 	map<Endpoint::Ptr, int> histogram;
 
 	EndpointManager::Iterator eit;
-	for (eit = GetEndpointManager()->Begin(); eit != GetEndpointManager()->End(); eit++)
+	for (eit = EndpointManager::GetInstance()->Begin(); eit != EndpointManager::GetInstance()->End(); eit++)
 		histogram[eit->second] = 0;
 
 	vector<Service> services;
@@ -155,7 +170,7 @@ void DelegationComponent::DelegationTimerHandler(void)
 		if (checker.empty())
 			continue;
 
-		Endpoint::Ptr endpoint = GetEndpointManager()->GetEndpointByIdentity(checker);
+		Endpoint::Ptr endpoint = EndpointManager::GetInstance()->GetEndpointByIdentity(checker);
 		if (!endpoint)
 			continue;
 
@@ -176,7 +191,7 @@ void DelegationComponent::DelegationTimerHandler(void)
 
 		Endpoint::Ptr oldEndpoint;
 		if (!checker.empty())
-			oldEndpoint = GetEndpointManager()->GetEndpointByIdentity(checker);
+			oldEndpoint = EndpointManager::GetInstance()->GetEndpointByIdentity(checker);
 
 		vector<Endpoint::Ptr> candidates = GetCheckerCandidates(service);
 
@@ -249,7 +264,7 @@ void DelegationComponent::DelegationTimerHandler(void)
 
 		for (sit = services.begin(); sit != services.end(); sit++) {
 			string checker = sit->GetChecker();
-			Endpoint::Ptr endpoint = GetEndpointManager()->GetEndpointByIdentity(checker);
+			Endpoint::Ptr endpoint = EndpointManager::GetInstance()->GetEndpointByIdentity(checker);
 
 			if (!endpoint)
 				continue;
@@ -263,4 +278,29 @@ void DelegationComponent::DelegationTimerHandler(void)
 	Application::Log(LogInformation, "delegation", msgbuf.str());
 }
 
+void DelegationComponent::CheckResultRequestHandler(const Endpoint::Ptr& sender, const RequestMessage& request)
+{
+	MessagePart params;
+	if (!request.GetParams(&params))
+		return;
+
+	string svcname;
+	if (!params.GetProperty("service", &svcname))
+		return;
+
+	Service service = Service::GetByName(svcname);
+
+	/* validate that this is an authentic check result */
+	if (!service.IsAllowedChecker(sender->GetIdentity()))
+		return;
+
+	/* TODO: send state update for dependant services */
+
+	/* send state update */
+	RequestMessage rm;
+	rm.SetMethod("delegation::ServiceStatus");
+	rm.SetParams(params);
+	EndpointManager::GetInstance()->SendMulticastMessage(m_DelegationEndpoint, rm);
+}
+
 EXPORT_COMPONENT(delegation, DelegationComponent);
diff --git a/components/delegation/delegationcomponent.h b/components/delegation/delegationcomponent.h
index 65e573e44..5b998039c 100644
--- a/components/delegation/delegationcomponent.h
+++ b/components/delegation/delegationcomponent.h
@@ -26,7 +26,7 @@ namespace icinga
 /**
  * @ingroup delegation
  */
-class DelegationComponent : public IcingaComponent
+class DelegationComponent : public Component
 {
 public:
 	virtual string GetName(void) const;
@@ -48,6 +48,10 @@ private:
 
 	void AssignService(const Endpoint::Ptr& checker, const Service& service);
 	void ClearServices(const Endpoint::Ptr& checker);
+
+	static bool IsEndpointChecker(const Endpoint::Ptr& endpoint);
+
+	void CheckResultRequestHandler(const Endpoint::Ptr& sender, const RequestMessage& request);
 };
 
 }
diff --git a/components/demo/democomponent.cpp b/components/demo/democomponent.cpp
index 0fc006692..19d6fa93b 100644
--- a/components/demo/democomponent.cpp
+++ b/components/demo/democomponent.cpp
@@ -28,7 +28,7 @@ using namespace icinga;
  */
 string DemoComponent::GetName(void) const
 {
-	return "democomponent";
+	return "demo";
 }
 
 /**
@@ -40,7 +40,7 @@ void DemoComponent::Start(void)
 	m_DemoEndpoint->RegisterTopicHandler("demo::HelloWorld",
 	    boost::bind(&DemoComponent::HelloWorldRequestHandler, this, _2, _3));
 	m_DemoEndpoint->RegisterPublication("demo::HelloWorld");
-	GetEndpointManager()->RegisterEndpoint(m_DemoEndpoint);
+	EndpointManager::GetInstance()->RegisterEndpoint(m_DemoEndpoint);
 
 	m_DemoTimer = boost::make_shared<Timer>();
 	m_DemoTimer->SetInterval(5);
@@ -53,12 +53,10 @@ void DemoComponent::Start(void)
  */
 void DemoComponent::Stop(void)
 {
-	IcingaApplication::Ptr app = GetIcingaApplication();
+	EndpointManager::Ptr endpointManager = EndpointManager::GetInstance();
 
-	if (app) {
-		EndpointManager::Ptr endpointManager = app->GetEndpointManager();
+	if (endpointManager)
 		endpointManager->UnregisterEndpoint(m_DemoEndpoint);
-	}
 }
 
 /**
@@ -73,8 +71,7 @@ void DemoComponent::DemoTimerHandler(void)
 	RequestMessage request;
 	request.SetMethod("demo::HelloWorld");
 
-	EndpointManager::Ptr endpointManager = GetIcingaApplication()->GetEndpointManager();
-	endpointManager->SendMulticastMessage(m_DemoEndpoint, request);
+	EndpointManager::GetInstance()->SendMulticastMessage(m_DemoEndpoint, request);
 }
 
 /**
diff --git a/components/demo/democomponent.h b/components/demo/democomponent.h
index 92176fdc9..623c6c8b4 100644
--- a/components/demo/democomponent.h
+++ b/components/demo/democomponent.h
@@ -26,7 +26,7 @@ namespace icinga
 /**
  * @ingroup demo
  */
-class DemoComponent : public IcingaComponent
+class DemoComponent : public Component
 {
 public:
 	virtual string GetName(void) const;
diff --git a/components/discovery/discoverycomponent.cpp b/components/discovery/discoverycomponent.cpp
index a841233ae..9c67c1bbc 100644
--- a/components/discovery/discoverycomponent.cpp
+++ b/components/discovery/discoverycomponent.cpp
@@ -49,10 +49,10 @@ void DiscoveryComponent::Start(void)
 	m_DiscoveryEndpoint->RegisterTopicHandler("discovery::Welcome",
 		boost::bind(&DiscoveryComponent::WelcomeMessageHandler, this, _2, _3));
 
-	GetEndpointManager()->ForEachEndpoint(boost::bind(&DiscoveryComponent::NewEndpointHandler, this, _2));
-	GetEndpointManager()->OnNewEndpoint.connect(boost::bind(&DiscoveryComponent::NewEndpointHandler, this, _2));
+	EndpointManager::GetInstance()->ForEachEndpoint(boost::bind(&DiscoveryComponent::NewEndpointHandler, this, _2));
+	EndpointManager::GetInstance()->OnNewEndpoint.connect(boost::bind(&DiscoveryComponent::NewEndpointHandler, this, _2));
 
-	GetEndpointManager()->RegisterEndpoint(m_DiscoveryEndpoint);
+	EndpointManager::GetInstance()->RegisterEndpoint(m_DiscoveryEndpoint);
 
 	/* create the reconnect timer */
 	m_DiscoveryTimer = boost::make_shared<Timer>();
@@ -69,7 +69,7 @@ void DiscoveryComponent::Start(void)
  */
 void DiscoveryComponent::Stop(void)
 {
-	EndpointManager::Ptr mgr = GetEndpointManager();
+	EndpointManager::Ptr mgr = EndpointManager::GetInstance();
 
 	if (mgr)
 		mgr->UnregisterEndpoint(m_DiscoveryEndpoint);
@@ -94,7 +94,7 @@ void DiscoveryComponent::CheckExistingEndpoint(const Endpoint::Ptr& self, const
 		Application::Log(LogWarning, "discovery", "Detected duplicate identity:" + other->GetIdentity() + " - Disconnecting old endpoint.");
 
 		other->Stop();
-		GetEndpointManager()->UnregisterEndpoint(other);
+		EndpointManager::GetInstance()->UnregisterEndpoint(other);
 	}
 }
 
@@ -119,16 +119,16 @@ void DiscoveryComponent::NewEndpointHandler(const Endpoint::Ptr& endpoint)
 
 	string identity = endpoint->GetIdentity();
 
-	if (identity == GetEndpointManager()->GetIdentity()) {
+	if (identity == EndpointManager::GetInstance()->GetIdentity()) {
 		Application::Log(LogWarning, "discovery", "Detected loop-back connection - Disconnecting endpoint.");
 
 		endpoint->Stop();
-		GetEndpointManager()->UnregisterEndpoint(endpoint);
+		EndpointManager::GetInstance()->UnregisterEndpoint(endpoint);
 
 		return;
 	}
 
-	GetEndpointManager()->ForEachEndpoint(boost::bind(&DiscoveryComponent::CheckExistingEndpoint, this, endpoint, _2));
+	EndpointManager::GetInstance()->ForEachEndpoint(boost::bind(&DiscoveryComponent::CheckExistingEndpoint, this, endpoint, _2));
 
 	// we assume the other component _always_ wants
 	// discovery::RegisterComponent messages from us
@@ -137,7 +137,7 @@ void DiscoveryComponent::NewEndpointHandler(const Endpoint::Ptr& endpoint)
 	// send a discovery::RegisterComponent message, if the
 	// other component is a broker this makes sure
 	// the broker knows about our message types
-	SendDiscoveryMessage("discovery::RegisterComponent", GetEndpointManager()->GetIdentity(), endpoint);
+	SendDiscoveryMessage("discovery::RegisterComponent", EndpointManager::GetInstance()->GetIdentity(), endpoint);
 
 	map<string, ComponentDiscoveryInfo::Ptr>::iterator ic;
 
@@ -146,7 +146,7 @@ void DiscoveryComponent::NewEndpointHandler(const Endpoint::Ptr& endpoint)
 	endpoint->RegisterSubscription("discovery::NewComponent");
 
 	// send discovery::NewComponent message for ourselves
-	SendDiscoveryMessage("discovery::NewComponent", GetEndpointManager()->GetIdentity(), endpoint);
+	SendDiscoveryMessage("discovery::NewComponent", EndpointManager::GetInstance()->GetIdentity(), endpoint);
 
 	// send discovery::NewComponent messages for all components
 	// we know about
@@ -203,14 +203,14 @@ void DiscoveryComponent::DiscoveryEndpointHandler(const Endpoint::Ptr& endpoint,
  */
 bool DiscoveryComponent::GetComponentDiscoveryInfo(string component, ComponentDiscoveryInfo::Ptr *info) const
 {
-	if (component == GetEndpointManager()->GetIdentity()) {
+	if (component == EndpointManager::GetInstance()->GetIdentity()) {
 		/* Build fake discovery info for ourselves */
 		*info = boost::make_shared<ComponentDiscoveryInfo>();
-		GetEndpointManager()->ForEachEndpoint(boost::bind(&DiscoveryComponent::DiscoveryEndpointHandler, this, _2, *info));
+		EndpointManager::GetInstance()->ForEachEndpoint(boost::bind(&DiscoveryComponent::DiscoveryEndpointHandler, this, _2, *info));
 		
 		(*info)->LastSeen = 0;
-		(*info)->Node = GetIcingaApplication()->GetNode();
-		(*info)->Service = GetIcingaApplication()->GetService();
+		(*info)->Node = IcingaApplication::GetInstance()->GetNode();
+		(*info)->Service = IcingaApplication::GetInstance()->GetService();
 
 		return true;
 	}
@@ -260,7 +260,7 @@ void DiscoveryComponent::FinishDiscoverySetup(const Endpoint::Ptr& endpoint)
 	endpoint->RegisterSubscription("discovery::Welcome");
 	RequestMessage request;
 	request.SetMethod("discovery::Welcome");
-	GetEndpointManager()->SendUnicastMessage(m_DiscoveryEndpoint, endpoint, request);
+	EndpointManager::GetInstance()->SendUnicastMessage(m_DiscoveryEndpoint, endpoint, request);
 
 	endpoint->SetSentWelcome(true);
 
@@ -310,9 +310,9 @@ void DiscoveryComponent::SendDiscoveryMessage(const string& method, const string
 	params.SetPublications(publications);
 
 	if (recipient)
-		GetEndpointManager()->SendUnicastMessage(m_DiscoveryEndpoint, recipient, request);
+		EndpointManager::GetInstance()->SendUnicastMessage(m_DiscoveryEndpoint, recipient, request);
 	else
-		GetEndpointManager()->SendMulticastMessage(m_DiscoveryEndpoint, request);
+		EndpointManager::GetInstance()->SendMulticastMessage(m_DiscoveryEndpoint, request);
 }
 
 bool DiscoveryComponent::HasMessagePermission(const Dictionary::Ptr& roles, const string& messageType, const string& message)
@@ -353,7 +353,7 @@ bool DiscoveryComponent::HasMessagePermission(const Dictionary::Ptr& roles, cons
 void DiscoveryComponent::ProcessDiscoveryMessage(const string& identity, const DiscoveryMessage& message, bool trusted)
 {
 	/* ignore discovery messages that are about ourselves */
-	if (identity == GetEndpointManager()->GetIdentity())
+	if (identity == EndpointManager::GetInstance()->GetIdentity())
 		return;
 
 	ComponentDiscoveryInfo::Ptr info = boost::make_shared<ComponentDiscoveryInfo>();
@@ -379,7 +379,7 @@ void DiscoveryComponent::ProcessDiscoveryMessage(const string& identity, const D
 		}
 	}
 
-	Endpoint::Ptr endpoint = GetEndpointManager()->GetEndpointByIdentity(identity);
+	Endpoint::Ptr endpoint = EndpointManager::GetInstance()->GetEndpointByIdentity(identity);
 
 	MessagePart publications;
 	if (message.GetPublications(&publications)) {
@@ -456,7 +456,7 @@ void DiscoveryComponent::RegisterComponentMessageHandler(const Endpoint::Ptr& se
  */
 void DiscoveryComponent::DiscoveryTimerHandler(void)
 {
-	EndpointManager::Ptr endpointManager = GetEndpointManager();
+	EndpointManager::Ptr endpointManager = EndpointManager::GetInstance();
 	
 	time_t now;
 	time(&now);
@@ -487,7 +487,7 @@ void DiscoveryComponent::DiscoveryTimerHandler(void)
 		i++;
 
 		/* there's no need to reconnect to ourself */
-		if (identity == GetEndpointManager()->GetIdentity())
+		if (identity == EndpointManager::GetInstance()->GetIdentity())
 			continue;
 
 		/* for explicitly-configured upstream endpoints
diff --git a/components/discovery/discoverycomponent.h b/components/discovery/discoverycomponent.h
index 3c9bc5fad..ed57447bf 100644
--- a/components/discovery/discoverycomponent.h
+++ b/components/discovery/discoverycomponent.h
@@ -44,7 +44,7 @@ public:
 /**
  * @ingroup discovery
  */
-class DiscoveryComponent : public IcingaComponent
+class DiscoveryComponent : public Component
 {
 public:
 	virtual string GetName(void) const;
diff --git a/configure.ac b/configure.ac
index 0da80ac31..172b88dc7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -68,6 +68,7 @@ Makefile
 base/Makefile
 components/Makefile
 components/checker/Makefile
+components/compat/Makefile
 components/configfile/Makefile
 components/configrpc/Makefile
 components/delegation/Makefile
diff --git a/dyn/config_lexer.cc b/dyn/config_lexer.cc
index f1fc33e99..94a4330cf 100644
--- a/dyn/config_lexer.cc
+++ b/dyn/config_lexer.cc
@@ -370,8 +370,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
 	*yy_cp = '\0'; \
 	yyg->yy_c_buf_p = yy_cp;
 
-#define YY_NUM_RULES 23
-#define YY_END_OF_BUFFER 24
+#define YY_NUM_RULES 24
+#define YY_END_OF_BUFFER 25
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -379,16 +379,16 @@ struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_accept[72] =
+static yyconst flex_int16_t yy_accept[81] =
     {   0,
-        0,    0,    0,    0,   24,   22,   21,   21,   22,   22,
-       22,   22,   22,   22,    9,   10,    7,    7,    7,    7,
-        7,    7,   17,   18,   21,    0,   20,   13,   11,   12,
-       15,    0,   14,    9,    7,    7,    7,    7,    7,    7,
-       17,   16,    8,   19,    7,    7,    7,    7,    7,    7,
-        7,    7,    7,    7,    6,    7,    7,    7,    7,    2,
-        7,    7,    7,    7,    3,    7,    4,    7,    1,    5,
-        0
+        0,    0,    0,    0,   25,   23,   22,   22,   23,   23,
+       23,   23,   23,   23,   10,   11,    8,    8,    8,    8,
+        8,    8,    8,   18,   19,   22,    0,   21,   14,   12,
+       13,   16,    0,   15,   10,    8,    8,    8,    8,    8,
+        8,    8,   18,   17,    9,   20,    8,    8,    8,    8,
+        8,    8,    8,    8,    8,    8,    8,    7,    8,    8,
+        8,    8,    8,    2,    8,    8,    8,    8,    8,    4,
+        8,    8,    5,    8,    8,    1,    6,    8,    3,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -404,9 +404,9 @@ static yyconst flex_int32_t yy_ec[256] =
        12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
         1,    1,    1,    1,   12,    1,   13,   14,   15,   16,
 
-       17,   12,   12,   18,   19,   20,   12,   21,   12,   22,
-       23,   12,   12,   24,   25,   26,   27,   12,   12,   12,
-       12,   12,    1,    1,    1,    1,    1,    1,    1,    1,
+       17,   12,   12,   18,   19,   20,   12,   21,   22,   23,
+       24,   25,   12,   26,   27,   28,   29,   12,   12,   12,
+       30,   12,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -423,78 +423,84 @@ static yyconst flex_int32_t yy_ec[256] =
         1,    1,    1,    1,    1
     } ;
 
-static yyconst flex_int32_t yy_meta[28] =
+static yyconst flex_int32_t yy_meta[31] =
     {   0,
         1,    1,    2,    3,    1,    4,    1,    5,    1,    5,
         1,    5,    5,    5,    5,    5,    5,    5,    5,    5,
-        5,    5,    5,    5,    5,    5,    5
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5
     } ;
 
-static yyconst flex_int16_t yy_base[78] =
+static yyconst flex_int16_t yy_base[87] =
     {   0,
-        0,    0,   93,   92,   97,  100,   26,   28,    0,    0,
-       85,   84,   83,   26,   83,  100,    0,   78,   69,   67,
-       62,   74,    0,   78,   31,   82,    0,  100,  100,  100,
-      100,    0,  100,   75,    0,   59,   21,   68,   61,   61,
-        0,  100,  100,    0,   54,   58,   61,   64,   55,   58,
-       50,   46,   48,   50,    0,   55,   56,   52,   48,    0,
-       40,   50,   44,   32,    0,   25,    0,   22,    0,    0,
-      100,   39,   44,   49,   33,   54,   59
+        0,    0,  104,  103,  108,  111,   29,   31,    0,    0,
+       96,   95,   94,   29,   94,  111,    0,   89,   79,   77,
+       71,   85,   81,    0,   88,   34,   92,    0,  111,  111,
+      111,  111,    0,  111,   85,    0,   67,   24,   78,   71,
+       71,   68,    0,  111,  111,    0,   61,   67,   70,   73,
+       64,   67,   58,   56,   52,   54,   58,    0,   63,   53,
+       63,   59,   55,    0,   45,   46,   56,   53,   41,    0,
+       55,   36,    0,   34,   28,    0,    0,   20,    0,  111,
+       42,   47,   52,   36,   57,   62
     } ;
 
-static yyconst flex_int16_t yy_def[78] =
+static yyconst flex_int16_t yy_def[87] =
     {   0,
-       71,    1,   72,   72,   71,   71,   71,   71,   73,   74,
-       71,   71,   71,   71,   71,   71,   75,   75,   75,   75,
-       75,   75,   76,   71,   71,   73,   74,   71,   71,   71,
-       71,   77,   71,   71,   75,   75,   75,   75,   75,   75,
-       76,   71,   71,   77,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-        0,   71,   71,   71,   71,   71,   71
+       80,    1,   81,   81,   80,   80,   80,   80,   82,   83,
+       80,   80,   80,   80,   80,   80,   84,   84,   84,   84,
+       84,   84,   84,   85,   80,   80,   82,   83,   80,   80,
+       80,   80,   86,   80,   80,   84,   84,   84,   84,   84,
+       84,   84,   85,   80,   80,   86,   84,   84,   84,   84,
+       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
+       84,   84,   84,   84,   84,   84,   84,   84,   84,   84,
+       84,   84,   84,   84,   84,   84,   84,   84,   84,    0,
+       80,   80,   80,   80,   80,   80
     } ;
 
-static yyconst flex_int16_t yy_nxt[128] =
+static yyconst flex_int16_t yy_nxt[142] =
     {   0,
         6,    7,    8,    9,   10,   11,   12,   13,   14,   15,
        16,   17,   18,   17,   17,   17,   17,   17,   19,   17,
-       20,   21,   22,   17,   17,   17,   17,   25,   25,   25,
-       25,   31,   25,   25,   32,   46,   33,   35,   47,   23,
-       23,   23,   23,   23,   26,   26,   70,   26,   26,   27,
-       69,   27,   27,   27,   41,   41,   41,   68,   41,   44,
-       67,   44,   44,   44,   66,   65,   64,   63,   62,   61,
-       60,   59,   58,   57,   56,   55,   54,   53,   52,   51,
-       50,   49,   48,   45,   34,   43,   42,   40,   39,   38,
-       37,   36,   34,   30,   29,   28,   71,   24,   24,    5,
+       20,   17,   21,   22,   17,   17,   17,   23,   17,   17,
+       26,   26,   26,   26,   32,   26,   26,   33,   48,   34,
+       36,   49,   24,   24,   24,   24,   24,   27,   27,   79,
+       27,   27,   28,   78,   28,   28,   28,   43,   43,   43,
+       77,   43,   46,   76,   46,   46,   46,   75,   74,   73,
+       72,   71,   70,   69,   68,   67,   66,   65,   64,   63,
+       62,   61,   60,   59,   58,   57,   56,   55,   54,   53,
+       52,   51,   50,   47,   35,   45,   44,   42,   41,   40,
 
-       71,   71,   71,   71,   71,   71,   71,   71,   71,   71,
-       71,   71,   71,   71,   71,   71,   71,   71,   71,   71,
-       71,   71,   71,   71,   71,   71,   71
+       39,   38,   37,   35,   31,   30,   29,   80,   25,   25,
+        5,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80
     } ;
 
-static yyconst flex_int16_t yy_chk[128] =
+static yyconst flex_int16_t yy_chk[142] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    7,    7,    8,
-        8,   14,   25,   25,   14,   37,   14,   75,   37,   72,
-       72,   72,   72,   72,   73,   73,   68,   73,   73,   74,
-       66,   74,   74,   74,   76,   76,   76,   64,   76,   77,
-       63,   77,   77,   77,   62,   61,   59,   58,   57,   56,
-       54,   53,   52,   51,   50,   49,   48,   47,   46,   45,
-       40,   39,   38,   36,   34,   26,   24,   22,   21,   20,
-       19,   18,   15,   13,   12,   11,    5,    4,    3,   71,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        7,    7,    8,    8,   14,   26,   26,   14,   38,   14,
+       84,   38,   81,   81,   81,   81,   81,   82,   82,   78,
+       82,   82,   83,   75,   83,   83,   83,   85,   85,   85,
+       74,   85,   86,   72,   86,   86,   86,   71,   69,   68,
+       67,   66,   65,   63,   62,   61,   60,   59,   57,   56,
+       55,   54,   53,   52,   51,   50,   49,   48,   47,   42,
+       41,   40,   39,   37,   35,   27,   25,   23,   22,   21,
 
-       71,   71,   71,   71,   71,   71,   71,   71,   71,   71,
-       71,   71,   71,   71,   71,   71,   71,   71,   71,   71,
-       71,   71,   71,   71,   71,   71,   71
+       20,   19,   18,   15,   13,   12,   11,    5,    4,    3,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80,   80,   80,
+       80
     } ;
 
 /* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[24] =
+static yyconst flex_int32_t yy_rule_can_match_eol[25] =
     {   0,
-0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 
-    0, 1, 0, 0,     };
+0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 
+    0, 0, 1, 0, 0,     };
 
 /* The intent behind this definition is that it'll catch
  * any uses of REJECT which flex missed.
@@ -545,7 +551,7 @@ do {							\
 } while (0)
 #define YY_NO_UNISTD_H 1
 
-#line 549 "config_lexer.cc"
+#line 555 "config_lexer.cc"
 
 #define INITIAL 0
 #define IN_C_COMMENT 1
@@ -794,7 +800,7 @@ YY_DECL
 
 #line 48 "config_lexer.ll"
 
-#line 798 "config_lexer.cc"
+#line 804 "config_lexer.cc"
 
     yylval = yylval_param;
 
@@ -851,13 +857,13 @@ yy_match:
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 72 )
+				if ( yy_current_state >= 81 )
 					yy_c = yy_meta[(unsigned int) yy_c];
 				}
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 			++yy_cp;
 			}
-		while ( yy_current_state != 71 );
+		while ( yy_current_state != 80 );
 		yy_cp = yyg->yy_last_accepting_cpos;
 		yy_current_state = yyg->yy_last_accepting_state;
 
@@ -902,116 +908,121 @@ return T_LOCAL;
 case 3:
 YY_RULE_SETUP
 #line 51 "config_lexer.ll"
-return T_OBJECT;
+return T_TEMPORARY;
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
 #line 52 "config_lexer.ll"
-return T_INCLUDE;
+return T_OBJECT;
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
 #line 53 "config_lexer.ll"
-return T_INHERITS;
+return T_INCLUDE;
 	YY_BREAK
 case 6:
 YY_RULE_SETUP
 #line 54 "config_lexer.ll"
-return T_NULL;
+return T_INHERITS;
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
 #line 55 "config_lexer.ll"
-{ yylval->text = strdup(yytext); return T_IDENTIFIER; }
+return T_NULL;
 	YY_BREAK
 case 8:
-/* rule 8 can match eol */
 YY_RULE_SETUP
 #line 56 "config_lexer.ll"
-{ yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING; }
+{ yylval->text = strdup(yytext); return T_IDENTIFIER; }
 	YY_BREAK
 case 9:
+/* rule 9 can match eol */
 YY_RULE_SETUP
 #line 57 "config_lexer.ll"
-{ yylval->num = atoi(yytext); return T_NUMBER; }
+{ yytext[yyleng-1] = '\0'; yylval->text = strdup(yytext + 1); return T_STRING; }
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
 #line 58 "config_lexer.ll"
-{ yylval->op = OperatorSet; return T_EQUAL; }
+{ yylval->num = atoi(yytext); return T_NUMBER; }
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
 #line 59 "config_lexer.ll"
-{ yylval->op = OperatorPlus; return T_PLUS_EQUAL; }
+{ yylval->op = OperatorSet; return T_EQUAL; }
 	YY_BREAK
 case 12:
 YY_RULE_SETUP
 #line 60 "config_lexer.ll"
-{ yylval->op = OperatorMinus; return T_MINUS_EQUAL; }
+{ yylval->op = OperatorPlus; return T_PLUS_EQUAL; }
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
 #line 61 "config_lexer.ll"
-{ yylval->op = OperatorMultiply; return T_MULTIPLY_EQUAL; }
+{ yylval->op = OperatorMinus; return T_MINUS_EQUAL; }
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
 #line 62 "config_lexer.ll"
+{ yylval->op = OperatorMultiply; return T_MULTIPLY_EQUAL; }
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 63 "config_lexer.ll"
 { yylval->op = OperatorDivide; return T_DIVIDE_EQUAL; }
 	YY_BREAK
 
-case 15:
+case 16:
 YY_RULE_SETUP
-#line 65 "config_lexer.ll"
+#line 66 "config_lexer.ll"
 BEGIN(IN_C_COMMENT);
 	YY_BREAK
 
 
-case 16:
-YY_RULE_SETUP
-#line 69 "config_lexer.ll"
-BEGIN(INITIAL);
-	YY_BREAK
 case 17:
-/* rule 17 can match eol */
 YY_RULE_SETUP
 #line 70 "config_lexer.ll"
-/* ignore comment */
+BEGIN(INITIAL);
 	YY_BREAK
 case 18:
+/* rule 18 can match eol */
 YY_RULE_SETUP
 #line 71 "config_lexer.ll"
+/* ignore comment */
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 72 "config_lexer.ll"
 /* ignore star */
 	YY_BREAK
 
-case 19:
-YY_RULE_SETUP
-#line 74 "config_lexer.ll"
-/* ignore C++-style comments */
-	YY_BREAK
 case 20:
 YY_RULE_SETUP
 #line 75 "config_lexer.ll"
-/* ignore shell-style comments */
+/* ignore C++-style comments */
 	YY_BREAK
 case 21:
-/* rule 21 can match eol */
 YY_RULE_SETUP
 #line 76 "config_lexer.ll"
-/* ignore whitespace */
+/* ignore shell-style comments */
 	YY_BREAK
 case 22:
+/* rule 22 can match eol */
 YY_RULE_SETUP
-#line 78 "config_lexer.ll"
-return yytext[0];
+#line 77 "config_lexer.ll"
+/* ignore whitespace */
 	YY_BREAK
 case 23:
 YY_RULE_SETUP
 #line 79 "config_lexer.ll"
+return yytext[0];
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 80 "config_lexer.ll"
 ECHO;
 	YY_BREAK
-#line 1015 "config_lexer.cc"
+#line 1026 "config_lexer.cc"
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(IN_C_COMMENT):
 	yyterminate();
@@ -1307,7 +1318,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 72 )
+			if ( yy_current_state >= 81 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1336,11 +1347,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 72 )
+		if ( yy_current_state >= 81 )
 			yy_c = yy_meta[(unsigned int) yy_c];
 		}
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 71);
+	yy_is_jam = (yy_current_state == 80);
 
 	return yy_is_jam ? 0 : yy_current_state;
 }
@@ -2199,7 +2210,7 @@ void yyfree (void * ptr , yyscan_t yyscanner)
 
 #define YYTABLES_NAME "yytables"
 
-#line 79 "config_lexer.ll"
+#line 80 "config_lexer.ll"
 
 
 
diff --git a/dyn/config_lexer.ll b/dyn/config_lexer.ll
index 56166a04e..19c80884d 100644
--- a/dyn/config_lexer.ll
+++ b/dyn/config_lexer.ll
@@ -48,6 +48,7 @@ do {							\
 %%
 abstract			return T_ABSTRACT;
 local				return T_LOCAL;
+temporary			return T_TEMPORARY;
 object				return T_OBJECT;
 include				return T_INCLUDE;
 inherits			return T_INHERITS;
diff --git a/dyn/config_parser.cc b/dyn/config_parser.cc
index f2bfca17a..52e1aba54 100644
--- a/dyn/config_parser.cc
+++ b/dyn/config_parser.cc
@@ -139,10 +139,11 @@ using namespace icinga;
      T_MULTIPLY_EQUAL = 265,
      T_DIVIDE_EQUAL = 266,
      T_ABSTRACT = 267,
-     T_LOCAL = 268,
-     T_OBJECT = 269,
-     T_INCLUDE = 270,
-     T_INHERITS = 271
+     T_TEMPORARY = 268,
+     T_LOCAL = 269,
+     T_OBJECT = 270,
+     T_INCLUDE = 271,
+     T_INHERITS = 272
    };
 #endif
 /* Tokens.  */
@@ -156,10 +157,11 @@ using namespace icinga;
 #define T_MULTIPLY_EQUAL 265
 #define T_DIVIDE_EQUAL 266
 #define T_ABSTRACT 267
-#define T_LOCAL 268
-#define T_OBJECT 269
-#define T_INCLUDE 270
-#define T_INHERITS 271
+#define T_TEMPORARY 268
+#define T_LOCAL 269
+#define T_OBJECT 270
+#define T_INCLUDE 271
+#define T_INHERITS 272
 
 
 
@@ -179,7 +181,7 @@ typedef union YYSTYPE
 
 
 /* Line 293 of yacc.c  */
-#line 183 "config_parser.cc"
+#line 185 "config_parser.cc"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -203,7 +205,7 @@ typedef struct YYLTYPE
 /* Copy the second part of user declarations.  */
 
 /* Line 343 of yacc.c  */
-#line 66 "config_parser.yy"
+#line 67 "config_parser.yy"
 
 
 int yylex(YYSTYPE *lvalp, YYLTYPE *llocp, void *scanner);
@@ -226,6 +228,7 @@ static stack<ExpressionList::Ptr> m_ExpressionLists;
 static vector<ConfigItem::Ptr> m_Objects;
 static ConfigItem::Ptr m_Object;
 static bool m_Abstract;
+static bool m_Temporary;
 static bool m_Local;
 static Dictionary::Ptr m_Array;
 
@@ -242,7 +245,7 @@ void ConfigCompiler::Compile(void)
 
 
 /* Line 343 of yacc.c  */
-#line 246 "config_parser.cc"
+#line 249 "config_parser.cc"
 
 #ifdef short
 # undef short
@@ -466,17 +469,17 @@ union yyalloc
 #define YYLAST   47
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  28
+#define YYNTOKENS  29
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  23
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  43
+#define YYNRULES  44
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  60
+#define YYNSTATES  61
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   271
+#define YYMAXUTOK   272
 
 #define YYTRANSLATE(YYX)						\
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -488,15 +491,15 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-      26,    27,    19,    17,    21,    18,     2,    20,     2,     2,
+      27,    28,    20,    18,    22,    19,     2,    21,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    24,     2,    25,     2,     2,     2,     2,     2,     2,
+       2,    25,     2,    26,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,    22,     2,    23,     2,     2,     2,     2,
+       2,     2,     2,    23,     2,    24,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -511,7 +514,7 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16
+      15,    16,    17
 };
 
 #if YYDEBUG
@@ -520,36 +523,36 @@ static const yytype_uint8 yytranslate[] =
 static const yytype_uint8 yyprhs[] =
 {
        0,     0,     3,     4,     7,     9,    11,    14,    15,    16,
-      25,    26,    29,    31,    33,    35,    39,    41,    42,    45,
-      46,    51,    52,    54,    58,    62,    69,    71,    73,    75,
-      77,    79,    81,    83,    85,    87,    89,    91,    93,    94,
-      99,   101,   102,   104
+      25,    26,    29,    31,    33,    35,    37,    41,    43,    44,
+      47,    48,    53,    54,    56,    60,    64,    71,    73,    75,
+      77,    79,    81,    83,    85,    87,    89,    91,    93,    95,
+      96,   101,   103,   104,   106
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      29,     0,    -1,    -1,    29,    30,    -1,    32,    -1,    31,
-      -1,    15,     3,    -1,    -1,    -1,    33,    35,    14,     6,
-       3,    34,    39,    40,    -1,    -1,    35,    36,    -1,    12,
-      -1,    13,    -1,    38,    -1,    37,    21,    38,    -1,     3,
-      -1,    -1,    16,    37,    -1,    -1,    22,    41,    42,    23,
-      -1,    -1,    43,    -1,    43,    21,    42,    -1,     6,    44,
-      46,    -1,     6,    24,     3,    25,    44,    46,    -1,     3,
-      -1,     7,    -1,     8,    -1,     9,    -1,    10,    -1,    11,
-      -1,     3,    -1,     4,    -1,     5,    -1,    45,    -1,    47,
-      -1,    40,    -1,    -1,    26,    48,    50,    27,    -1,    45,
-      -1,    -1,    49,    -1,    49,    21,    50,    -1
+      30,     0,    -1,    -1,    30,    31,    -1,    33,    -1,    32,
+      -1,    16,     3,    -1,    -1,    -1,    34,    36,    15,     6,
+       3,    35,    40,    41,    -1,    -1,    36,    37,    -1,    12,
+      -1,    13,    -1,    14,    -1,    39,    -1,    38,    22,    39,
+      -1,     3,    -1,    -1,    17,    38,    -1,    -1,    23,    42,
+      43,    24,    -1,    -1,    44,    -1,    44,    22,    43,    -1,
+       6,    45,    47,    -1,     6,    25,     3,    26,    45,    47,
+      -1,     3,    -1,     7,    -1,     8,    -1,     9,    -1,    10,
+      -1,    11,    -1,     3,    -1,     4,    -1,     5,    -1,    46,
+      -1,    48,    -1,    41,    -1,    -1,    27,    49,    51,    28,
+      -1,    46,    -1,    -1,    50,    -1,    50,    22,    51,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   104,   104,   105,   108,   108,   111,   115,   120,   115,
-     150,   151,   154,   158,   164,   165,   168,   175,   176,   180,
-     179,   191,   192,   193,   196,   204,   218,   227,   228,   229,
-     230,   231,   237,   242,   246,   252,   253,   254,   261,   260,
-     272,   278,   280,   281
+       0,   106,   106,   107,   110,   110,   113,   117,   122,   117,
+     155,   156,   159,   163,   167,   173,   174,   177,   184,   185,
+     189,   188,   200,   201,   202,   205,   213,   227,   236,   237,
+     238,   239,   240,   246,   251,   255,   261,   262,   263,   270,
+     269,   281,   287,   289,   290
 };
 #endif
 
@@ -560,13 +563,14 @@ static const char *const yytname[] =
 {
   "$end", "error", "$undefined", "T_STRING", "T_NUMBER", "T_NULL",
   "T_IDENTIFIER", "T_EQUAL", "T_PLUS_EQUAL", "T_MINUS_EQUAL",
-  "T_MULTIPLY_EQUAL", "T_DIVIDE_EQUAL", "T_ABSTRACT", "T_LOCAL",
-  "T_OBJECT", "T_INCLUDE", "T_INHERITS", "'+'", "'-'", "'*'", "'/'", "','",
-  "'{'", "'}'", "'['", "']'", "'('", "')'", "$accept", "statements",
-  "statement", "include", "object", "$@1", "$@2", "attributes",
-  "attribute", "inherits_list", "inherits_item", "inherits_specifier",
-  "expressionlist", "$@3", "expressions", "expression", "operator",
-  "simplevalue", "value", "tuple", "$@4", "tupleitem", "tupleitems", 0
+  "T_MULTIPLY_EQUAL", "T_DIVIDE_EQUAL", "T_ABSTRACT", "T_TEMPORARY",
+  "T_LOCAL", "T_OBJECT", "T_INCLUDE", "T_INHERITS", "'+'", "'-'", "'*'",
+  "'/'", "','", "'{'", "'}'", "'['", "']'", "'('", "')'", "$accept",
+  "statements", "statement", "include", "object", "$@1", "$@2",
+  "attributes", "attribute", "inherits_list", "inherits_item",
+  "inherits_specifier", "expressionlist", "$@3", "expressions",
+  "expression", "operator", "simplevalue", "value", "tuple", "$@4",
+  "tupleitem", "tupleitems", 0
 };
 #endif
 
@@ -576,29 +580,29 @@ static const char *const yytname[] =
 static const yytype_uint16 yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
-     265,   266,   267,   268,   269,   270,   271,    43,    45,    42,
-      47,    44,   123,   125,    91,    93,    40,    41
+     265,   266,   267,   268,   269,   270,   271,   272,    43,    45,
+      42,    47,    44,   123,   125,    91,    93,    40,    41
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    28,    29,    29,    30,    30,    31,    33,    34,    32,
-      35,    35,    36,    36,    37,    37,    38,    39,    39,    41,
-      40,    42,    42,    42,    43,    43,    43,    44,    44,    44,
-      44,    44,    45,    45,    45,    46,    46,    46,    48,    47,
-      49,    50,    50,    50
+       0,    29,    30,    30,    31,    31,    32,    34,    35,    33,
+      36,    36,    37,    37,    37,    38,    38,    39,    40,    40,
+      42,    41,    43,    43,    43,    44,    44,    44,    45,    45,
+      45,    45,    45,    46,    46,    46,    47,    47,    47,    49,
+      48,    50,    51,    51,    51
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
        0,     2,     0,     2,     1,     1,     2,     0,     0,     8,
-       0,     2,     1,     1,     1,     3,     1,     0,     2,     0,
-       4,     0,     1,     3,     3,     6,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     1,     0,     4,
-       1,     0,     1,     3
+       0,     2,     1,     1,     1,     1,     3,     1,     0,     2,
+       0,     4,     0,     1,     3,     3,     6,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     0,
+       4,     1,     0,     1,     3
 };
 
 /* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
@@ -607,40 +611,42 @@ static const yytype_uint8 yyr2[] =
 static const yytype_uint8 yydefact[] =
 {
        2,     7,     1,     0,     3,     5,     4,    10,     6,     0,
-      12,    13,     0,    11,     0,     8,    17,     0,     0,    16,
-      18,    14,    19,     9,     0,    21,    15,    26,     0,     0,
-      22,    27,    28,    29,    30,    31,     0,     0,    20,    21,
-       0,    32,    33,    34,    38,    37,    35,    24,    36,    23,
-       0,    41,     0,    40,    42,     0,    25,    41,    39,    43
+      12,    13,    14,     0,    11,     0,     8,    18,     0,     0,
+      17,    19,    15,    20,     9,     0,    22,    16,    27,     0,
+       0,    23,    28,    29,    30,    31,    32,     0,     0,    21,
+      22,     0,    33,    34,    35,    39,    38,    36,    25,    37,
+      24,     0,    42,     0,    41,    43,     0,    26,    42,    40,
+      44
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
-      -1,     1,     4,     5,     6,     7,    16,     9,    13,    20,
-      21,    18,    45,    25,    29,    30,    37,    46,    47,    48,
-      51,    54,    55
+      -1,     1,     4,     5,     6,     7,    17,     9,    14,    21,
+      22,    19,    46,    26,    30,    31,    38,    47,    48,    49,
+      52,    55,    56
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -44
+#define YYPACT_NINF -45
 static const yytype_int8 yypact[] =
 {
-     -44,     9,   -44,     8,   -44,   -44,   -44,   -44,   -44,     3,
-     -44,   -44,     6,   -44,    15,   -44,     5,    19,    11,   -44,
-      13,   -44,   -44,   -44,    19,     7,   -44,   -44,    -4,    12,
-      16,   -44,   -44,   -44,   -44,   -44,    33,    -3,   -44,     7,
-      14,   -44,   -44,   -44,   -44,   -44,   -44,   -44,   -44,   -44,
-      18,    27,    -3,   -44,    17,    20,   -44,    27,   -44,   -44
+     -45,     9,   -45,    19,   -45,   -45,   -45,   -45,   -45,    -2,
+     -45,   -45,   -45,    25,   -45,    27,   -45,    15,    30,    11,
+     -45,    13,   -45,   -45,   -45,    30,    20,   -45,   -45,    -4,
+      12,    16,   -45,   -45,   -45,   -45,   -45,    34,    -3,   -45,
+      20,    14,   -45,   -45,   -45,   -45,   -45,   -45,   -45,   -45,
+     -45,     8,    24,    -3,   -45,    17,    18,   -45,    24,   -45,
+     -45
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -44,   -44,   -44,   -44,   -44,   -44,   -44,   -44,   -44,   -44,
-      21,   -44,    22,   -44,     2,   -44,    -8,   -43,    -9,   -44,
-     -44,   -44,   -13
+     -45,   -45,   -45,   -45,   -45,   -45,   -45,   -45,   -45,   -45,
+      22,   -45,    23,   -45,     1,   -45,    -8,   -44,    -9,   -45,
+     -45,   -45,   -13
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -649,38 +655,39 @@ static const yytype_int8 yypgoto[] =
 #define YYTABLE_NINF -1
 static const yytype_uint8 yytable[] =
 {
-      41,    42,    43,    31,    32,    33,    34,    35,    53,     2,
-      27,     8,    14,    28,    53,    10,    11,    12,    15,    22,
-      36,    17,    19,    44,     3,    31,    32,    33,    34,    35,
-      41,    42,    43,    22,    24,    38,    40,    39,    57,    50,
-      23,    49,    52,    56,    59,    26,     0,    58
+      42,    43,    44,    32,    33,    34,    35,    36,    54,     2,
+      10,    11,    12,    13,    54,    32,    33,    34,    35,    36,
+      23,    37,     8,    28,    45,     3,    29,    42,    43,    44,
+      16,    15,    18,    20,    23,    25,    39,    41,    40,    58,
+      51,    50,    24,    53,    57,    60,    59,    27
 };
 
 #define yypact_value_is_default(yystate) \
-  ((yystate) == (-44))
+  ((yystate) == (-45))
 
 #define yytable_value_is_error(yytable_value) \
   YYID (0)
 
-static const yytype_int8 yycheck[] =
+static const yytype_uint8 yycheck[] =
 {
-       3,     4,     5,     7,     8,     9,    10,    11,    51,     0,
-       3,     3,     6,     6,    57,    12,    13,    14,     3,    22,
-      24,    16,     3,    26,    15,     7,     8,     9,    10,    11,
-       3,     4,     5,    22,    21,    23,     3,    21,    21,    25,
-      18,    39,    50,    52,    57,    24,    -1,    27
+       3,     4,     5,     7,     8,     9,    10,    11,    52,     0,
+      12,    13,    14,    15,    58,     7,     8,     9,    10,    11,
+      23,    25,     3,     3,    27,    16,     6,     3,     4,     5,
+       3,     6,    17,     3,    23,    22,    24,     3,    22,    22,
+      26,    40,    19,    51,    53,    58,    28,    25
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,    29,     0,    15,    30,    31,    32,    33,     3,    35,
-      12,    13,    14,    36,     6,     3,    34,    16,    39,     3,
-      37,    38,    22,    40,    21,    41,    38,     3,     6,    42,
-      43,     7,     8,     9,    10,    11,    24,    44,    23,    21,
-       3,     3,     4,     5,    26,    40,    45,    46,    47,    42,
-      25,    48,    44,    45,    49,    50,    46,    21,    27,    50
+       0,    30,     0,    16,    31,    32,    33,    34,     3,    36,
+      12,    13,    14,    15,    37,     6,     3,    35,    17,    40,
+       3,    38,    39,    23,    41,    22,    42,    39,     3,     6,
+      43,    44,     7,     8,     9,    10,    11,    25,    45,    24,
+      22,     3,     3,     4,     5,    27,    41,    46,    47,    48,
+      43,    26,    49,    45,    46,    50,    51,    47,    22,    28,
+      51
 };
 
 #define yyerrok		(yyerrstatus = 0)
@@ -1566,7 +1573,7 @@ yyreduce:
         case 7:
 
 /* Line 1806 of yacc.c  */
-#line 115 "config_parser.yy"
+#line 117 "config_parser.yy"
     {
 		m_Abstract = false;
 		m_Local = false;
@@ -1576,7 +1583,7 @@ yyreduce:
   case 8:
 
 /* Line 1806 of yacc.c  */
-#line 120 "config_parser.yy"
+#line 122 "config_parser.yy"
     {
 		m_Object = boost::make_shared<ConfigItem>((yyvsp[(4) - (5)].text), (yyvsp[(5) - (5)].text), yylloc);
 		free((yyvsp[(4) - (5)].text));
@@ -1587,7 +1594,7 @@ yyreduce:
   case 9:
 
 /* Line 1806 of yacc.c  */
-#line 126 "config_parser.yy"
+#line 128 "config_parser.yy"
     {
 		Object::Ptr exprl_object = *(yyvsp[(8) - (8)].variant);
 		delete (yyvsp[(8) - (8)].variant);
@@ -1602,6 +1609,9 @@ yyreduce:
 		Expression abstractexpr("__abstract", OperatorSet, m_Abstract ? 1 : 0, yylloc);
 		exprl->AddExpression(abstractexpr);
 
+		Expression tempexpr("__temporary", OperatorSet, m_Temporary ? 1 : 0, yylloc);
+		exprl->AddExpression(tempexpr);
+
 		Expression localexpr("__local", OperatorSet, m_Local ? 1 : 0, yylloc);
 		exprl->AddExpression(localexpr);
 
@@ -1615,7 +1625,7 @@ yyreduce:
   case 12:
 
 /* Line 1806 of yacc.c  */
-#line 155 "config_parser.yy"
+#line 160 "config_parser.yy"
     {
 		m_Abstract = true;
 	}
@@ -1624,45 +1634,54 @@ yyreduce:
   case 13:
 
 /* Line 1806 of yacc.c  */
-#line 159 "config_parser.yy"
+#line 164 "config_parser.yy"
+    {
+		m_Temporary = true;
+	}
+    break;
+
+  case 14:
+
+/* Line 1806 of yacc.c  */
+#line 168 "config_parser.yy"
     {
 		m_Local = true;
 	}
     break;
 
-  case 16:
+  case 17:
 
 /* Line 1806 of yacc.c  */
-#line 169 "config_parser.yy"
+#line 178 "config_parser.yy"
     {
 		m_Object->AddParent((yyvsp[(1) - (1)].text));
 		free((yyvsp[(1) - (1)].text));
 	}
     break;
 
-  case 19:
+  case 20:
 
 /* Line 1806 of yacc.c  */
-#line 180 "config_parser.yy"
+#line 189 "config_parser.yy"
     {
 		m_ExpressionLists.push(boost::make_shared<ExpressionList>());
 	}
     break;
 
-  case 20:
+  case 21:
 
 /* Line 1806 of yacc.c  */
-#line 185 "config_parser.yy"
+#line 194 "config_parser.yy"
     {
 		(yyval.variant) = new Variant(m_ExpressionLists.top());
 		m_ExpressionLists.pop();
 	}
     break;
 
-  case 24:
+  case 25:
 
 /* Line 1806 of yacc.c  */
-#line 197 "config_parser.yy"
+#line 206 "config_parser.yy"
     {
 		Expression expr((yyvsp[(1) - (3)].text), (yyvsp[(2) - (3)].op), *(yyvsp[(3) - (3)].variant), yylloc);
 		free((yyvsp[(1) - (3)].text));
@@ -1672,10 +1691,10 @@ yyreduce:
 	}
     break;
 
-  case 25:
+  case 26:
 
 /* Line 1806 of yacc.c  */
-#line 205 "config_parser.yy"
+#line 214 "config_parser.yy"
     {
 		Expression subexpr((yyvsp[(3) - (6)].text), (yyvsp[(5) - (6)].op), *(yyvsp[(6) - (6)].variant), yylloc);
 		free((yyvsp[(3) - (6)].text));
@@ -1691,10 +1710,10 @@ yyreduce:
 	}
     break;
 
-  case 26:
+  case 27:
 
 /* Line 1806 of yacc.c  */
-#line 219 "config_parser.yy"
+#line 228 "config_parser.yy"
     {
 		Expression expr((yyvsp[(1) - (1)].text), OperatorSet, (yyvsp[(1) - (1)].text), yylloc);
 		free((yyvsp[(1) - (1)].text));
@@ -1703,75 +1722,75 @@ yyreduce:
 	}
     break;
 
-  case 31:
-
-/* Line 1806 of yacc.c  */
-#line 232 "config_parser.yy"
-    {
-		(yyval.op) = (yyvsp[(1) - (1)].op);
-	}
-    break;
-
   case 32:
 
 /* Line 1806 of yacc.c  */
-#line 238 "config_parser.yy"
+#line 241 "config_parser.yy"
     {
-		(yyval.variant) = new Variant((yyvsp[(1) - (1)].text));
-		free((yyvsp[(1) - (1)].text));
+		(yyval.op) = (yyvsp[(1) - (1)].op);
 	}
     break;
 
   case 33:
 
 /* Line 1806 of yacc.c  */
-#line 243 "config_parser.yy"
+#line 247 "config_parser.yy"
     {
-		(yyval.variant) = new Variant((yyvsp[(1) - (1)].num));
+		(yyval.variant) = new Variant((yyvsp[(1) - (1)].text));
+		free((yyvsp[(1) - (1)].text));
 	}
     break;
 
   case 34:
 
 /* Line 1806 of yacc.c  */
-#line 247 "config_parser.yy"
+#line 252 "config_parser.yy"
     {
-		(yyval.variant) = new Variant();
+		(yyval.variant) = new Variant((yyvsp[(1) - (1)].num));
 	}
     break;
 
-  case 37:
+  case 35:
 
 /* Line 1806 of yacc.c  */
-#line 255 "config_parser.yy"
+#line 256 "config_parser.yy"
     {
-		(yyval.variant) = (yyvsp[(1) - (1)].variant);
+		(yyval.variant) = new Variant();
 	}
     break;
 
   case 38:
 
 /* Line 1806 of yacc.c  */
-#line 261 "config_parser.yy"
+#line 264 "config_parser.yy"
     {
-		m_Array = boost::make_shared<Dictionary>();
+		(yyval.variant) = (yyvsp[(1) - (1)].variant);
 	}
     break;
 
   case 39:
 
 /* Line 1806 of yacc.c  */
-#line 266 "config_parser.yy"
+#line 270 "config_parser.yy"
     {
-		(yyval.variant) = new Variant(m_Array);
-		m_Array.reset();
+		m_Array = boost::make_shared<Dictionary>();
 	}
     break;
 
   case 40:
 
 /* Line 1806 of yacc.c  */
-#line 273 "config_parser.yy"
+#line 275 "config_parser.yy"
+    {
+		(yyval.variant) = new Variant(m_Array);
+		m_Array.reset();
+	}
+    break;
+
+  case 41:
+
+/* Line 1806 of yacc.c  */
+#line 282 "config_parser.yy"
     {
 		m_Array->AddUnnamedProperty(*(yyvsp[(1) - (1)].variant));
 		delete (yyvsp[(1) - (1)].variant);
@@ -1781,7 +1800,7 @@ yyreduce:
 
 
 /* Line 1806 of yacc.c  */
-#line 1785 "config_parser.cc"
+#line 1804 "config_parser.cc"
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -2019,6 +2038,6 @@ yyreturn:
 
 
 /* Line 2067 of yacc.c  */
-#line 283 "config_parser.yy"
+#line 292 "config_parser.yy"
 
 
diff --git a/dyn/config_parser.h b/dyn/config_parser.h
index 3eb48bf15..4ac314b8c 100644
--- a/dyn/config_parser.h
+++ b/dyn/config_parser.h
@@ -82,10 +82,11 @@ using namespace icinga;
      T_MULTIPLY_EQUAL = 265,
      T_DIVIDE_EQUAL = 266,
      T_ABSTRACT = 267,
-     T_LOCAL = 268,
-     T_OBJECT = 269,
-     T_INCLUDE = 270,
-     T_INHERITS = 271
+     T_TEMPORARY = 268,
+     T_LOCAL = 269,
+     T_OBJECT = 270,
+     T_INCLUDE = 271,
+     T_INHERITS = 272
    };
 #endif
 /* Tokens.  */
@@ -99,10 +100,11 @@ using namespace icinga;
 #define T_MULTIPLY_EQUAL 265
 #define T_DIVIDE_EQUAL 266
 #define T_ABSTRACT 267
-#define T_LOCAL 268
-#define T_OBJECT 269
-#define T_INCLUDE 270
-#define T_INHERITS 271
+#define T_TEMPORARY 268
+#define T_LOCAL 269
+#define T_OBJECT 270
+#define T_INCLUDE 271
+#define T_INHERITS 272
 
 
 
@@ -122,7 +124,7 @@ typedef union YYSTYPE
 
 
 /* Line 2068 of yacc.c  */
-#line 126 "config_parser.h"
+#line 128 "config_parser.h"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
diff --git a/dyn/config_parser.yy b/dyn/config_parser.yy
index 58fd273a8..de041a8d6 100644
--- a/dyn/config_parser.yy
+++ b/dyn/config_parser.yy
@@ -52,6 +52,7 @@ using namespace icinga;
 %token <op> T_MULTIPLY_EQUAL
 %token <op> T_DIVIDE_EQUAL
 %token T_ABSTRACT
+%token T_TEMPORARY
 %token T_LOCAL
 %token T_OBJECT
 %token T_INCLUDE
@@ -85,6 +86,7 @@ static stack<ExpressionList::Ptr> m_ExpressionLists;
 static vector<ConfigItem::Ptr> m_Objects;
 static ConfigItem::Ptr m_Object;
 static bool m_Abstract;
+static bool m_Temporary;
 static bool m_Local;
 static Dictionary::Ptr m_Array;
 
@@ -137,6 +139,9 @@ inherits_specifier expressionlist
 		Expression abstractexpr("__abstract", OperatorSet, m_Abstract ? 1 : 0, yylloc);
 		exprl->AddExpression(abstractexpr);
 
+		Expression tempexpr("__temporary", OperatorSet, m_Temporary ? 1 : 0, yylloc);
+		exprl->AddExpression(tempexpr);
+
 		Expression localexpr("__local", OperatorSet, m_Local ? 1 : 0, yylloc);
 		exprl->AddExpression(localexpr);
 
@@ -155,6 +160,10 @@ attribute: T_ABSTRACT
 	{
 		m_Abstract = true;
 	}
+	| T_TEMPORARY
+	{
+		m_Temporary = true;
+	}
 	| T_LOCAL
 	{
 		m_Local = true;
diff --git a/dyn/configitem.cpp b/dyn/configitem.cpp
index 96ab331f2..5d45e73ca 100644
--- a/dyn/configitem.cpp
+++ b/dyn/configitem.cpp
@@ -138,7 +138,10 @@ void ConfigItem::Commit(void)
 
 void ConfigItem::Unregister(void)
 {
-	// TODO: unregister associated ConfigObject
+	ConfigObject::Ptr dobj = m_ConfigObject.lock();
+
+	if (dobj)
+		dobj->Unregister();
 
 	GetAllObjects()->RemoveObject(GetSelf());
 }
diff --git a/icinga-app/Makefile.am b/icinga-app/Makefile.am
index 78b5fd112..e6f97438b 100644
--- a/icinga-app/Makefile.am
+++ b/icinga-app/Makefile.am
@@ -22,6 +22,7 @@ icinga_LDADD = \
 	${top_builddir}/base/libbase.la \
 	${top_builddir}/icinga/libicinga.la \
 	-dlopen ${top_builddir}/components/checker/checker.la \
+	-dlopen ${top_builddir}/components/compat/compat.la \
 	-dlopen ${top_builddir}/components/configfile/configfile.la \
 	-dlopen ${top_builddir}/components/configrpc/configrpc.la \
 	-dlopen ${top_builddir}/components/delegation/delegation.la \
diff --git a/icinga/Makefile.am b/icinga/Makefile.am
index 3e10318ed..aaade88d0 100644
--- a/icinga/Makefile.am
+++ b/icinga/Makefile.am
@@ -9,6 +9,8 @@ libicinga_la_SOURCES =  \
 	checkresult.h \
 	checktask.cpp \
 	checktask.h \
+	cib.cpp \
+	cib.h \
 	configobjectadapter.cpp \
 	configobjectadapter.h \
 	endpoint.cpp \
@@ -17,8 +19,6 @@ libicinga_la_SOURCES =  \
 	endpointmanager.h \
 	icingaapplication.cpp \
 	icingaapplication.h \
-	icingacomponent.cpp \
-	icingacomponent.h \
 	host.cpp \
 	host.h \
 	i2-icinga.h \
diff --git a/icinga/cib.cpp b/icinga/cib.cpp
new file mode 100644
index 000000000..52fb845c2
--- /dev/null
+++ b/icinga/cib.cpp
@@ -0,0 +1,67 @@
+#include "i2-icinga.h"
+
+using namespace icinga;
+
+int CIB::m_Types;
+VirtualEndpoint::Ptr CIB::m_Endpoint;
+
+void CIB::RequireInformation(InformationType types)
+{
+	m_Types |= types;
+}
+
+void CIB::Start(void)
+{
+	m_Endpoint = boost::make_shared<VirtualEndpoint>();
+	if (m_Types & CIB_ServiceStatus) {
+		m_Endpoint->RegisterTopicHandler("delegation::ServiceStatus",
+		    boost::bind(&CIB::ServiceStatusRequestHandler, _2, _3));
+	}
+	EndpointManager::GetInstance()->RegisterEndpoint(m_Endpoint);
+}
+
+void CIB::ServiceStatusRequestHandler(const Endpoint::Ptr& sender, const RequestMessage& request)
+{
+	MessagePart params;
+	if (!request.GetParams(&params))
+		return;
+
+	string svcname;
+	if (!params.GetProperty("service", &svcname))
+		return;
+
+	Service service = Service::GetByName(svcname);
+
+	long nextCheck;
+	if (params.GetProperty("next_check", &nextCheck))
+		service.SetNextCheck(nextCheck);
+
+	long state, stateType;
+	if (params.GetProperty("state", &state) && params.GetProperty("state_type", &stateType)) {
+		long old_state, old_stateType;
+		old_state = service.GetState();
+		old_stateType = service.GetStateType();
+
+		if (state != old_state) {
+			time_t now;
+			time(&now);
+
+			service.SetLastStateChange(now);
+
+			if (old_stateType != stateType)
+				service.SetLastHardStateChange(now);
+		}
+
+		service.SetState(static_cast<ServiceState>(state));
+		service.SetStateType(static_cast<ServiceStateType>(stateType));
+	}
+
+	long attempt;
+	if (params.GetProperty("current_attempt", &attempt))
+		service.SetCurrentCheckAttempt(attempt);
+
+	Dictionary::Ptr cr;
+	if (params.GetProperty("result", &cr))
+		service.SetLastCheckResult(cr);
+}
+
diff --git a/icinga/cib.h b/icinga/cib.h
new file mode 100644
index 000000000..ab8389ac7
--- /dev/null
+++ b/icinga/cib.h
@@ -0,0 +1,30 @@
+#ifndef CIB_H
+#define CIB_H
+
+namespace icinga
+{
+
+enum InformationType
+{
+	CIB_Configuration = 1<<0,
+	CIB_ProgramStatus = 1<<1,
+	CIB_ServiceStatus = 1<<2
+};
+
+class CIB
+{
+public:
+	static void RequireInformation(InformationType type);
+
+	static void Start(void);
+
+private:
+	static int m_Types;
+	static VirtualEndpoint::Ptr m_Endpoint;
+
+	static void ServiceStatusRequestHandler(const Endpoint::Ptr& sender, const RequestMessage& request);
+};
+
+}
+
+#endif /* CIB_H */
diff --git a/icinga/endpointmanager.cpp b/icinga/endpointmanager.cpp
index 84cb4463c..04f1face1 100644
--- a/icinga/endpointmanager.cpp
+++ b/icinga/endpointmanager.cpp
@@ -379,3 +379,12 @@ EndpointManager::Iterator EndpointManager::End(void)
 	return m_Endpoints.end();
 }
 
+EndpointManager::Ptr EndpointManager::GetInstance(void)
+{
+	static EndpointManager::Ptr instance;
+
+	if (!instance)
+		instance = boost::make_shared<EndpointManager>();
+
+	return instance;
+}
diff --git a/icinga/endpointmanager.h b/icinga/endpointmanager.h
index 82363cbec..7a89c660d 100644
--- a/icinga/endpointmanager.h
+++ b/icinga/endpointmanager.h
@@ -38,6 +38,8 @@ public:
 
 	EndpointManager(void);
 
+	static EndpointManager::Ptr GetInstance(void);
+
 	void SetIdentity(string identity);
 	string GetIdentity(void) const;
 
diff --git a/icinga/i2-icinga.h b/icinga/i2-icinga.h
index 635d7fb43..690d40e72 100644
--- a/icinga/i2-icinga.h
+++ b/icinga/i2-icinga.h
@@ -46,12 +46,13 @@ using boost::unique_future;
 #include "virtualendpoint.h"
 #include "endpointmanager.h"
 #include "icingaapplication.h"
-#include "icingacomponent.h"
 
 #include "configobjectadapter.h"
 #include "host.h"
 #include "service.h"
 
+#include "cib.h"
+
 #include "macroprocessor.h"
 #include "checkresult.h"
 #include "checktask.h"
diff --git a/icinga/icingaapplication.cpp b/icinga/icingaapplication.cpp
index b2f8b5575..e200eacd3 100644
--- a/icinga/icingaapplication.cpp
+++ b/icinga/icingaapplication.cpp
@@ -49,8 +49,6 @@ int IcingaApplication::Main(const vector<string>& args)
 		return EXIT_FAILURE;
 	}
 
-	m_EndpointManager = boost::make_shared<EndpointManager>();
-
 	string componentDirectory = GetExeDirectory() + "/../lib/icinga2";
 	AddComponentSearchDir(componentDirectory);
 
@@ -85,32 +83,25 @@ int IcingaApplication::Main(const vector<string>& args)
 		shared_ptr<X509> cert = Utility::GetX509Certificate(GetCertificateFile());
 		string identity = Utility::GetCertificateCN(cert);
 		Application::Log(LogInformation, "icinga", "My identity: " + identity);
-		m_EndpointManager->SetIdentity(identity);
+		EndpointManager::GetInstance()->SetIdentity(identity);
 
 		shared_ptr<SSL_CTX> sslContext = Utility::MakeSSLContext(GetCertificateFile(), GetCertificateFile(), GetCAFile());
-		m_EndpointManager->SetSSLContext(sslContext);
+		EndpointManager::GetInstance()->SetSSLContext(sslContext);
 	}
 
 	/* create the primary RPC listener */
 	string service = GetService();
 	if (!service.empty())
-		GetEndpointManager()->AddListener(service);
+		EndpointManager::GetInstance()->AddListener(service);
+
+	CIB::RequireInformation(CIB_ServiceStatus);
+	CIB::Start();
 
 	RunEventLoop();
 
 	return EXIT_SUCCESS;
 }
 
-/**
- * Retrieves Icinga's endpoint manager.
- *
- * @returns The endpoint manager.
- */
-EndpointManager::Ptr IcingaApplication::GetEndpointManager(void)
-{
-	return m_EndpointManager;
-}
-
 void IcingaApplication::NewComponentHandler(const ConfigObject::Ptr& object)
 {
 	/* don't allow replicated config objects */
@@ -129,6 +120,11 @@ void IcingaApplication::NewComponentHandler(const ConfigObject::Ptr& object)
 	LoadComponent(path, object);
 }
 
+IcingaApplication::Ptr IcingaApplication::GetInstance(void)
+{
+	return static_pointer_cast<IcingaApplication>(Application::GetInstance());
+}
+
 void IcingaApplication::DeletedComponentHandler(const ConfigObject::Ptr& object)
 {
 	Component::Ptr component = GetComponent(object->GetName());
diff --git a/icinga/icingaapplication.h b/icinga/icingaapplication.h
index 438a1866c..ac0717408 100644
--- a/icinga/icingaapplication.h
+++ b/icinga/icingaapplication.h
@@ -36,7 +36,7 @@ public:
 
 	int Main(const vector<string>& args);
 
-	EndpointManager::Ptr GetEndpointManager(void);
+	static IcingaApplication::Ptr GetInstance(void);
 
 	string GetCertificateFile(void) const;
 	string GetCAFile(void) const;
@@ -44,8 +44,6 @@ public:
 	string GetService(void) const;
 
 private:
-	EndpointManager::Ptr m_EndpointManager;
-
 	string m_CertificateFile;
 	string m_CAFile;
 	string m_Node;
diff --git a/icinga/service.cpp b/icinga/service.cpp
index 9df1c581e..6f64ddd5f 100644
--- a/icinga/service.cpp
+++ b/icinga/service.cpp
@@ -12,6 +12,16 @@ string Service::GetDisplayName(void) const
 	return GetName();
 }
 
+Service Service::GetByName(string name)
+{
+	ConfigObject::Ptr configObject = ConfigObject::GetObject("service", name);
+
+	if (!configObject)
+		throw invalid_argument("Service '" + name + "' does not exist.");
+
+	return configObject;
+}
+
 Host Service::GetHost(void) const
 {
 	string hostname;
@@ -62,8 +72,17 @@ long Service::GetCheckInterval(void) const
 
 long Service::GetRetryInterval(void) const
 {
-	long value = 60;
-	GetConfigObject()->GetProperty("retry_interval", &value);
+	long value;
+	if (!GetConfigObject()->GetProperty("retry_interval", &value))
+		value = GetCheckInterval() / 5;
+
+	return value;
+}
+
+Dictionary::Ptr Service::GetDependencies(void) const
+{
+	Dictionary::Ptr value;
+	GetConfigObject()->GetProperty("dependencies", &value);
 	return value;
 }
 
@@ -74,15 +93,25 @@ void Service::SetNextCheck(time_t nextCheck)
 
 time_t Service::GetNextCheck(void)
 {
-	long value = -1;
-	GetConfigObject()->GetTag("next_check", &value);
-	if (value == -1) {
+	long value;
+	if (!GetConfigObject()->GetTag("next_check", &value)) {
 		value = time(NULL) + rand() % GetCheckInterval();
 		SetNextCheck(value);
 	}
 	return value;
 }
 
+void Service::UpdateNextCheck(void)
+{
+	time_t now;
+	time(&now);
+
+	if (GetStateType() == StateTypeSoft)
+		SetNextCheck(now + GetRetryInterval());
+	else
+		SetNextCheck(now + GetCheckInterval());
+}
+
 void Service::SetChecker(string checker)
 {
 	GetConfigObject()->SetTag("checker", checker);
@@ -131,6 +160,42 @@ ServiceStateType Service::GetStateType(void) const
 	return static_cast<ServiceStateType>(value);
 }
 
+void Service::SetLastCheckResult(const Dictionary::Ptr& result)
+{
+	GetConfigObject()->SetTag("last_result", result);
+}
+
+Dictionary::Ptr Service::GetLastCheckResult(void) const
+{
+	Dictionary::Ptr value;
+	GetConfigObject()->GetTag("last_result", &value);
+	return value;
+}
+
+void Service::SetLastStateChange(time_t ts)
+{
+	GetConfigObject()->SetTag("last_state_change", ts);
+}
+
+time_t Service::GetLastStateChange(void) const
+{
+	long value = 0;
+	GetConfigObject()->GetTag("last_state_change", &value);
+	return value;
+}
+
+void Service::SetLastHardStateChange(time_t ts)
+{
+	GetConfigObject()->SetTag("last_hard_state_change", ts);
+}
+
+time_t Service::GetLastHardStateChange(void) const
+{
+	long value = 0;
+	GetConfigObject()->GetTag("last_hard_state_change", &value);
+	return value;
+}
+
 void Service::ApplyCheckResult(const CheckResult& cr)
 {
 	long attempt = GetCurrentCheckAttempt();
@@ -154,3 +219,66 @@ void Service::ApplyCheckResult(const CheckResult& cr)
 	SetState(cr.GetState());
 }
 
+ServiceState Service::StateFromString(string state)
+{
+	/* TODO: make this thread-safe */
+	static map<string, ServiceState> stateLookup;
+
+	if (stateLookup.empty()) {
+		stateLookup["ok"] = StateOK;
+		stateLookup["warning"] = StateWarning;
+		stateLookup["critical"] = StateCritical;
+		stateLookup["unreachable"] = StateUnreachable;
+		stateLookup["uncheckable"] = StateUncheckable;
+		stateLookup["unknown"] = StateUnknown;
+	}
+
+	map<string, ServiceState>::iterator it;
+	it = stateLookup.find(state);
+
+	if (it == stateLookup.end())
+		return StateUnknown;
+	else
+		return it->second;
+}
+
+string Service::StateToString(ServiceState state)
+{
+	switch (state) {
+		case StateOK:
+			return "ok";
+		case StateWarning:
+			return "warning";
+		case StateCritical:
+			return "critical";
+		case StateUnreachable:
+			return "unreachable";
+		case StateUncheckable:
+			return "uncheckable";
+		case StateUnknown:
+		default:
+			return "unknown";
+	}
+}
+
+ServiceStateType Service::StateTypeFromString(string type)
+{
+	if (type == "soft")
+		return StateTypeSoft;
+	else
+		return StateTypeHard;
+}
+
+string Service::StateTypeToString(ServiceStateType type)
+{
+	if (type == StateTypeSoft)
+		return "soft";
+	else
+		return "hard";
+}
+
+bool Service::IsAllowedChecker(string checker) const
+{
+	/* TODO: check config */
+	return true;
+}
diff --git a/icinga/service.h b/icinga/service.h
index 5cf13e862..511aaa8b6 100644
--- a/icinga/service.h
+++ b/icinga/service.h
@@ -9,15 +9,15 @@ enum ServiceState
 	StateOK,
 	StateWarning,
 	StateCritical,
+	StateUnknown,
 	StateUnreachable,
 	StateUncheckable,
-	StateUnknown
 };
 
 enum ServiceStateType
 {
-	StateTypeHard,
-	StateTypeSoft
+	StateTypeSoft,
+	StateTypeHard
 };
 
 struct CheckResult;
@@ -29,6 +29,8 @@ public:
 		: ConfigObjectAdapter(configObject)
 	{ }
 
+	static Service GetByName(string name);
+
 	string GetDisplayName(void) const;
 	Host GetHost(void) const;
 	Dictionary::Ptr GetMacros(void) const;
@@ -37,13 +39,17 @@ public:
 	long GetMaxCheckAttempts(void) const;
 	long GetCheckInterval(void) const;
 	long GetRetryInterval(void) const;
+	Dictionary::Ptr GetDependencies(void) const;
 
 	void SetNextCheck(time_t nextCheck);
 	time_t GetNextCheck(void);
+	void UpdateNextCheck(void);
 
 	void SetChecker(string checker);
 	string GetChecker(void) const;
 
+	bool IsAllowedChecker(string checker) const;
+
 	void SetCurrentCheckAttempt(long attempt);
 	long GetCurrentCheckAttempt(void) const;
 
@@ -53,7 +59,22 @@ public:
 	void SetStateType(ServiceStateType type);
 	ServiceStateType GetStateType(void) const;
 
+	void SetLastCheckResult(const Dictionary::Ptr& result);
+	Dictionary::Ptr GetLastCheckResult(void) const;
+
+	void SetLastStateChange(time_t ts);
+	time_t GetLastStateChange(void) const;
+
+	void SetLastHardStateChange(time_t ts);
+	time_t GetLastHardStateChange(void) const;
+
 	void ApplyCheckResult(const CheckResult& cr);
+
+	static ServiceState StateFromString(string state);
+	static string StateToString(ServiceState state);
+
+	static ServiceStateType StateTypeFromString(string state);
+	static string StateTypeToString(ServiceStateType state);
 };
 
 }