001/* 002 * #%L 003 * Netarchivesuite - harvester 004 * %% 005 * Copyright (C) 2005 - 2018 The Royal Danish 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 */ 023 024package dk.netarkivet.harvester.datamodel; 025 026import java.io.Reader; 027import java.io.StringReader; 028import java.sql.Clob; 029import java.sql.Connection; 030import java.sql.PreparedStatement; 031import java.sql.ResultSet; 032import java.sql.SQLException; 033import java.util.Iterator; 034import java.util.List; 035 036import org.slf4j.Logger; 037import org.slf4j.LoggerFactory; 038 039import dk.netarkivet.common.exceptions.ArgumentNotValid; 040import dk.netarkivet.common.exceptions.IOFailure; 041import dk.netarkivet.common.exceptions.PermissionDenied; 042import dk.netarkivet.common.exceptions.UnknownID; 043import dk.netarkivet.common.utils.DBUtils; 044import dk.netarkivet.common.utils.ExceptionUtils; 045 046/** 047 * Implements the TemplateDAO with databases. 048 * <p> 049 * The statements to create the tables are now in scripts/sql/createfullhddb.sql 050 */ 051 052public class TemplateDBDAO extends TemplateDAO { 053 054 /** the log. */ 055 private static final Logger log = LoggerFactory.getLogger(TemplateDBDAO.class); 056 057 /** 058 * Default constructor. Only used by TemplateDAO,getInstance(). 059 */ 060 TemplateDBDAO() { 061 Connection connection = HarvestDBConnection.get(); 062 try { 063 HarvesterDatabaseTables.checkVersion(connection, HarvesterDatabaseTables.ORDERTEMPLATES); 064 } finally { 065 HarvestDBConnection.release(connection); 066 } 067 } 068 069 /** 070 * Read an XML order file for the named order XML. 071 * 072 * @param orderXmlName The name of the order.xml document 073 * @return The contents of this order.xml document 074 */ 075 public synchronized HeritrixTemplate read(String orderXmlName) { 076 ArgumentNotValid.checkNotNullOrEmpty(orderXmlName, "String orderXmlName"); 077 Connection c = HarvestDBConnection.get(); 078 PreparedStatement s = null; 079 log.debug("Reading template {} from database", orderXmlName); 080 try { 081 s = c.prepareStatement("SELECT template_id, orderxml, isActive FROM ordertemplates WHERE name = ?"); 082 s.setString(1, orderXmlName); 083 ResultSet res = s.executeQuery(); 084 if (!res.next()) { 085 throw new UnknownID("Can't find template " + orderXmlName); 086 } 087 Reader orderTemplateReader = null; 088 long template_id = res.getLong(1); 089 if (DBSpecifics.getInstance().supportsClob()) { 090 Clob clob = res.getClob(2); 091 orderTemplateReader = clob.getCharacterStream(); 092 } else { 093 String string = res.getString(2); 094 orderTemplateReader = new StringReader(string); 095 } 096 HeritrixTemplate heritrixTemplate = HeritrixTemplate.read(template_id, orderTemplateReader); 097 heritrixTemplate.setIsActive(res.getBoolean(3)); 098 return heritrixTemplate; 099 } catch (SQLException e) { 100 final String message = "SQL error finding order.xml for " + orderXmlName + "\n" 101 + ExceptionUtils.getSQLExceptionCause(e); 102 log.warn(message, e); 103 throw new IOFailure(message, e); 104 } 105 finally { 106 DBUtils.closeStatementIfOpen(s); 107 HarvestDBConnection.release(c); 108 } 109 } 110 111 /** 112 * Returns an iterator with all names of order.xml-templates. 113 * 114 * @return Iterator<String> with all names of templates (without .xml). 115 */ 116 public synchronized Iterator<String> getAll() { 117 Connection c = HarvestDBConnection.get(); 118 try { 119 List<String> names = DBUtils.selectStringList(c, "SELECT name FROM ordertemplates ORDER BY name"); 120 return names.iterator(); 121 } finally { 122 HarvestDBConnection.release(c); 123 } 124 } 125 126 @Override 127 public synchronized Iterator<String> getAll(boolean active) { 128 Connection c = HarvestDBConnection.get(); 129 try { 130 List<String> names = DBUtils.selectStringList(c, "SELECT name FROM ordertemplates WHERE isActive=? ORDER BY name ", active); 131 return names.iterator(); 132 } finally { 133 HarvestDBConnection.release(c); 134 } 135 } 136 137 /** 138 * Return true if the database contains a template with the given name. 139 * 140 * @param orderXmlName Name of an order.xml template (without .xml). 141 * @return True if such a template exists. 142 * @throws ArgumentNotValid If the orderXmlName is null or an empty String 143 */ 144 public synchronized boolean exists(String orderXmlName) { 145 ArgumentNotValid.checkNotNullOrEmpty(orderXmlName, "String orderXmlName"); 146 147 Connection c = HarvestDBConnection.get(); 148 try { 149 return exists(c, orderXmlName); 150 } finally { 151 HarvestDBConnection.release(c); 152 } 153 } 154 155 /** 156 * Return true if the database contains a template with the given name. 157 * 158 * @param orderXmlName Name of an order.xml template (without .xml). 159 * @return True if such a template exists. 160 * @throws ArgumentNotValid If the orderXmlName is null or an empty String 161 */ 162 private synchronized boolean exists(Connection c, String orderXmlName) { 163 int count = DBUtils.selectIntValue(c, "SELECT COUNT(*) FROM ordertemplates WHERE name = ?", orderXmlName); 164 return count == 1; 165 } 166 167 /** 168 * Create a template. The template must not already exist. 169 * 170 * @param orderXmlName Name of the template. 171 * @param orderXml XML documents that is a Heritrix order.xml template. 172 * @throws ArgumentNotValid If the orderXmlName is null or an empty String, or the orderXml is null. 173 */ 174 public synchronized void create(String orderXmlName, HeritrixTemplate orderXml) { 175 ArgumentNotValid.checkNotNullOrEmpty(orderXmlName, "String orderXmlName"); 176 ArgumentNotValid.checkNotNull(orderXml, "HeritrixTemplate orderXml"); 177 178 Connection c = HarvestDBConnection.get(); 179 PreparedStatement s = null; 180 try { 181 if (exists(c, orderXmlName)) { 182 throw new PermissionDenied("An order template called " + orderXmlName + " already exists"); 183 } 184 185 s = c.prepareStatement("INSERT INTO ordertemplates " + "( name, orderxml, isActive ) VALUES ( ?, ?, ? )"); 186 DBUtils.setStringMaxLength(s, 1, orderXmlName, Constants.MAX_NAME_SIZE, orderXmlName, "length"); 187 DBUtils.setClobMaxLength(s, 2, orderXml.getXML(), Constants.MAX_ORDERXML_SIZE, "size", orderXmlName); 188 s.setBoolean(3, orderXml.isActive()); 189 s.executeUpdate(); 190 } catch (SQLException e) { 191 throw new IOFailure("SQL error creating template " + orderXmlName + "\n" 192 + ExceptionUtils.getSQLExceptionCause(e), e); 193 } finally { 194 HarvestDBConnection.release(c); 195 } 196 } 197 198 /** 199 * Update a template. The template must already exist. 200 * 201 * @param orderXmlName Name of the template. 202 * @param orderXml XML document that is a Heritrix order.xml template. 203 * @throws PermissionDenied If the template does not exist 204 * @throws IOFailure If the template could not be 205 * @throws ArgumentNotValid If the orderXmlName is null or an empty String, or the orderXml is null. 206 */ 207 public synchronized void update(String orderXmlName, HeritrixTemplate orderXml) { 208 ArgumentNotValid.checkNotNullOrEmpty(orderXmlName, "String orderXmlName"); 209 ArgumentNotValid.checkNotNull(orderXml, "HeritrixTemplate orderXml"); 210 211 Connection c = HarvestDBConnection.get(); 212 PreparedStatement s = null; 213 try { 214 if (!exists(c, orderXmlName)) { 215 throw new PermissionDenied("No order template called " + orderXmlName + " exists"); 216 } 217 218 s = c.prepareStatement("UPDATE ordertemplates SET orderxml = ?, isActive= ? WHERE name = ?"); 219 DBUtils.setClobMaxLength(s, 1, orderXml.getXML(), Constants.MAX_ORDERXML_SIZE, "size", orderXmlName); 220 s.setBoolean(2, orderXml.isActive()); 221 s.setString(3, orderXmlName); 222 s.executeUpdate(); 223 } catch (SQLException e) { 224 throw new IOFailure("SQL error updating template " + orderXmlName + "\n" 225 + ExceptionUtils.getSQLExceptionCause(e), e); 226 } finally { 227 HarvestDBConnection.release(c); 228 } 229 } 230 231}