final Map<String,Boolean> changedAuth = new TreeMap<String,Boolean>();
client.get(new FeedDestination() {
public void onFeed(Document feedDoc) {
}
public void onEntry(Document entryDoc) {
Entry entry = new Entry(entryDoc);
entry.index();
if (entry.getTerm(HOST_TERM)!=null) {
// store host entry till DB entries are done
hostsToDo.add(entry);
return;
}
if (entry.getTerm(DB_TERM)!=null) {
// store db entry till realms are done
dbToDo.add(entry);
return;
}
if (entry.getTerm(REALM_TERM)==null) {
// ignore non-realm entry
return;
}
Term nameT = entry.getTerm(REALM_NAME_TERM);
if (nameT==null) {
return;
}
String name = nameT.getFirstValue();
List<Link> services = entry.getLinks().get("service");
if (services==null) {
getLogger().warning("Missing 'service' relation link on realm "+name);
} else {
URI service = services.get(0).getLink();
AuthProtocolService auth = (AuthProtocolService)autoServices.get(name);
if (auth!=null) {
if (!auth.getServiceURI().equals(service)) {
// The service URI has changed
autoServices.remove(name);
auth = null;
changedAuth.put(name,Boolean.TRUE);
}
}
if (auth==null) {
getLogger().info("Adding realm "+name+" from service "+service);
auth = new AuthProtocolService();
Properties props = new Properties();
props.setProperty("href",service.toString());
try {
auth.init(props);
autoServices.put(name,auth);
currentAuthList.put(name,Boolean.TRUE);
} catch (AuthException ex) {
getLogger().log(Level.SEVERE,"Cannot initialize auth service for realm "+name,ex);
}
}
}
}
});
// Configure the databases
final Map<String,Boolean> currentDBList = new TreeMap<String,Boolean>();
for (Entry entry : dbToDo) {
Term nameT = entry.getTerm(DB_NAME_TERM);
if (nameT==null) {
getLogger().warning("Ignoring db entry that does not have name term "+DB_NAME_TERM);
return;
}
Term authT = entry.getTerm(DB_AUTH_TERM);
if (authT==null) {
getLogger().warning("Ignoring db entry that does not have auth term "+DB_AUTH_TERM);
return;
}
Term groupT = entry.getTerm(DB_GROUP_TERM);
Term aliasT = entry.getTerm(DB_ALIAS_TERM);
String dbName = nameT.getFirstValue();
String authName = authT.getFirstValue();
if (dbName==null) {
getLogger().warning("Ignoring db entry where name term "+DB_NAME_TERM+" does not have a value.");
return;
}
if (authName==null) {
getLogger().warning("Ignoring db entry where auth term "+DB_NAME_TERM+" does not have a value.");
return;
}
AuthService auth = services.get(authName);
if (auth==null) {
auth = autoServices.get(authName);
}
if (auth==null) {
getLogger().warning("Cannot configure db entry for "+dbName+" as auth service "+authName+" does not exist.");
return;
}
DBInfo dbinfo = autodbList.get(dbName);
Storage storage = null;
if (dbinfo==null) {
getLogger().info("Creating DB "+dbName);
DB db = new DB(getLogger(),new File(dbDir,dbName));
dbinfo = new DBInfo(dbName,db,auth,groupT!=null ? groupT.getFirstValue() : null, aliasT!=null ? aliasT.getFirstValue() : null);
storage = storageFactory.getStorage(db);
try {
getLogger().info("Connecting to DB "+dbName);
db.connect();
getLogger().info("Connected to DB "+dbName);
autodbList.put(dbName,dbinfo);
storage.start();
} catch (SQLException ex) {
getLogger().log(Level.SEVERE,"Cannot connect to database "+dbName,ex);
}
} else {
storage = storageFactory.getStorage(dbinfo.getDB());
}
currentDBList.put(dbName,Boolean.TRUE);
UserGuard adminGuard = new UserGuard(childContext,ChallengeScheme.HTTP_BASIC,"Atom Administrator",auth);
adminGuard.getRequiredGroups().add(AuthService.ADMIN_GROUP);
adminGuard.setNext(new AdminApplication(childContext,dbinfo.getDB(),storage,AtomApplication.RESOURCE_BASE));
admins.put(dbName,adminGuard);
for (Router router : adminRouters) {
router.attach("/admin/database/"+dbName,adminGuard).getTemplate().setMatchingMode(Template.MODE_STARTS_WITH);
}
}
// Remove databases that have been removed from feed
for (String name : autodbList.keySet()) {
if (currentDBList.get(name)==null) {
// the database was removed
DBInfo dbinfo = autodbList.remove(name);
dbinfo.getDB().stop();
Storage storage = storageFactory.getStorage(dbinfo.getDB());
storage.stop();
Restlet admin = admins.remove(name);
if (admin!=null) {
for (Router router : adminRouters) {
router.detach(admin);
}
}
}
}
final Map<String,Boolean> currentEntries = new TreeMap<String,Boolean>();
for (Entry entry : hostsToDo) {
Text text = entry.getContent();
if (text==null || !text.isXML()) {
getLogger().warning("Ignoring host entry with missing or has incorrectly typed content for configuration.");
continue;
}
Element hostE = text.getContent();
if (hostE==null) {
getLogger().warning("Ignoring host entry with empty content.");
continue;
}
Date edited = null;
try {
edited = entry.getEdited();
if (edited==null) {
edited = entry.getUpdated();
}
} catch (ParseException ex) {
getLogger().warning("Ignoring host entry with malformed date in updated or edited element: "+ex.getMessage());
continue;
}
if (edited==null) {
getLogger().warning("Ignoring host entry without updated or edited element.");
continue;
}
currentEntries.put(entry.getId(),Boolean.TRUE);
AutoConfiguredHost autoHost = hosts.get(entry.getId());
if (autoHost!=null && (autoHost.edited.getTime()<edited.getTime() || changedAuth.get(autoHost.host.getDatabaseName())!=null)) {
// the entry has changed, so delete
getLogger().info("Entry changed for host "+autoHost.vhost.getHostDomain()+", reconfiguring.");
getHosts().remove(autoHost.vhost);
autoHost = null;
}
if (autoHost!=null) {
getLogger().info("Nothing has changed for host "+autoHost.vhost.getHostDomain());
continue;
}
// Create configuration
changes = true;
ServerConfiguration.Host host = config.createHost(hostE);
// Configure host
getLogger().info("Adding host "+host.getName());
VirtualHost vhost = createVirtualHost(host);
WebComponent.this.configure(vhost,host);
if (autoHost==null) {
hosts.put(entry.getId(),new AutoConfiguredHost(vhost,host,edited));
} else {
autoHost.vhost = vhost;
autoHost.host = host;
autoHost.edited = edited;
}