001package fr.ifremer.adagio.synchro.intercept.internal; 002 003/* 004 * #%L 005 * SIH-Adagio :: Synchronization 006 * $Id:$ 007 * $HeadURL:$ 008 * %% 009 * Copyright (C) 2012 - 2014 Ifremer 010 * %% 011 * This program is free software: you can redistribute it and/or modify 012 * it under the terms of the GNU Affero General Public License as published by 013 * the Free Software Foundation, either version 3 of the License, or 014 * (at your option) any later version. 015 * 016 * This program is distributed in the hope that it will be useful, 017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 019 * GNU General Public License for more details. 020 * 021 * You should have received a copy of the GNU Affero General Public License 022 * along with this program. If not, see <http://www.gnu.org/licenses/>. 023 * #L% 024 */ 025 026import java.sql.SQLException; 027import java.sql.Types; 028import java.util.List; 029import java.util.Map; 030 031import oracle.sql.TIMESTAMP; 032 033import org.hibernate.dialect.Dialect; 034import org.hibernate.tool.hbm2ddl.ColumnMetadata; 035import org.hibernate.tool.hbm2ddl.TableMetadata; 036 037import com.google.common.base.Preconditions; 038import com.google.common.collect.Lists; 039import com.google.common.collect.Maps; 040 041import fr.ifremer.adagio.synchro.dao.SynchroTableDao; 042import fr.ifremer.adagio.synchro.intercept.SynchroInterceptorBase; 043import fr.ifremer.adagio.synchro.intercept.SynchroWriteBuffer; 044import fr.ifremer.adagio.synchro.meta.SynchroDatabaseMetadata; 045import fr.ifremer.adagio.synchro.meta.SynchroTableMetadata; 046import fr.ifremer.adagio.synchro.service.SynchroContext; 047 048/** 049 * Workaround need for Oracle timestamp serialization 050 * If ojdbc not found in classpath, do not try to cast to TIMESTAMP 051 * 052 * @author Benoit Lavenier <benoit.lavenier@e-is.pro> 053 * @since 054 * 055 */ 056public class OracleInterceptor extends SynchroInterceptorBase { 057 058 private Map<TableMetadata, int[]> columnIndexesByTable = Maps.newHashMap(); 059 060 private SynchroTableDao lastDao = null; 061 062 private int[] lastIndexes = null; 063 064 @Override 065 public boolean apply(SynchroDatabaseMetadata meta, TableMetadata table) { 066 boolean isOracleDialect = meta.getDialect().getClass().getName().contains("Oracle"); 067 if (!isOracleDialect) { 068 return false; 069 } 070 071 Map<String, ColumnMetadata> columns = SynchroTableMetadata.getColumns(table); 072 List<Integer> columnIndexesList = Lists.newArrayList(); 073 int index = 0; 074 for (ColumnMetadata column : columns.values()) { 075 if (column.getTypeCode() == Types.DATE 076 || column.getTypeCode() == Types.TIMESTAMP) { 077 columnIndexesList.add(index); 078 } 079 index++; 080 } 081 082 if (columnIndexesList.isEmpty()) { 083 return false; 084 } 085 086 int[] columnIndexes = getColumnIndexes(table); 087 if (columnIndexes == null) { 088 return false; 089 } 090 091 columnIndexesByTable.put(table, columnIndexes); 092 093 return true; 094 } 095 096 @Override 097 public boolean enableOnRead() { 098 return true; 099 } 100 101 @Override 102 protected String doCreateSelectQuery(SynchroTableMetadata table, String queryName, String sql) { 103 return sql; 104 } 105 106 @Override 107 protected void doOnRead(Object[] data, SynchroTableDao dao) throws SQLException { 108 if (dao != lastDao) { 109 lastIndexes = getColumnMapIndexes(dao); 110 lastDao = dao; 111 } 112 for (int index : lastIndexes) { 113 Object value = data[index]; 114 if (value != null && value instanceof TIMESTAMP) { 115 data[index] = ((TIMESTAMP) value).timestampValue(); 116 } 117 } 118 } 119 120 @Override 121 public boolean enableOnWrite() { 122 return true; 123 } 124 125 @Override 126 protected void doOnWrite(Object[] data, SynchroTableDao dao, SynchroWriteBuffer buffer) throws SQLException { 127 if (dao != lastDao) { 128 lastIndexes = getColumnMapIndexes(dao); 129 lastDao = dao; 130 } 131 for (int index : lastIndexes) { 132 Object value = data[index]; 133 if (value != null && value instanceof TIMESTAMP) { 134 data[index] = ((TIMESTAMP) value).timestampValue(); 135 } 136 } 137 } 138 139 protected int[] getColumnMapIndexes(SynchroTableDao dao) { 140 TableMetadata table = dao.getTable().getDelegate(); 141 int[] columnIndexes = columnIndexesByTable.get(table); 142 if (columnIndexes == null) { 143 columnIndexes = getColumnIndexes(table); 144 columnIndexesByTable.put(table, columnIndexes); 145 } 146 return columnIndexes; 147 } 148 149 protected int[] getColumnIndexes(TableMetadata table) { 150 Map<String, ColumnMetadata> columns = SynchroTableMetadata.getColumns(table); 151 if (columns == null) { 152 return null; 153 } 154 155 List<Integer> columnIndexesList = Lists.newArrayList(); 156 int index = 0; 157 for (ColumnMetadata column : columns.values()) { 158 if (column.getTypeCode() == Types.DATE 159 || column.getTypeCode() == Types.TIMESTAMP) { 160 columnIndexesList.add(index); 161 } 162 index++; 163 } 164 165 if (columnIndexesList.isEmpty()) { 166 return null; 167 } 168 169 int[] columnIndexes = new int[columnIndexesList.size()]; 170 index = 0; 171 for (Integer columnIndex : columnIndexesList) { 172 columnIndexes[index] = columnIndex; 173 } 174 175 return columnIndexes; 176 } 177}