franta-hg@146: /** franta-hg@146: * SQL-DK franta-hg@146: * Copyright © 2014 František Kučera (frantovo.cz) franta-hg@146: * franta-hg@146: * This program is free software: you can redistribute it and/or modify franta-hg@146: * it under the terms of the GNU General Public License as published by franta-hg@250: * the Free Software Foundation, version 3 of the License. franta-hg@146: * franta-hg@146: * This program is distributed in the hope that it will be useful, franta-hg@146: * but WITHOUT ANY WARRANTY; without even the implied warranty of franta-hg@146: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the franta-hg@146: * GNU General Public License for more details. franta-hg@146: * franta-hg@146: * You should have received a copy of the GNU General Public License franta-hg@146: * along with this program. If not, see . franta-hg@146: */ franta-hg@146: package info.globalcode.sql.dk.batch; franta-hg@146: franta-hg@146: import info.globalcode.sql.dk.Parameter; franta-hg@146: import info.globalcode.sql.dk.SQLCommand; franta-hg@146: import info.globalcode.sql.dk.SQLCommandNumbered; franta-hg@146: import java.io.DataInputStream; franta-hg@146: import java.io.InputStream; franta-hg@146: import static info.globalcode.sql.dk.batch.BatchConstants.*; franta-hg@146: import static info.globalcode.sql.dk.Functions.toHex; franta-hg@146: import info.globalcode.sql.dk.SQLType; franta-hg@146: import java.io.IOException; franta-hg@146: import java.util.ArrayList; franta-hg@146: import java.util.Arrays; franta-hg@146: import java.util.List; franta-hg@146: franta-hg@146: /** franta-hg@146: * franta-hg@146: * @author Ing. František Kučera (frantovo.cz) franta-hg@146: */ franta-hg@146: public class BatchDecoder { franta-hg@146: franta-hg@146: public Batch decode(InputStream in) throws BatchException { franta-hg@146: return new BatchFromStream(new DataInputStream(in)); franta-hg@146: } franta-hg@146: franta-hg@146: private class BatchFromStream implements Batch { franta-hg@146: franta-hg@146: private DataInputStream in; franta-hg@146: private boolean hasNext; franta-hg@146: franta-hg@146: public BatchFromStream(DataInputStream in) throws BatchException { franta-hg@146: this.in = in; franta-hg@146: hasNext = verifyHeader(); franta-hg@146: } franta-hg@146: franta-hg@146: @Override franta-hg@146: public boolean hasNext() throws BatchException { franta-hg@146: return hasNext; franta-hg@146: } franta-hg@146: franta-hg@146: @Override franta-hg@146: public SQLCommand next() throws BatchException { franta-hg@146: try { franta-hg@146: String sql = readNextString(); franta-hg@146: franta-hg@146: int paramCount = in.readInt(); franta-hg@146: List parameters = new ArrayList<>(paramCount); franta-hg@146: franta-hg@146: for (int i = 0; i < paramCount; i++) { franta-hg@146: SQLType type = SQLType.valueOf(in.readInt()); franta-hg@146: String value = readNextString(); franta-hg@146: parameters.add(new Parameter(value, type)); franta-hg@146: } franta-hg@146: franta-hg@146: hasNext = verifyHeader(); franta-hg@146: franta-hg@146: SQLCommand sqlCommand = new SQLCommandNumbered(sql, parameters); franta-hg@146: return sqlCommand; franta-hg@146: } catch (IOException e) { franta-hg@146: throw new BatchException("Unable to read batch", e); franta-hg@146: } franta-hg@146: } franta-hg@146: franta-hg@146: private String readNextString() throws IOException { franta-hg@146: byte[] buffer = new byte[in.readInt()]; franta-hg@146: in.read(buffer); franta-hg@146: return new String(buffer, CHARSET); franta-hg@146: } franta-hg@146: franta-hg@146: /** franta-hg@146: * @return true if correct batch header was found | false if EOF was found franta-hg@146: * @throws BatchException if unexpected data was found (not batch header nor EOF) franta-hg@146: */ franta-hg@146: private boolean verifyHeader() throws BatchException { franta-hg@146: try { franta-hg@146: byte[] buffer = new byte[BATCH_HEADER.length]; franta-hg@146: int bytesRead = in.read(buffer); franta-hg@146: franta-hg@146: if (bytesRead == BATCH_HEADER.length && Arrays.equals(buffer, BATCH_HEADER)) { franta-hg@146: return true; franta-hg@146: } else if (bytesRead == -1) { franta-hg@146: return false; franta-hg@146: } else { franta-hg@146: throw new BatchException("This is not SQL-DK batch: " + toHex(buffer)); franta-hg@146: } franta-hg@146: } catch (IOException e) { franta-hg@146: throw new BatchException("Unable to read batch header", e); franta-hg@146: } franta-hg@146: } franta-hg@146: } franta-hg@146: }