/* * 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); } }