<commit_before>/*
  Copyright 2010-2017 BusinessCode GmbH, Germany

  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 de.businesscode.bcdui.toolbox;

import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.log4j.Logger;

import de.businesscode.bcdui.binding.exc.BindingException;
import de.businesscode.bcdui.toolbox.config.BareConfiguration;
import de.businesscode.bcdui.toolbox.config.ConfigurationProvider;
import de.businesscode.bcdui.toolbox.config.DbProperties;
import de.businesscode.util.JNDIProvider;
import de.businesscode.util.SingletonHolder;

/**
 *
 * This class extends the {@link JNDIProvider} and offers a common API to retrieve configuration parameter from JNDI
 * context as specified by servlet spec, furthermore this class cascades the configuration via {@link DbProperties}
 * allowing to manage dynamic properties from database. all API refer to "server" scope in sense of {@link DbProperties} scope,
 * except of {@link #getClientParameters()} which provides "client" scope configuration from database.
 *
 */
public class Configuration implements ConfigurationProvider {
  /* singleton handling */
  // this one is used internally in static convenience getters
  private static boolean isInitialized = false;
  private static SingletonHolder<Configuration> holder = new SingletonHolder<Configuration>() {
    @Override
    protected Configuration createInstance() {
      return new Configuration();
    }
  }; // MUST NOT initialize eagerly here!

  public static Configuration getInstance() {
    return holder.get();
  }

  // Well known context values:
  public static final String CONFIG_FILE_PATH_KEY  = "bcdui/filePathKey";
  public static final String DISABLE_CACHE         = "bcdui/disableCache";
  public static final String VFS_CATALOG_KEY       = "bcdui/cache/vfs/catalog";
  public static final String CONFIG_DB_RELOAD_SEC  = "bcdui/config/dbProperties/reloadFrequencySeconds";

  public static final String DEFAULT_DB_CONTEXT_ID = "bcdui/defaultConnection";
  private static final String BINDING_DB_CONFIG    = "bcd_db_properties";
  private static final int DEFAULT_CONFIG_DB_RELOAD_SEC = 30; // db properties are reloaded after every 30sec

  private DbProperties dbProperties;
  private BareConfiguration bareConfig;

  static private Logger log = Logger.getLogger(Configuration.class);

  // For the optional classes, we determine here, which one to use based on a priority list and a lookup, which class actually is available
  // This serves as our form of dependency injection until we can assume all platforms we run on have CDI
  public static enum OPT_CLASSES {
    WRQ2SQL,            // Extends de.businesscode.bcdui.wrs.load.Wrq2Sql, has constructor with param: (IRequestOptions)
    WRQCALC2SQL,        // Extends de.businesscode.bcdui.wrs.load.WrqCalc2Sql, has constructor with param: (WrqInfo)
    DATASOURCEWRAPPER,  // Implements java.jdbc.DataSource, has constructor with params: (DataSource origDataSource, Boolean alertUnclosedObjects, String dataSourceName)
    BINDINGS,           // Extends de.businesscode.bcdui.binding.Bindings, has constructor with no params
    SUBJECTSETTINGS2SQL,// Implements de.businesscode.bcdui.wrs.load.SqlConditionGenerator, has constructor with params: (BindingSet bindingSet, WrqInfo wrqInfo, Collection<Element> connectives)
    VFSRESOURCEPROVIDER, // Implements de.businesscode.bcdui.web.servlets.StaticResourceServlet.ResourceProvider, has a default contructor
    DATABASECOMPATIBILITY // Implements de.businesscode.bcdui.web.servlets.StaticResourceServlet.ResourceProvider, has a default contructor
  }
  static private final Map<OPT_CLASSES,String[]> optionalClassesPrio;
  static private final Map<OPT_CLASSES,Class<?>> optionalClasses;
  static {
    optionalClassesPrio = new HashMap<OPT_CLASSES, String[]>();
    optionalClassesPrio.put(OPT_CLASSES.WRQ2SQL,     new String[]{"de.businesscode.bcdui.wrs.load.Wrq2Sql_TopN_Opt", "de.businesscode.bcdui.wrs.load.Wrq2Sql"});
    optionalClassesPrio.put(OPT_CLASSES.WRQCALC2SQL, new String[]{"de.businesscode.bcdui.wrs.load.WrqCalc2Sql_AnalytFct_Opt", "de.businesscode.bcdui.wrs.load.WrqCalc2Sql"});
    optionalClassesPrio.put(OPT_CLASSES.BINDINGS,    new String[]{"de.businesscode.bcdui.binding.BindingsEnterprise", "de.businesscode.bcdui.binding.Bindings"});
    optionalClassesPrio.put(OPT_CLASSES.DATASOURCEWRAPPER, new String[]{"de.businesscode.util.jdbc.wrapper.BcdDataSourceWrapper"});
    optionalClassesPrio.put(OPT_CLASSES.SUBJECTSETTINGS2SQL, new String[]{"de.businesscode.bcdui.wrs.load.SubjectSettings2Sql"});
    optionalClassesPrio.put(OPT_CLASSES.VFSRESOURCEPROVIDER, new String[]{"de.businesscode.bcdui.web.servlets.VfsResourceProvider"});
    optionalClassesPrio.put(OPT_CLASSES.DATABASECOMPATIBILITY, new String[]{"de.businesscode.util.jdbc.DatabaseCompatibilityEnterprise", "de.businesscode.util.jdbc.DatabaseCompatibility"});
    
    // For some classes he have several options available, for now we determine here, which one to use
    optionalClasses = new HashMap<OPT_CLASSES, Class<?>>();
    for(Iterator<OPT_CLASSES> it = optionalClassesPrio.keySet().iterator(); it.hasNext(); ) {
      OPT_CLASSES className = it.next();
      String[] classOptions = optionalClassesPrio.get(className);
      for(int i=0; i<classOptions.length; i++) {
        try {
          optionalClasses.put(className, Class.forName(classOptions[i]) );
          break;
        } catch(ClassNotFoundException e) {
          // No harm, we just try the next one
        }
      }
    }
  }

