/******************************************************************************* * Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * Oracle - initial API and implementation from Oracle TopLink ******************************************************************************/ package org.eclipse.persistence.internal.helper; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.eclipse.persistence.logging.SessionLog; /** * @author Mitesh Meswani * This class is responsible to translate given database name to a DatabasePlatform. */ public class DBPlatformHelper { private static final String DEFAULTPLATFORM = "org.eclipse.persistence.platform.database.DatabasePlatform"; // NOI18N private final static String PROPERTY_PATH = "org/eclipse/persistence/internal/helper/"; // NOI18N private final static String VENDOR_NAME_TO_PLATFORM_RESOURCE_NAME = PROPERTY_PATH + "VendorNameToPlatformMapping.properties"; //NOI18N /** * Holds mapping between possible vendor names to internal platforms defined above. * vendor names are treated as regular expressions. */ private static List<String[]> _nameToVendorPlatform = null; /** Get Database Platform from vendor name. * @param vendorName Input vendor name. Typically this is obtained by querying * <code>DatabaseMetaData</code>. * @param logger The logger. * @return Database platform that corresponds to <code>vendorName</code>. * If vendorName does not match any of predefined vendor names, <code> * DEFAULTPLATFORM </code> is returned. */ public static String getDBPlatform(String vendorName, SessionLog logger) { initializeNameToVendorPlatform(logger); String detectedDbPlatform = null; if(vendorName != null) { detectedDbPlatform = matchVendorNameInProperties(vendorName, _nameToVendorPlatform, logger); } if (logger.shouldLog(SessionLog.FINE) ) { logger.log(SessionLog.FINE, SessionLog.CONNECTION, "dbPlatformHelper_detectedVendorPlatform", detectedDbPlatform ); // NOI18N } if (detectedDbPlatform == null) { if(logger.shouldLog(SessionLog.INFO)) { logger.log(SessionLog.INFO, SessionLog.CONNECTION, "dbPlatformHelper_defaultingPlatform", vendorName, DEFAULTPLATFORM); // NOI18N } detectedDbPlatform = DEFAULTPLATFORM; } return detectedDbPlatform; } /** * Allocate and initialize nameToVendorPlatform if not already done. */ private static List<String[]> initializeNameToVendorPlatform(SessionLog logger) { synchronized(DBPlatformHelper.class) { if(_nameToVendorPlatform == null) { _nameToVendorPlatform = new ArrayList<String[]>(); try { loadFromResource(_nameToVendorPlatform, VENDOR_NAME_TO_PLATFORM_RESOURCE_NAME, DBPlatformHelper.class.getClassLoader() ); } catch (IOException e) { logger.log(SessionLog.WARNING, SessionLog.CONNECTION, "dbPlatformHelper_noMappingFound", VENDOR_NAME_TO_PLATFORM_RESOURCE_NAME); } } } return _nameToVendorPlatform; } /** * Match vendorName in properties specified by _nameToVendorPlatform. */ private static String matchVendorNameInProperties(String vendorName, List<String[]> nameToVendorPlatform, SessionLog logger) { String dbPlatform = null; //Iterate over all properties till we find match. for( Iterator<String[]> iterator = nameToVendorPlatform.iterator(); dbPlatform == null && iterator.hasNext();) { String[] entry = iterator.next(); String regExpr = entry[0]; String value = entry[1]; if (logger.shouldLog(SessionLog.FINEST)) { logger.log(SessionLog.FINEST, SessionLog.CONNECTION, "dbPlatformHelper_regExprDbPlatform", regExpr, value); // NOI18N } if( matchPattern(regExpr, vendorName, logger) ) { dbPlatform = value; } } return dbPlatform; } /** Matches target to pattern specified regExp. Returns false if there is * any error compiling regExp. * @param regExp The regular expression. * @param target The target against which we are trying to match regExp. * @param logger * @return false if there is error compiling regExp or target does not * match regExp. true if regExp matches pattern. */ private static boolean matchPattern(String regExp, String target, SessionLog logger) { boolean matches = false; try { matches = Pattern.matches(regExp,target); } catch (PatternSyntaxException e){ if(logger.shouldLog(SessionLog.FINE)) { logger.log(SessionLog.FINE, SessionLog.CONNECTION, "dbPlatformHelper_patternSyntaxException", e); // NOI18N } } return matches; } //-----Property Loading helper methods ----/ private static void loadFromResource(List<String[]> properties, String resourceName, ClassLoader classLoader) throws IOException { load(properties, resourceName, classLoader); } /** * Loads properties list from the specified resource * into specified Properties object. * @param properties Properties object to load * @param resourceName Name of resource. * If loadFromFile is true, this is fully qualified path name to a file. * param classLoader is ignored. * If loadFromFile is false,this is resource name. * @param classLoader The class loader that should be used to load the resource. If null,primordial * class loader is used. */ private static void load(List<String[]> properties, final String resourceName, final ClassLoader classLoader) throws IOException { try (BufferedReader bin = new BufferedReader( new InputStreamReader(openResourceInputStream(resourceName,classLoader)))) { for (String line = bin.readLine(); line != null; line = bin.readLine()) { String[] keyValue = validateLineForReturnAsKeyValueArray(line); if (keyValue != null) { properties.add(keyValue); } } } } /** * Open resourceName as input stream inside doPriviledged block */ private static InputStream openResourceInputStream(final String resourceName, final ClassLoader classLoader) { return (InputStream) AccessController.doPrivileged( new PrivilegedAction() { public Object run() { if (classLoader != null) { return classLoader.getResourceAsStream(resourceName); } else { return ClassLoader.getSystemResourceAsStream(resourceName); } } } ); } private static String[] validateLineForReturnAsKeyValueArray(String line) { if (line == null || line.length() == 0) { return null; } // trim leading AND trailing space line = line.trim(); // check for comment and empty line if (line.length() == 0 || line.startsWith("#")) { return null; } // check line contains valid properties '=' separator int indexOfEquals = line.indexOf('='); if (indexOfEquals == -1) { return null; } String key = line.substring(0, indexOfEquals); String value = line.substring(indexOfEquals + 1, line.length()); return new String[] { key, value }; } }