001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2012 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.core.persistence; 021 022 import org.apache.commons.io.IOUtils; 023 import org.apache.commons.lang.StringUtils; 024 import org.apache.ibatis.builder.xml.XMLMapperBuilder; 025 import org.apache.ibatis.logging.LogFactory; 026 import org.apache.ibatis.mapping.Environment; 027 import org.apache.ibatis.session.*; 028 import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; 029 import org.slf4j.LoggerFactory; 030 import org.sonar.api.BatchComponent; 031 import org.sonar.api.ServerComponent; 032 import org.sonar.core.dashboard.*; 033 import org.sonar.core.duplication.DuplicationMapper; 034 import org.sonar.core.duplication.DuplicationUnitDto; 035 import org.sonar.core.properties.PropertiesMapper; 036 import org.sonar.core.properties.PropertyDto; 037 import org.sonar.core.purge.PurgeMapper; 038 import org.sonar.core.purge.PurgeVendorMapper; 039 import org.sonar.core.purge.PurgeableSnapshotDto; 040 import org.sonar.core.resource.*; 041 import org.sonar.core.review.ReviewDto; 042 import org.sonar.core.review.ReviewMapper; 043 import org.sonar.core.rule.RuleDto; 044 import org.sonar.core.rule.RuleMapper; 045 import org.sonar.core.template.LoadedTemplateDto; 046 import org.sonar.core.template.LoadedTemplateMapper; 047 import org.sonar.core.user.AuthorDto; 048 import org.sonar.core.user.AuthorMapper; 049 050 import java.io.IOException; 051 import java.io.InputStream; 052 053 public class MyBatis implements BatchComponent, ServerComponent { 054 055 private Database database; 056 private SqlSessionFactory sessionFactory; 057 058 public MyBatis(Database database) { 059 this.database = database; 060 } 061 062 public MyBatis start() throws IOException { 063 LogFactory.useSlf4jLogging(); 064 Configuration conf = new Configuration(); 065 conf.setEnvironment(new Environment("production", createTransactionFactory(), database.getDataSource())); 066 conf.setUseGeneratedKeys(true); 067 conf.setLazyLoadingEnabled(false); 068 conf.getVariables().setProperty("_true", database.getDialect().getTrueSqlValue()); 069 conf.getVariables().setProperty("_false", database.getDialect().getFalseSqlValue()); 070 071 loadAlias(conf, "ActiveDashboard", ActiveDashboardDto.class); 072 loadAlias(conf, "Author", AuthorDto.class); 073 loadAlias(conf, "Dashboard", DashboardDto.class); 074 loadAlias(conf, "DuplicationUnit", DuplicationUnitDto.class); 075 loadAlias(conf, "LoadedTemplate", LoadedTemplateDto.class); 076 loadAlias(conf, "Property", PropertyDto.class); 077 loadAlias(conf, "PurgeableSnapshot", PurgeableSnapshotDto.class); 078 loadAlias(conf, "Review", ReviewDto.class); 079 loadAlias(conf, "Resource", ResourceDto.class); 080 loadAlias(conf, "ResourceIndex", ResourceIndexDto.class); 081 loadAlias(conf, "Rule", RuleDto.class); 082 loadAlias(conf, "Snapshot", SnapshotDto.class); 083 loadAlias(conf, "SchemaMigration", SchemaMigrationDto.class); 084 loadAlias(conf, "Widget", WidgetDto.class); 085 loadAlias(conf, "WidgetProperty", WidgetPropertyDto.class); 086 087 loadMapper(conf, ActiveDashboardMapper.class); 088 loadMapper(conf, AuthorMapper.class); 089 loadMapper(conf, DashboardMapper.class); 090 loadMapper(conf, DuplicationMapper.class); 091 loadMapper(conf, LoadedTemplateMapper.class); 092 loadMapper(conf, PropertiesMapper.class); 093 loadMapper(conf, PurgeMapper.class); 094 loadMapper(conf, PurgeVendorMapper.class); 095 loadMapper(conf, ResourceMapper.class); 096 loadMapper(conf, ReviewMapper.class); 097 loadMapper(conf, ResourceIndexerMapper.class); 098 loadMapper(conf, RuleMapper.class); 099 loadMapper(conf, SchemaMigrationMapper.class); 100 loadMapper(conf, WidgetMapper.class); 101 loadMapper(conf, WidgetPropertyMapper.class); 102 103 sessionFactory = new SqlSessionFactoryBuilder().build(conf); 104 return this; 105 } 106 107 public SqlSessionFactory getSessionFactory() { 108 return sessionFactory; 109 } 110 111 public SqlSession openSession() { 112 return sessionFactory.openSession(ExecutorType.REUSE); 113 } 114 115 public BatchSession openBatchSession() { 116 SqlSession session = sessionFactory.openSession(ExecutorType.BATCH); 117 return new BatchSession(session); 118 } 119 120 public static void closeQuietly(SqlSession session) { 121 if (session != null) { 122 try { 123 session.close(); 124 } catch (Exception e) { 125 LoggerFactory.getLogger(MyBatis.class).warn("Fail to close session", e); 126 // do not re-throw the exception 127 } 128 } 129 } 130 131 private void loadMapper(Configuration conf, Class mapperClass) throws IOException { 132 // trick to use database-specific XML files for a single Mapper Java interface 133 InputStream input = getPathToMapper(mapperClass); 134 try { 135 XMLMapperBuilder mapperParser = new XMLMapperBuilder(input, conf, mapperClass.getName(), conf.getSqlFragments()); 136 mapperParser.parse(); 137 conf.addLoadedResource(mapperClass.getName()); 138 139 } finally { 140 IOUtils.closeQuietly(input); 141 } 142 } 143 144 private InputStream getPathToMapper(Class mapperClass) { 145 InputStream input = getClass().getResourceAsStream( 146 "/" + StringUtils.replace(mapperClass.getName(), ".", "/") + "-" + database.getDialect().getId() + ".xml"); 147 if (input == null) { 148 input = getClass().getResourceAsStream("/" + StringUtils.replace(mapperClass.getName(), ".", "/") + ".xml"); 149 } 150 return input; 151 } 152 153 private void loadAlias(Configuration conf, String alias, Class dtoClass) { 154 conf.getTypeAliasRegistry().registerAlias(alias, dtoClass); 155 } 156 157 private static JdbcTransactionFactory createTransactionFactory() { 158 return new JdbcTransactionFactory(); 159 } 160 161 }