001/* 002 * #%L 003 * Netarchivesuite - harvester 004 * %% 005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library, 006 * the National Library of France and the Austrian National Library. 007 * %% 008 * This program is free software: you can redistribute it and/or modify 009 * it under the terms of the GNU Lesser General Public License as 010 * published by the Free Software Foundation, either version 2.1 of the 011 * License, or (at your option) any later version. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Lesser Public License for more details. 017 * 018 * You should have received a copy of the GNU General Lesser Public 019 * License along with this program. If not, see 020 * <http://www.gnu.org/licenses/lgpl-2.1.html>. 021 * #L% 022 */ 023package dk.netarkivet.harvester.datamodel; 024 025import java.sql.Connection; 026import java.sql.PreparedStatement; 027import java.sql.ResultSet; 028import java.sql.SQLException; 029import java.util.ArrayList; 030import java.util.Iterator; 031 032import dk.netarkivet.common.exceptions.ArgumentNotValid; 033import dk.netarkivet.common.exceptions.IOFailure; 034import dk.netarkivet.common.exceptions.IllegalState; 035import dk.netarkivet.common.exceptions.PermissionDenied; 036import dk.netarkivet.common.exceptions.UnknownID; 037 038/** 039 * Implementation class for the DAO handling the persistence of {@link HarvestChannel} instances. 040 * 041 * @author ngiraud 042 */ 043public class HarvestChannelDBDAO extends HarvestChannelDAO { 044 045 /** 046 * Create a new HarvestChannelDAO implemented using database. This constructor also tries to upgrade the jobs and 047 * jobs_configs tables in the current database. Throws an {@link IllegalState} exception, if default channels are 048 * missing in the DB. 049 */ 050 protected HarvestChannelDBDAO() { 051 Connection connection = HarvestDBConnection.get(); 052 try { 053 HarvesterDatabaseTables.checkVersion(connection, HarvesterDatabaseTables.HARVESTCHANNELS); 054 } finally { 055 HarvestDBConnection.release(connection); 056 } 057 058 /* 059 * String defaultSnapshotChannelName = Settings.get(HarvesterSettings.SNAPSHOT_HARVEST_CHANNEL_ID); if 060 * (defaultSnapshotChannelName != null && defaultSnapshotChannelName.length() > 0) { HarvestChannel 061 * harvestChannel = lookupName(defaultSnapshotChannelName); if (harvestChannel == null) { harvestChannel = new 062 * HarvestChannel(defaultSnapshotChannelName, true, true, "Default channel for focused harvest."); 063 * create(harvestChannel); } } 064 */ 065 066 if (!defaultFocusedChannelExists()) { 067 throw new IllegalState("No default harvest channel defined for focused jobs!"); 068 } 069 } 070 071 private static final String get_by_id_sql = "SELECT * FROM harvestchannel WHERE id=?"; 072 073 @Override 074 public HarvestChannel getById(final long id) throws ArgumentNotValid, UnknownID { 075 Connection connection = HarvestDBConnection.get(); 076 try { 077 PreparedStatement stm = connection.prepareStatement(get_by_id_sql); 078 stm.setLong(1, id); 079 ResultSet rs = stm.executeQuery(); 080 if (!rs.next()) { 081 throw new UnknownID("No harvestchannel with id " + id); 082 } 083 return buildFromResultSet(rs); 084 } catch (SQLException e) { 085 throw new UnknownID("Failed to get harvestchannel with id " + id, e); 086 } finally { 087 HarvestDBConnection.release(connection); 088 } 089 } 090 091 private static final String get_by_name_sql = "SELECT * FROM harvestchannel WHERE name=?"; 092 093 @Override 094 public HarvestChannel getByName(final String name) throws ArgumentNotValid, UnknownID { 095 ArgumentNotValid.checkNotNullOrEmpty(name, "name"); 096 /* 097 * if (HarvestChannel.SNAPSHOT.getName().equals(name)) { return HarvestChannel.SNAPSHOT; } 098 */ 099 Connection connection = HarvestDBConnection.get(); 100 try { 101 PreparedStatement stm = connection.prepareStatement(get_by_name_sql); 102 stm.setString(1, name); 103 ResultSet rs = stm.executeQuery(); 104 if (!rs.next()) { 105 throw new UnknownID("No harvestchannel with name '" + name + "'"); 106 } 107 108 return buildFromResultSet(rs); 109 } catch (SQLException e) { 110 throw new UnknownID("Failed to get harvestchannel with name '" + name + "'", e); 111 } finally { 112 HarvestDBConnection.release(connection); 113 } 114 } 115 116 /* 117 * private HarvestChannel lookupName(final String name) throws ArgumentNotValid, UnknownID { 118 * ArgumentNotValid.checkNotNullOrEmpty(name, "name"); HarvestChannel harvestChannel = null; Connection connection = 119 * HarvestDBConnection.get(); try { PreparedStatement stm = connection.prepareStatement( get_by_name_sql); 120 * stm.setString(1, name); ResultSet rs = stm.executeQuery(); if (rs.next()) { harvestChannel = 121 * buildFromResultSet(rs); } } catch (SQLException e) { throw new 122 * UnknownID("Failed to get harvestchannel with name '" + name + "'", e); } finally { 123 * HarvestDBConnection.release(connection); } return harvestChannel; } 124 */ 125 126 private static final String create_sql = "INSERT INTO harvestchannel(name, issnapshot, isdefault, comments) VALUES (?, ?, ?, ?)"; 127 128 @Override 129 public void create(final HarvestChannel harvestChan) { 130 ArgumentNotValid.checkNotNull(harvestChan, "HarvestChannel harvestChan"); 131 /* 132 * if (HarvestChannel.SNAPSHOT.equals(harvestChan)) { throw new 133 * PermissionDenied("Cannot store SNAPSHOT channel!"); } 134 */ 135 Connection connection = HarvestDBConnection.get(); 136 try { 137 PreparedStatement stm = connection.prepareStatement(create_sql); 138 stm.setString(1, harvestChan.getName()); 139 stm.setBoolean(2, harvestChan.isSnapshot()); 140 stm.setBoolean(3, harvestChan.isDefault()); 141 stm.setString(4, harvestChan.getComments()); 142 if (stm.executeUpdate() < 1) { 143 throw new IOFailure("Failed to create harvestchannel '" + harvestChan.getName() + "'"); 144 } 145 } catch (SQLException e) { 146 throw new IOFailure("Failed to create harvestchannel '" + harvestChan.getName() + "'", e); 147 } finally { 148 HarvestDBConnection.release(connection); 149 } 150 } 151 152 private static final String update_sql = "UPDATE harvestchannel SET name=?, isDefault=?, comments=? WHERE id=?"; 153 154 @Override 155 public void update(HarvestChannel harvestChan) { 156 ArgumentNotValid.checkNotNull(harvestChan, "HarvestChannel harvestChan"); 157 if (harvestChan.isSnapshot()) { 158 throw new PermissionDenied("Cannot update SNAPSHOT channel!"); 159 } 160 Connection connection = HarvestDBConnection.get(); 161 try { 162 PreparedStatement stm = connection.prepareStatement(update_sql); 163 stm.setString(1, harvestChan.getName()); 164 stm.setBoolean(2, harvestChan.isDefault()); 165 stm.setString(3, harvestChan.getComments()); 166 stm.setLong(4, harvestChan.getId()); 167 if (stm.executeUpdate() != 1) { 168 throw new IOFailure("Failed to update harvestchannel with id " + harvestChan.getId()); 169 } 170 } catch (SQLException e) { 171 throw new IOFailure("Failed to update harvestchannel with id " + harvestChan.getId(), e); 172 } finally { 173 HarvestDBConnection.release(connection); 174 } 175 } 176 177 @Override 178 public Iterator<HarvestChannel> iterator() { 179 return getAll(true); 180 } 181 182 private static final String get_all_sql = "SELECT * FROM harvestchannel ORDER BY name"; 183 184 @Override 185 public Iterator<HarvestChannel> getAll(final boolean includeSnapshot) { 186 Connection connection = HarvestDBConnection.get(); 187 try { 188 PreparedStatement stm = connection.prepareStatement(get_all_sql); 189 ResultSet rs = stm.executeQuery(); 190 ArrayList<HarvestChannel> channelList = new ArrayList<HarvestChannel>(); 191 while (rs.next()) { 192 boolean isSnapshot = rs.getBoolean("issnapshot"); 193 if (!isSnapshot || includeSnapshot) { 194 channelList.add(new HarvestChannel(rs.getLong("id"), rs.getString("name"), isSnapshot, rs 195 .getBoolean("isdefault"), rs.getString("comments"))); 196 } 197 } 198 return channelList.iterator(); 199 } catch (SQLException e) { 200 throw new IOFailure("Failed to get harvest channels", e); 201 } finally { 202 HarvestDBConnection.release(connection); 203 } 204 } 205 206 private static final String get_default_focused_channel_exists_sql = "SELECT * FROM harvestchannel WHERE issnapshot = true AND isdefault=true"; 207 208 @Override 209 public boolean defaultFocusedChannelExists() { 210 Connection connection = HarvestDBConnection.get(); 211 try { 212 PreparedStatement stm = connection.prepareStatement(get_default_focused_channel_exists_sql); 213 ResultSet rs = stm.executeQuery(); 214 return rs.next(); 215 } catch (SQLException e) { 216 throw new IOFailure("Failed to get default harvest channel for focused jobs", e); 217 } finally { 218 HarvestDBConnection.release(connection); 219 } 220 } 221 222 private static final String get_default_channel_sql = "SELECT * FROM harvestchannel WHERE issnapshot = ? AND isdefault=true"; 223 224 @Override 225 public HarvestChannel getDefaultChannel(boolean isSnapshot) { 226 Connection connection = HarvestDBConnection.get(); 227 try { 228 PreparedStatement stm = connection.prepareStatement(get_default_channel_sql); 229 stm.setBoolean(1, isSnapshot); 230 ResultSet rs = stm.executeQuery(); 231 if (!rs.next()) { 232 throw new IOFailure("No default harvest channel for snapshot=" + isSnapshot); 233 } 234 return buildFromResultSet(rs); 235 } catch (SQLException e) { 236 throw new IOFailure("Failed to get default harvest channel for snapshot=" + isSnapshot, e); 237 } finally { 238 HarvestDBConnection.release(connection); 239 } 240 } 241 242 private static final String get_channel_for_hd_sql; 243 244 static { 245 get_channel_for_hd_sql = "SELECT * FROM harvestchannel C, harvestdefinitions D " 246 + "WHERE D.channel_id=C.id AND D.harvest_id=?"; 247 } 248 249 @Override 250 public HarvestChannel getChannelForHarvestDefinition(long harvestDefinitionId) { 251 Connection connection = HarvestDBConnection.get(); 252 try { 253 PreparedStatement stm = connection.prepareStatement(get_channel_for_hd_sql); 254 stm.setLong(1, harvestDefinitionId); 255 ResultSet rs = stm.executeQuery(); 256 if (!rs.next()) { 257 return null; 258 } 259 return buildFromResultSet(rs); 260 } catch (SQLException e) { 261 throw new IOFailure("Failed to find harvestdefinition-channel association", e); 262 } finally { 263 HarvestDBConnection.release(connection); 264 } 265 } 266 267 private HarvestChannel buildFromResultSet(ResultSet rs) throws SQLException { 268 return new HarvestChannel(rs.getLong("id"), rs.getString("name"), rs.getBoolean("issnapshot"), 269 rs.getBoolean("isdefault"), rs.getString("comments")); 270 } 271 272}