/*
* Zed Attack Proxy (ZAP) and its related class files.
*
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
*
* Copyright 2010 psiinon@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.parosproxy.paros.db.paros;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.parosproxy.paros.db.DatabaseException;
import org.parosproxy.paros.db.DbUtils;
import org.parosproxy.paros.db.RecordStructure;
import org.parosproxy.paros.db.TableStructure;
public class ParosTableStructure extends ParosAbstractTable implements TableStructure {
private static final String TABLE_NAME = "STRUCTURE";
private static final String STRUCTUREID = "STRUCTUREID";
private static final String SESSIONID = "SESSIONID";
private static final String PARENTID = "PARENTID";
private static final String HISTORYID = "HISTORYID";
private static final String NAME = "NAME";
private static final String NAMEHASH = "NAMEHASH";
private static final String URL = "URL";
private static final String METHOD = "METHOD";
private PreparedStatement psRead = null;
private PreparedStatement psFind = null;
private PreparedStatement psInsert = null;
private CallableStatement psGetIdLastInsert = null;
private PreparedStatement psGetChildren = null;
private PreparedStatement psGetChildCount = null;
public ParosTableStructure() {
}
/*
* public RecordStructure(long structureId, long parentId, int historyId, String url) {
*/
@Override
protected void reconnect(Connection conn) throws DatabaseException {
try {
if (!DbUtils.hasTable(conn, TABLE_NAME)) {
// Need to create the table
DbUtils.executeAndClose(
conn.prepareStatement("CREATE cached TABLE STRUCTURE (STRUCTUREID bigint generated by default as identity (start with 1), " +
"SESSIONID bigint not null, PARENTID bigint not null, HISTORYID int, " +
"NAME varchar(8192) not null, NAMEHASH bigint not null, " +
"URL varchar(8192) not null, METHOD varchar(10) not null)"));
}
psRead = conn.prepareStatement("SELECT * FROM STRUCTURE WHERE SESSIONID = ? AND STRUCTUREID = ?");
psFind = conn.prepareStatement("SELECT * FROM STRUCTURE WHERE SESSIONID = ? AND NAMEHASH = ? AND METHOD = ?");
psInsert = conn.prepareStatement("INSERT INTO STRUCTURE (SESSIONID, PARENTID, HISTORYID, NAME, NAMEHASH, URL, METHOD) VALUES (?, ?, ?, ?, ?, ?, ?)");
psGetIdLastInsert = conn.prepareCall("CALL IDENTITY();");
psGetChildren = conn.prepareStatement("SELECT * FROM STRUCTURE WHERE SESSIONID = ? AND PARENTID = ?");
psGetChildCount = conn.prepareStatement("SELECT COUNT(*) FROM STRUCTURE WHERE SESSIONID = ? AND PARENTID = ?");
} catch (SQLException e) {
throw new DatabaseException(e);
}
}
/* (non-Javadoc)
* @see org.parosproxy.paros.db.paros.TableParam#read(long)
*/
@Override
public synchronized RecordStructure read(long sessionId, long urlId) throws DatabaseException {
try {
psRead.setLong(1, sessionId);
psRead.setLong(2, urlId);
try (ResultSet rs = psRead.executeQuery()) {
RecordStructure result = build(rs);
return result;
}
} catch (SQLException e) {
throw new DatabaseException(e);
}
}
@Override
public RecordStructure insert(long sessionId, long parentId, int historyId, String name, String url, String method) throws DatabaseException {
try {
psInsert.setLong(1, sessionId);
psInsert.setLong(2, parentId);
psInsert.setInt(3, historyId);
psInsert.setString(4, name);
psInsert.setInt(5, name.hashCode());
psInsert.setString(6, url);
psInsert.setString(7, method);
psInsert.executeUpdate();
long id;
try (ResultSet rs = psGetIdLastInsert.executeQuery()) {
rs.next();
id = rs.getLong(1);
}
return read(sessionId, id);
} catch (SQLException e) {
throw new DatabaseException(e);
}
}
@Override
public RecordStructure find(long sessionId, String name, String method) throws DatabaseException {
try {
psFind.setLong(1, sessionId);
psFind.setInt(2, name.hashCode());
psFind.setString(3, method);
try (ResultSet rs = psFind.executeQuery()) {
while (rs.next()) {
// We can get multiple records back due to hash collisions,
// so double check the actual URL
if (name.equals(rs.getString(NAME))) {
return build(rs);
}
}
}
} catch (SQLException e) {
throw new DatabaseException(e);
}
return null;
}
@Override
public List<RecordStructure> getChildren(long sessionId, long parentId)
throws DatabaseException {
try {
psGetChildren.setLong(1, sessionId);
psGetChildren.setLong(2, parentId);
List<RecordStructure> result = new ArrayList<>();
try (ResultSet rs = psGetChildren.executeQuery()) {
while (rs.next()) {
result.add(build(rs));
}
}
return result;
} catch (SQLException e) {
throw new DatabaseException(e);
}
}
@Override
public long getChildCount(long sessionId, long parentId) throws DatabaseException {
try {
psGetChildCount.setLong(1, sessionId);
psGetChildCount.setLong(2, parentId);
try (ResultSet rs = psGetChildCount.executeQuery()) {
if (rs.next()) {
return rs.getLong(1);
}
}
return 0;
} catch (SQLException e) {
throw new DatabaseException(e);
}
}
@Override
public void deleteLeaf(long sessionId, long structureId) throws DatabaseException {
// TODO Implement
}
@Override
public void deleteSubtree(long sessionId, long structureId) throws DatabaseException {
// TODO Implement
}
private RecordStructure build(ResultSet rs) throws DatabaseException {
try {
RecordStructure rt = null;
if (rs.next()) {
rt = new RecordStructure(rs.getLong(SESSIONID), rs.getLong(STRUCTUREID), rs.getLong(PARENTID), rs.getInt(HISTORYID),
rs.getString(NAME), rs.getString(URL), rs.getString(METHOD));
}
return rt;
} catch (SQLException e) {
throw new DatabaseException(e);
}
}
}