/*
* Seldon -- open source prediction engine
* =======================================
*
* Copyright 2011-2015 Seldon Technologies Ltd and Rummble Ltd (http://www.seldon.io/)
*
* ********************************************************************************************
*
* 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.
*
* ********************************************************************************************
*/
/* Generated by Together */
package io.seldon.db.jdo;
import io.seldon.api.APIException;
import io.seldon.api.Constants;
import io.seldon.api.state.ClientConfigHandler;
import io.seldon.api.state.NewClientListener;
import io.seldon.db.jdbc.JDBCConnectionFactory;
import io.seldon.dbcp.DbcpInitialisedListener;
import io.seldon.dbcp.DbcpPoolHandler;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class JDOFactory implements NewClientListener, DbConfigHandler, DbcpInitialisedListener
{
private static final Logger logger = Logger.getLogger( JDOFactory.class.getName() );
public static final String DEFAULT_DB_JNDI_NAME = "ClientDB";
private JDOPMRetriever pmRet = new JDOPMRetriever();
private Map<String, PersistenceManagerFactory> factories = new ConcurrentHashMap<>();
private Map<String,String> clientJNDINames = new ConcurrentHashMap<>();
private Map<String,String> clientToDBName = new ConcurrentHashMap<>();
@Autowired
private Properties dataNucleusProperties;
@Autowired
private JDBCConnectionFactory jdbcConnectionFactory;
@Autowired
private DbcpPoolHandler dbcpPoolHandler;
@Autowired
private ClientConfigHandler clientConfigHandler;
private static JDOFactory jdoFactory;
private List<DbConfigListener> listeners = new ArrayList<>();
@PostConstruct
public void setup()
{
dbcpPoolHandler.addInitialisedListener(this);
}
@Override
public void dbcpInitialised() {
addDataSource("api", "api", DEFAULT_DB_JNDI_NAME);
clientConfigHandler.addNewClientListener(this, true);
jdoFactory = this; // should be removed at some point
}
public String getJNDIForClient(String client)
{
return clientJNDINames.get(client);
}
private boolean addDataSource(String client,String dbName,String jndiName)
{
DataSource ds = dbcpPoolHandler.get(jndiName);
if (ds != null)
{
registerFactory(client,dbName,ds);
jdbcConnectionFactory.addDataSource(client,ds,dbName);
return true;
}
else
{
logger.error("Failed to get datasource for client "+client+" with jndiName="+jndiName);
return false;
}
}
private void registerFactory(String clientName, String databaseName, DataSource ds) {
Properties connectionProperties = (Properties) dataNucleusProperties.clone();
connectionProperties.put("javax.jdo.option.ConnectionFactory", ds);
if (databaseName != null)
connectionProperties.setProperty("datanucleus.mapping.Catalog", databaseName);
logger.info("Adding PMF factory for client "+clientName+" with database "+databaseName);
PersistenceManagerFactory factory = JDOHelper.getPersistenceManagerFactory(connectionProperties);
factories.put(clientName, factory);
}
/**
* Return the singleton persistence manager factory instance.
*/
public synchronized PersistenceManagerFactory getPersistenceManagerFactory ()
{
if (factories.size() == 1)
return factories.values().iterator().next();
else
return null;
}
public boolean isDefaultClient(String key)
{
return !factories.containsKey(key);
}
public PersistenceManager getPersistenceManager(String key)
{
PersistenceManagerFactory pmf = factories.get(key);
if (pmf == null)
{
throw new APIException(APIException.INTERNAL_DB_ERROR);
}
if (pmf != null)
{
PersistenceManager pm = (PersistenceManager) pmRet.getPersistenceManager(key,pmf);
if (!pm.currentTransaction().isActive())
TransactionPeer.startReadOnlyTransaction(pm);
return pm;
}
else
return null;
}
public void cleanupPM()
{
pmRet.cleanup();
}
@Override
public synchronized void clientAdded(String client, Map<String, String> initialConfig) {
String jndiName = initialConfig.get("DB_JNDI_NAME");
if(jndiName==null)
jndiName = DEFAULT_DB_JNDI_NAME;
String dbName = initialConfig.get("DB_NAME");
if(dbName==null)
dbName = client;
logger.info("Adding client "+client+" JNDI="+jndiName+" dbName="+dbName);
if (addDataSource(client, dbName, jndiName))
{
for(DbConfigListener listener: listeners)
listener.dbConfigInitialised(client);
}
}
@Override
public void clientDeleted(String client) {
logger.info("Removing PM factory for "+client);
factories.get(client).close();
factories.remove(client);
}
public static JDOFactory get(){
return jdoFactory;
}
@Override
public void addDbConfigListener(DbConfigListener listener) {
listeners.add(listener);
}
}