/* * Copyright 2013 Robert von Burg <eitch@eitchnet.ch> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package li.strolch.runtime.configuration; import static li.strolch.db.DbConstants.PROP_DB_IGNORE_REALM; import static li.strolch.db.DbConstants.PROP_DB_PASSWORD; import static li.strolch.db.DbConstants.PROP_DB_URL; import static li.strolch.db.DbConstants.PROP_DB_USERNAME; import static li.strolch.runtime.StrolchConstants.makeRealmKey; import java.sql.Connection; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.Set; import javax.sql.DataSource; import li.strolch.agent.api.ComponentContainer; import li.strolch.agent.api.StrolchRealm; import li.strolch.persistence.api.StrolchPersistenceException; import li.strolch.runtime.StrolchConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Robert von Burg <eitch@eitchnet.ch> */ public abstract class DbConnectionBuilder { private static final String PROP_DB_POOL_PREFIX = "db.pool"; protected static final Logger logger = LoggerFactory.getLogger(DbConnectionBuilder.class); private ComponentContainer container; private ComponentConfiguration configuration; /** * @param container * @param persistenceHandlerConfiguration */ public DbConnectionBuilder(ComponentContainer container, ComponentConfiguration persistenceHandlerConfiguration) { this.container = container; this.configuration = persistenceHandlerConfiguration; } public Map<String, DataSource> build() { Map<String, DataSource> dsMap = new HashMap<>(); Set<String> realmNames = container.getRealmNames(); for (String realmName : realmNames) { StrolchRealm realm = container.getRealm(realmName); if (realm.getMode().isTransient()) continue; String dbIgnoreRealmKey = makeRealmKey(realmName, PROP_DB_IGNORE_REALM); String dbUrlKey = makeRealmKey(realmName, PROP_DB_URL); String dbUsernameKey = makeRealmKey(realmName, PROP_DB_USERNAME); String dbPasswordKey = makeRealmKey(realmName, PROP_DB_PASSWORD); boolean dbIgnoreRealm = configuration.getBoolean(dbIgnoreRealmKey, Boolean.FALSE); if (dbIgnoreRealm) { logger.info("Ignoring any DB configuration for Realm " + realmName); continue; } String dbUrl = configuration.getString(dbUrlKey, null); String username = configuration.getString(dbUsernameKey, null); String password = configuration.getString(dbPasswordKey, null); // find any pool configuration values Set<String> propertyKeys = configuration.getPropertyKeys(); Properties props = new Properties(); for (String key : propertyKeys) { if (!key.startsWith(PROP_DB_POOL_PREFIX)) continue; // TODO we should change how properties for realms are configured // since defaultRealm does not have to be on the key, we need this hack: String[] segments = key.split("\\."); String poolKey; String foundRealm; if (segments.length == 4) { // ends with realm foundRealm = segments[3]; } else if (segments.length == 3) { // default realm foundRealm = StrolchConstants.DEFAULT_REALM; } else { throw new IllegalArgumentException("Can't detect realm of this property: " + key); } // see if this is our realm if (!foundRealm.equals(realmName)) continue; poolKey = segments[2]; String value = configuration.getString(key, null); props.setProperty(poolKey, value); } DataSource ds = build(realmName, dbUrl, username, password, props); dsMap.put(realmName, ds); } return dsMap; } protected abstract DataSource build(String realm, String url, String username, String password, Properties proops); protected void validateConnection(DataSource ds) { try (Connection con = ds.getConnection()) { con.commit(); } catch (SQLException e) { throw new StrolchPersistenceException("Failed to validate connection to " + ds, e); } } }