  protected Configuration(){
    super();
    isInitialized = true;
    this.bareConfig = BareConfiguration.getInstance();

    // Set some defaults
    try {
      getConfigurationParameter(DISABLE_CACHE);
    } catch (Exception e) {
      addConfigurationParameter(DISABLE_CACHE, false);
    }<commit_msg>Server / Configuration / extend custom class injection<commit_after>/*
  Copyright 2010-2017 BusinessCode GmbH, Germany

  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 de.businesscode.bcdui.toolbox;

import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.log4j.Logger;

import de.businesscode.bcdui.binding.exc.BindingException;
import de.businesscode.bcdui.toolbox.config.BareConfiguration;
import de.businesscode.bcdui.toolbox.config.ConfigurationProvider;
import de.businesscode.bcdui.toolbox.config.DbProperties;
import de.businesscode.util.JNDIProvider;
import de.businesscode.util.SingletonHolder;

/**
 *
 * This class extends the {@link JNDIProvider} and offers a common API to retrieve configuration parameter from JNDI
 * context as specified by servlet spec, furthermore this class cascades the configuration via {@link DbProperties}
 * allowing to manage dynamic properties from database. all API refer to "server" scope in sense of {@link DbProperties} scope,
 * except of {@link #getClientParameters()} which provides "client" scope configuration from database.
 *
 */
public class Configuration implements ConfigurationProvider {
  /* singleton handling */
  // this one is used internally in static convenience getters
  private static boolean isInitialized = false;
  private static SingletonHolder<Configuration> holder = new SingletonHolder<Configuration>() {
    @Override
    protected Configuration createInstance() {
      return new Configuration();
    }
  }; // MUST NOT initialize eagerly here!

  public static Configuration getInstance() {
    return holder.get();
  }

  // Well known context values:
  public static final String CONFIG_FILE_PATH_KEY  = "bcdui/filePathKey";
  public static final String DISABLE_CACHE         = "bcdui/disableCache";
  public static final String VFS_CATALOG_KEY       = "bcdui/cache/vfs/catalog";
  public static final String CONFIG_DB_RELOAD_SEC  = "bcdui/config/dbProperties/reloadFrequencySeconds";

  public static final String DEFAULT_DB_CONTEXT_ID = "bcdui/defaultConnection";
  private static final String BINDING_DB_CONFIG    = "bcd_db_properties";
  private static final int DEFAULT_CONFIG_DB_RELOAD_SEC = 30; // db properties are reloaded after every 30sec

  private DbProperties dbProperties;
  private BareConfiguration bareConfig;

  static private Logger log = Logger.getLogger(Configuration.class);

  // For the optional classes, we determine here, which one to use based on a priority list and a lookup, which class actually is available
  // This serves as our form of dependency injection until we can assume all platforms we run on have CDI
  public static enum OPT_CLASSES {
    WRQ2SQL,            // Extends de.businesscode.bcdui.wrs.load.Wrq2Sql, has constructor with param: (IRequestOptions)
    WRQCALC2SQL,        // Extends de.businesscode.bcdui.wrs.load.WrqCalc2Sql, has constructor with param: (WrqInfo)
    DATASOURCEWRAPPER,  // Implements java.jdbc.DataSource, has constructor with params: (DataSource origDataSource, Boolean alertUnclosedObjects, String dataSourceName)
    BINDINGS,           // Extends de.businesscode.bcdui.binding.Bindings, has constructor with no params
    SUBJECTSETTINGS2SQL,// Implements de.businesscode.bcdui.wrs.load.SqlConditionGenerator, has constructor with params: (BindingSet bindingSet, WrqInfo wrqInfo, Collection<Element> connectives)
    VFSRESOURCEPROVIDER, // Implements de.businesscode.bcdui.web.servlets.StaticResourceServlet.ResourceProvider, has a default contructor
    DATABASECOMPATIBILITY // Implements de.businesscode.bcdui.web.servlets.StaticResourceServlet.ResourceProvider, has a default contructor
  }
  static private final Map<OPT_CLASSES,String[]> optionalClassesPrio;
  static private final Map<OPT_CLASSES,Class<?>> optionalClasses;
  static {
    optionalClassesPrio = new HashMap<OPT_CLASSES, String[]>();
    optionalClassesPrio.put(OPT_CLASSES.WRQ2SQL,     new String[]{"de.businesscode.bcdui.wrs.load.Wrq2Sql_TopN_Opt", "de.businesscode.bcdui.wrs.load.Wrq2Sql"});
    optionalClassesPrio.put(OPT_CLASSES.WRQCALC2SQL, new String[]{"de.businesscode.bcdui.wrs.load.WrqCalc2Sql_AnalytFct_Opt", "de.businesscode.bcdui.wrs.load.WrqCalc2Sql"});
    optionalClassesPrio.put(OPT_CLASSES.BINDINGS,    new String[]{"de.businesscode.bcdui.binding.BindingsEnterprise", "de.businesscode.bcdui.binding.Bindings"});
    optionalClassesPrio.put(OPT_CLASSES.DATASOURCEWRAPPER, new String[]{"de.businesscode.util.jdbc.wrapper.BcdDataSourceWrapper"});
    optionalClassesPrio.put(OPT_CLASSES.SUBJECTSETTINGS2SQL, new String[]{"de.businesscode.bcdui.wrs.load.SubjectSettings2Sql_Custom", "de.businesscode.bcdui.wrs.load.SubjectSettings2Sql"});
    optionalClassesPrio.put(OPT_CLASSES.VFSRESOURCEPROVIDER, new String[]{"de.businesscode.bcdui.web.servlets.VfsResourceProvider"});
    optionalClassesPrio.put(OPT_CLASSES.DATABASECOMPATIBILITY, new String[]{"de.businesscode.util.jdbc.DatabaseCompatibilityEnterprise", "de.businesscode.util.jdbc.DatabaseCompatibility"});
    
    // For some classes he have several options available, for now we determine here, which one to use
    optionalClasses = new HashMap<OPT_CLASSES, Class<?>>();
    for(Iterator<OPT_CLASSES> it = optionalClassesPrio.keySet().iterator(); it.hasNext(); ) {
      OPT_CLASSES className = it.next();
      String[] classOptions = optionalClassesPrio.get(className);
      for(int i=0; i<classOptions.length; i++) {
        try {
          optionalClasses.put(className, Class.forName(classOptions[i]) );
          break;
        } catch(ClassNotFoundException e) {
          // No harm, we just try the next one
        }
      }
    }
  }

  protected Configuration(){
    super();
    isInitialized = true;
    this.bareConfig = BareConfiguration.getInstance();

    // Set some defaults
    try {
      getConfigurationParameter(DISABLE_CACHE);
    } catch (Exception e) {
      addConfigurationParameter(DISABLE_CACHE, false);
    }
{'fraction_non_alphanumeric': 0.0885036496350365, 'fraction_numerical': 0.00479014598540146, 'mean_word_length': 4.6209401709401705, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1565933', 'n_tokens_mistral': 3832, 'n_tokens_neox': 3694, 'n_words': 1010}