001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2008-2011 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * Sonar is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU Lesser General Public
008     * License as published by the Free Software Foundation; either
009     * version 3 of the License, or (at your option) any later version.
010     *
011     * Sonar is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * Lesser General Public License for more details.
015     *
016     * You should have received a copy of the GNU Lesser General Public
017     * License along with Sonar; if not, write to the Free Software
018     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019     */
020    package org.sonar.jpa.dialect;
021    
022    import com.google.common.base.Predicate;
023    import com.google.common.collect.Iterators;
024    import org.apache.commons.lang.StringUtils;
025    import org.sonar.api.utils.SonarException;
026    
027    import java.util.Arrays;
028    import java.util.Collection;
029    import java.util.List;
030    import java.util.NoSuchElementException;
031    
032    /**
033     * @since 1.12
034     */
035    public final class DialectRepository {
036    
037      private DialectRepository() {
038      }
039    
040      private static List<Dialect> builtInDialects = getSupportedDialects();
041    
042      public static Dialect find(final String dialectId, final String jdbcConnectionUrl) {
043        Dialect match = StringUtils.isNotEmpty(dialectId) ? findById(dialectId) : findByJdbcUrl(jdbcConnectionUrl);
044        if (match == null) {
045          throw new SonarException("Unable to determine database dialect to use within sonar with dialect " + dialectId + " jdbc url " + jdbcConnectionUrl);
046        }
047        return match;
048      }
049    
050      private static Dialect findByJdbcUrl(final String jdbcConnectionUrl) {
051        Dialect match = findDialect(builtInDialects, new Predicate<Dialect>() {
052          public boolean apply(Dialect dialect) {
053            return dialect.matchesJdbcURL(StringUtils.trimToEmpty(jdbcConnectionUrl));
054          }
055        });
056        return match;
057      }
058    
059      private static Dialect findById(final String dialectId) {
060        Dialect match = findDialect(builtInDialects, new Predicate<Dialect>() {
061          public boolean apply(Dialect dialect) {
062            return dialect.getId().equals(dialectId);
063          }
064        });
065        // maybe a class name if no match
066        match = match == null ? getDialectByClassname(dialectId) : match;
067        return match;
068      }
069    
070      private static Dialect findDialect(Collection<Dialect> dialects, Predicate<Dialect> predicate) {
071        try {
072          return Iterators.find(dialects.iterator(), predicate);
073        } catch (NoSuchElementException ex) {
074          return null;
075        }
076      }
077    
078      private static Dialect getDialectByClassname(String dialectId) {
079        try {
080          Class<? extends Dialect> dialectClass = (Class<? extends Dialect>) DialectRepository.class.getClassLoader().loadClass(dialectId);
081          return dialectClass.newInstance();
082        } catch (ClassNotFoundException e) {
083          // dialectId was not a class name :)
084        } catch (Exception e) {
085          throw new SonarException("Unable to instantiate dialect class", e);
086        }
087        return null;
088      }
089    
090      private static List<Dialect> getSupportedDialects() {
091        return Arrays.asList(new Derby(), new HsqlDb(), new MySql(), new Oracle(), new PostgreSql(), new MsSql());
092      }
093    }