DataSourceFactory.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */

  20. package org.openspcoop2.utils.datasource;

  21. import java.text.SimpleDateFormat;
  22. import java.util.ArrayList;
  23. import java.util.Collection;
  24. import java.util.Collections;
  25. import java.util.Enumeration;
  26. import java.util.Iterator;
  27. import java.util.List;
  28. import java.util.Map;
  29. import java.util.Properties;
  30. import java.util.concurrent.ConcurrentHashMap;

  31. import javax.naming.RefAddr;

  32. import org.openspcoop2.utils.Utilities;
  33. import org.openspcoop2.utils.UtilsAlreadyExistsException;
  34. import org.openspcoop2.utils.UtilsException;
  35. import org.openspcoop2.utils.date.DateUtils;
  36. import org.openspcoop2.utils.jmx.RisorseJMXException;
  37. import org.openspcoop2.utils.resources.GestoreJNDI;

  38. /**
  39.  * DatasourceFactory
  40.  *  
  41.  * @author Poli Andrea (apoli@link.it)
  42.  * @author $Author$
  43.  * @version $Rev$, $Date$
  44.  */
  45. public class DataSourceFactory {

  46.     private static Map<String, org.openspcoop2.utils.datasource.DataSource> mapUUIDtoDatasources = new ConcurrentHashMap<String, org.openspcoop2.utils.datasource.DataSource>();
  47.     private static Map<String, String> mapApplicativeIDtoUUID = new ConcurrentHashMap<String, String>();
  48.     private static Map<String, String> mapJndiNametoUUID = new ConcurrentHashMap<String, String>();
  49.     private static org.openspcoop2.utils.jmx.GestoreRisorseJMX gestoreRisorse = null;
  50.    
  51.     private static synchronized void initGestoreRisorseJMX() throws RisorseJMXException{
  52.         if(gestoreRisorse==null)
  53.             gestoreRisorse = new org.openspcoop2.utils.jmx.GestoreRisorseJMX();
  54.     }
  55.    
  56.     public static int sizeDatasources(){
  57.         return mapUUIDtoDatasources.size();
  58.     }
  59.    
  60.     public static List<String> getJndiNameDatasources() {
  61.         if(mapJndiNametoUUID==null || mapJndiNametoUUID.isEmpty()) {
  62.             return null;
  63.         }
  64.         List<String> l = new ArrayList<>();
  65.         l.addAll(mapJndiNametoUUID.keySet());
  66.         return l;
  67.     }
  68.    
  69.     public static List<String> getApplicativeIdDatasources() {
  70.         if(mapApplicativeIDtoUUID==null || mapApplicativeIDtoUUID.isEmpty()) {
  71.             return null;
  72.         }
  73.         List<String> l = new ArrayList<>();
  74.         l.addAll(mapApplicativeIDtoUUID.keySet());
  75.         return l;
  76.     }
  77.    
  78.     public static String[] getJmxStatus() throws UtilsException{    
  79.         if(mapUUIDtoDatasources==null || mapUUIDtoDatasources.size()<=0)
  80.             return null;
  81.    
  82.         Collection<org.openspcoop2.utils.datasource.DataSource> list = mapUUIDtoDatasources.values();
  83.         Iterator<org.openspcoop2.utils.datasource.DataSource> it = list.iterator();
  84.         List<String> listResource = new ArrayList<>();
  85.         while (it.hasNext()) {
  86.             org.openspcoop2.utils.datasource.DataSource datasource = (org.openspcoop2.utils.datasource.DataSource) it.next();
  87.             StringBuilder bf = new StringBuilder();
  88.             SimpleDateFormat dateformat = DateUtils.getSimpleDateFormatMs();
  89.             bf.append("(").append(dateformat.format(datasource.getDate())).append(") ");
  90.             bf.append("idDatasource:");
  91.             bf.append(datasource.getUuidDatasource());
  92.             if(datasource.getJndiName()!=null){
  93.                 if(bf.length() > 0){
  94.                     bf.append(" ");
  95.                 }
  96.                 bf.append("jndiName:");
  97.                 bf.append(datasource.getJndiName());
  98.             }
  99.             if(datasource.getApplicativeIdDatasource()!=null){
  100.                 if(bf.length() > 0){
  101.                     bf.append(" ");
  102.                 }
  103.                 bf.append("idApplicativo:");
  104.                 bf.append(datasource.getApplicativeIdDatasource());
  105.             }
  106.             if(bf.length() > 0){
  107.                 bf.append(" ");
  108.             }
  109.             bf.append("ConnessioniAttive:");
  110.             bf.append(datasource.size());
  111.             listResource.add(bf.toString());
  112.         }
  113.         if(listResource.size()>0){
  114.             Collections.sort(listResource);
  115.             return listResource.toArray(new String[1]);
  116.         }else
  117.             return null;
  118.        
  119.     }
  120.    
  121.    
  122.     // **** Metodi per la creazione ***
  123.    
  124.     public static org.openspcoop2.utils.datasource.DataSource newInstance(String jndiName,Properties jndiContext, DataSourceParams params) throws UtilsException, UtilsAlreadyExistsException{
  125.         if(jndiContext==null){
  126.             jndiContext = new Properties();
  127.         }
  128.         GestoreJNDI jndi = new GestoreJNDI(jndiContext);
  129.         Object oSearch = null;
  130.         try{
  131.             oSearch = jndi.lookup(jndiName);
  132.         }catch(Throwable t){
  133.             throw new UtilsException("Lookup jndiResource ["+jndiName+"] failed: "+t.getMessage(),t);
  134.         }
  135.         if(oSearch==null){
  136.             throw new UtilsException("Lookup jndiResource ["+jndiName+"] not found");
  137.         }
  138.         javax.sql.DataSource datasource = null;
  139.         try{
  140.             datasource = (javax.sql.DataSource) oSearch;
  141.         }catch(Throwable t){
  142.             StringBuilder bf = new StringBuilder();
  143.             if(oSearch instanceof javax.naming.Reference){
  144.                 javax.naming.Reference r = (javax.naming.Reference) oSearch;
  145.                 bf.append(" (Factory=");
  146.                 bf.append(r.getFactoryClassName());
  147.                 bf.append(" FactoryLocation=");
  148.                 bf.append(r.getFactoryClassLocation());
  149.                 Enumeration<RefAddr> enR = r.getAll();
  150.                 if(enR!=null){
  151.                     while (enR.hasMoreElements()) {
  152.                         RefAddr refAddr = (RefAddr) enR.nextElement();
  153.                         bf.append(" [").
  154.                             append("type=").
  155.                             append(refAddr.getType()).
  156.                             append(" content=").
  157.                             append(refAddr.getContent()).
  158.                             append("]");
  159.                     }
  160.                 }
  161.                 bf.append(")");
  162.             }
  163.             throw new UtilsException("lookup failed (object class: "+oSearch.getClass().getName()+")"+bf.toString()+": "+t.getMessage(),t);
  164.         }
  165.        
  166.         return newInstance(datasource, params, jndiName);
  167.     }

  168.     public static org.openspcoop2.utils.datasource.DataSource newInstance(javax.sql.DataSource datasource, DataSourceParams params) throws UtilsException, UtilsAlreadyExistsException{
  169.         return newInstance(datasource, params, null);
  170.     }
  171.    
  172.     public static synchronized DataSource newInstance(javax.sql.DataSource datasource, DataSourceParams params, String jndiName) throws UtilsException, UtilsAlreadyExistsException{
  173.        
  174.         if(params==null){
  175.             throw new UtilsException("Parameters undefined");
  176.         }
  177.         if(params.getDatabaseType()==null){
  178.             throw new UtilsException("Parameters.databaseType undefined");
  179.         }
  180.         try{
  181.             if(params.getApplicativeId()!=null){
  182.                 if(mapApplicativeIDtoUUID.containsKey(params.getApplicativeId())){
  183.                     throw new UtilsAlreadyExistsException("Datasource with applicative id ["+params.getApplicativeId()+"] already exists");
  184.                 }
  185.             }
  186.            
  187.             if(jndiName!=null){
  188.                 if(mapJndiNametoUUID.containsKey(jndiName)){
  189.                     throw new UtilsAlreadyExistsException("Datasource with jndiName ["+jndiName+"] already exists");
  190.                 }
  191.             }
  192.            
  193.             org.openspcoop2.utils.datasource.DataSource ds =
  194.                     new org.openspcoop2.utils.datasource.DataSource(datasource, params.getDatabaseType(), params.isWrapOriginalMethods(), jndiName, params.getApplicativeId());
  195.            
  196.             String uuidDatasource = ds.getUuidDatasource();
  197.             mapUUIDtoDatasources.put(uuidDatasource, ds);
  198.             if(params.getApplicativeId()!=null){
  199.                 mapApplicativeIDtoUUID.put(params.getApplicativeId(), uuidDatasource);
  200.             }
  201.             if(jndiName!=null){
  202.                 mapJndiNametoUUID.put(jndiName, uuidDatasource);
  203.             }
  204.        
  205.             if(params.isBindJmx()){
  206.                 if(gestoreRisorse==null){
  207.                     initGestoreRisorseJMX();
  208.                     gestoreRisorse.registerMBean(JmxDataSource.class, params.getJmxDomain(), params.getJmxType(), params.getJmxName(), false);
  209.                 }
  210.             }
  211.            
  212.             return ds;
  213.         }
  214.         catch(UtilsAlreadyExistsException e){
  215.             throw e;
  216.         }
  217.         catch(Exception e){
  218.             throw new UtilsException(e.getMessage(),e);
  219.         }
  220.        
  221.     }
  222.    
  223.     // **** Metodi per recuperare il datasource ***
  224.    
  225.     public static org.openspcoop2.utils.datasource.DataSource getInstance(String id) throws UtilsException{
  226.         String uuid = id;
  227.         if(mapApplicativeIDtoUUID.containsKey(id)){
  228.             uuid = mapApplicativeIDtoUUID.get(id);
  229.         }
  230.         else if(mapJndiNametoUUID.containsKey(id)){
  231.             uuid = mapJndiNametoUUID.get(id);
  232.         }
  233.         org.openspcoop2.utils.datasource.DataSource d = mapUUIDtoDatasources.get(uuid);
  234.         if(d==null){
  235.             throw new UtilsException("Datasource with id ["+id+"] not exists");
  236.         }
  237.         return d;
  238.     }

  239.     // **** Metodi per rilasciare le risorse ***
  240.     public static void closeResources() throws UtilsException{

  241.         mapApplicativeIDtoUUID.clear();
  242.         mapJndiNametoUUID.clear();

  243.         Collection<org.openspcoop2.utils.datasource.DataSource> list = mapUUIDtoDatasources.values();
  244.         Iterator<org.openspcoop2.utils.datasource.DataSource> it = list.iterator();
  245.         while (it.hasNext()) {
  246.             org.openspcoop2.utils.datasource.DataSource datasource = (org.openspcoop2.utils.datasource.DataSource) it.next();
  247.             datasource.setClosed(true);
  248.         }
  249.        
  250.         boolean waitCloseConnection = true;
  251.         int maxWait = 60000;
  252.         int sleep = 1000;
  253.         int index = 0;
  254.         int count = 1;
  255.         int total = maxWait / sleep;
  256.         while(waitCloseConnection && index<maxWait){
  257.             list = mapUUIDtoDatasources.values();
  258.             it = list.iterator();
  259.             boolean closeAll = true;
  260.             StringBuilder bf = new StringBuilder();
  261.             boolean debugClose = true;
  262.             while (it.hasNext()) {
  263.                 org.openspcoop2.utils.datasource.DataSource datasource = (org.openspcoop2.utils.datasource.DataSource) it.next();
  264.                 if(datasource.size()>0){
  265.                     closeAll = false;
  266.                     bf.append("Find datasource (applicative-id:"+datasource.getApplicativeIdDatasource()+" jndi:"+datasource.getJndiName()+") with "+datasource.size()+" released connection:");
  267.                     String[] status = datasource.getJmxStatus();
  268.                     if(status!=null) {
  269.                         for (int i = 0; i < status.length; i++) {
  270.                             bf.append("\n");
  271.                             bf.append("\t"+status[i]);
  272.                         }
  273.                     }
  274.                     break;
  275.                 }
  276.             }
  277.             if(closeAll==false){
  278.                 if(debugClose && ((count%5)==0)) {
  279.                     // stampo la situazione ogni 5 secondi
  280.                     System.out.println(bf.toString());
  281.                 }
  282.                 System.out.println("Wait close connection ("+count+"/"+total+") ...");
  283.                 Utilities.sleep(sleep);
  284.                 index = index + sleep;
  285.                 count++;
  286.             }
  287.             else{
  288.                 waitCloseConnection = false;
  289.             }
  290.         }
  291.         if(waitCloseConnection==true){
  292.             System.out.println("Forzo chiusura connessioni");
  293.             // forzo chiusura connessioni
  294.             list = mapUUIDtoDatasources.values();
  295.             it = list.iterator();
  296.             while (it.hasNext()) {
  297.                 org.openspcoop2.utils.datasource.DataSource datasource = (org.openspcoop2.utils.datasource.DataSource) it.next();
  298.                 if(datasource.size()>0){
  299.                     datasource.releaseConnnections();
  300.                 }
  301.             }
  302.         }
  303.         mapUUIDtoDatasources.clear();  
  304.        
  305.         if(gestoreRisorse!=null){
  306.             gestoreRisorse.unregisterMBeans();
  307.         }
  308.     }
  309. }