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.persistence;
021    
022    import java.io.IOException;
023    import java.io.InputStream;
024    
025    import org.apache.commons.io.IOUtils;
026    import org.apache.commons.lang.StringUtils;
027    import org.apache.ibatis.builder.xml.XMLMapperBuilder;
028    import org.apache.ibatis.mapping.Environment;
029    import org.apache.ibatis.session.*;
030    import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
031    import org.sonar.api.BatchComponent;
032    import org.sonar.api.ServerComponent;
033    import org.sonar.persistence.model.DuplicationMapper;
034    import org.sonar.persistence.model.DuplicationUnit;
035    import org.sonar.persistence.model.Rule;
036    import org.sonar.persistence.model.RuleMapper;
037    
038    public class MyBatis implements BatchComponent, ServerComponent {
039    
040      private Database database;
041      private SqlSessionFactory sessionFactory;
042    
043      public MyBatis(Database database) {
044        this.database = database;
045      }
046    
047      public MyBatis start() throws IOException {
048        Configuration conf = new Configuration();
049        conf.setEnvironment(new Environment("production", createTransactionFactory(), database.getDataSource()));
050        conf.setUseGeneratedKeys(true);
051        conf.setLazyLoadingEnabled(false);
052    
053        loadAlias(conf, "DuplicationUnit", DuplicationUnit.class);
054        loadAlias(conf, "Rule", Rule.class);
055        loadMapper(conf, DuplicationMapper.class);
056        loadMapper(conf, RuleMapper.class);
057    
058        sessionFactory = new SqlSessionFactoryBuilder().build(conf);
059        return this;
060      }
061    
062      public SqlSessionFactory getSessionFactory() {
063        return sessionFactory;
064      }
065    
066      public SqlSession openSession() {
067        return sessionFactory.openSession();
068      }
069    
070      public SqlSession openSession(ExecutorType type) {
071        return sessionFactory.openSession(type);
072      }
073    
074    
075      private void loadMapper(Configuration conf, Class mapperClass) throws IOException {
076        // trick to use database-specific XML files for a single Mapper Java interface
077        InputStream input = getPathToMapper(mapperClass);
078        try {
079          XMLMapperBuilder mapperParser = new XMLMapperBuilder(input, conf, mapperClass.getName(), conf.getSqlFragments());
080          mapperParser.parse();
081          conf.addLoadedResource(mapperClass.getName());
082    
083        } finally {
084          IOUtils.closeQuietly(input);
085        }
086      }
087    
088      private InputStream getPathToMapper(Class mapperClass) {
089        InputStream input = getClass().getResourceAsStream("/" + StringUtils.replace(mapperClass.getName(), ".", "/") + "-" + database.getDialect().getId() + ".xml");
090        if (input == null) {
091          input = getClass().getResourceAsStream("/" + StringUtils.replace(mapperClass.getName(), ".", "/") + ".xml");
092        }
093        return input;
094      }
095    
096      private void loadAlias(Configuration conf, String alias, Class dtoClass) {
097        conf.getTypeAliasRegistry().registerAlias(alias, dtoClass);
098      }
099    
100      private static JdbcTransactionFactory createTransactionFactory() {
101        return new JdbcTransactionFactory();
102      }
103    
104    }