package de.is24.infrastructure.gridfs.http.metadata.generation;
import de.is24.infrastructure.gridfs.http.domain.YumEntry;
import de.is24.infrastructure.gridfs.http.domain.yum.YumPackage;
import de.is24.infrastructure.gridfs.http.domain.yum.YumPackageDir;
import de.is24.infrastructure.gridfs.http.domain.yum.YumPackageFile;
import de.is24.infrastructure.gridfs.http.domain.yum.YumPackageFormatEntry;
import de.is24.infrastructure.gridfs.http.domain.yum.YumPackageRequirement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import static de.is24.infrastructure.gridfs.http.domain.yum.YumPackageFileType.DIR;
import static de.is24.infrastructure.gridfs.http.domain.yum.YumPackageFileType.FILE;
import static de.is24.infrastructure.gridfs.http.domain.yum.YumPackageFileType.GHOST;
import static java.util.stream.Collectors.toList;
import static org.apache.commons.lang.StringUtils.defaultIfBlank;
public class PrimaryDbGenerator extends DbGenerator {
public static final String OBSOLETES = "obsoletes";
public static final String CONFLICTS = "conflicts";
public static final String PROVIDES = "provides";
public static final String REQUIRES = "requires";
public PrimaryDbGenerator() {
super("primary");
}
@Override
protected Map<String, PreparedStatement> createPreparedStatements(Connection connection) throws SQLException {
Map<String, PreparedStatement> preparedStatements = new HashMap<>();
preparedStatements.put(PACKAGES,
connection.prepareStatement(
"insert into packages values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"));
preparedStatements.put(OBSOLETES, connection.prepareStatement("insert into obsoletes values (?, ?, ?, ?, ?, ?)"));
preparedStatements.put(CONFLICTS, connection.prepareStatement("insert into conflicts values (?, ?, ?, ?, ?, ?)"));
preparedStatements.put(PROVIDES, connection.prepareStatement("insert into provides values (?, ?, ?, ?, ?, ?)"));
preparedStatements.put(REQUIRES, connection.prepareStatement("insert into requires values (?, ?, ?, ?, ?, ?, ?)"));
preparedStatements.put(FILES, connection.prepareStatement("insert into files values (?, ?, ?)"));
return preparedStatements;
}
@Override
protected void writeEntry(Map<String, PreparedStatement> ps, int pkgKey, YumEntry entry) throws SQLException {
YumPackage p = entry.getYumPackage();
writePrimaryPackage(ps.get(PACKAGES), pkgKey, p);
writeDependency(ps.get(OBSOLETES), pkgKey, p.getPackageFormat().getObsoletes());
writeDependency(ps.get(PROVIDES), pkgKey, p.getPackageFormat().getProvides());
writeDependency(ps.get(CONFLICTS), pkgKey, p.getPackageFormat().getConflicts());
writeRequires(ps.get(REQUIRES), pkgKey, filterRequires(p.getPackageFormat().getRequires()));
PreparedStatement filesStatement = ps.get(FILES);
writePrimaryFiles(filesStatement, p, pkgKey, (YumPackageFile file) -> FILE.equals(file.getType()) && isPrimaryFileName(file));
writePrimaryFiles(filesStatement, p, pkgKey, (YumPackageFile file) -> DIR.equals(file.getType()) && isPrimaryDirName(file.getDir()));
writePrimaryFiles(filesStatement, p, pkgKey, (YumPackageFile file) -> GHOST.equals(file.getType()) && isPrimaryFileName(file));
}
private void writePrimaryPackage(PreparedStatement ps, int pkgKey, YumPackage p) throws SQLException {
int c = 1;
ps.setInt(c++, pkgKey);
ps.setString(c++, p.getChecksum().getChecksum());
ps.setString(c++, p.getName());
ps.setString(c++, p.getArch());
ps.setString(c++, p.getVersion().getVer());
ps.setInt(c++, p.getVersion().getEpoch());
ps.setString(c++, p.getVersion().getRel());
ps.setString(c++, trim(p.getSummary()));
ps.setString(c++, trim(p.getDescription()));
ps.setString(c++, defaultIfBlank(p.getUrl(), null));
ps.setInt(c++, p.getTime().getFile());
ps.setInt(c++, p.getTime().getBuild());
ps.setString(c++, emptyIfBlank(p.getPackageFormat().getLicense()));
ps.setString(c++, emptyIfBlank(p.getPackageFormat().getVendor()));
ps.setString(c++, emptyIfBlank(p.getPackageFormat().getGroup()));
ps.setString(c++, emptyIfBlank(p.getPackageFormat().getBuildHost()));
ps.setString(c++, emptyIfBlank(p.getPackageFormat().getSourceRpm()));
ps.setInt(c++, p.getPackageFormat().getHeaderStart());
ps.setInt(c++, p.getPackageFormat().getHeaderEnd());
ps.setString(c++, nullIfBlank(p.getPackager()));
ps.setInt(c++, p.getSize().getPackaged());
ps.setInt(c++, p.getSize().getInstalled());
ps.setInt(c++, p.getSize().getArchive());
ps.setString(c++, p.getLocation().getHref());
ps.setString(c++, null);
ps.setString(c, p.getChecksum().getType());
ps.executeUpdate();
}
private void writeDependency(PreparedStatement ps, int pkgKey, List<YumPackageFormatEntry> dependencies)
throws SQLException {
for (YumPackageFormatEntry dependency : dependencies) {
int c = fillStatementForYumPackageFormatEntry(ps, dependency, 1);
ps.setInt(c, pkgKey);
ps.addBatch();
}
if (!dependencies.isEmpty()) {
ps.executeBatch();
}
}
private static int fillStatementForYumPackageFormatEntry(final PreparedStatement ps,
final YumPackageFormatEntry dependency, int startCount)
throws SQLException {
int counter = startCount;
ps.setString(counter++, dependency.getName());
if (dependency.getFlags() == null) {
ps.setString(counter++, null);
ps.setString(counter++, null);
ps.setString(counter++, null);
ps.setString(counter++, null);
} else {
ps.setString(counter++, dependency.getFlags());
ps.setInt(counter++, dependency.getVersion().getEpoch());
ps.setString(counter++, nullIfBlank(dependency.getVersion().getVer()));
ps.setString(counter++, nullIfBlank(dependency.getVersion().getRel()));
}
return counter;
}
private void writeRequires(PreparedStatement ps, int pkgKey, List<YumPackageRequirement> dependencies)
throws SQLException {
for (YumPackageRequirement dependency : dependencies) {
int c = fillStatementForYumPackageFormatEntry(ps, dependency, 1);
ps.setInt(c++, pkgKey);
ps.setString(c, dependency.isPre().toString().toUpperCase());
ps.addBatch();
}
if (!dependencies.isEmpty()) {
ps.executeBatch();
}
}
private List<YumPackageRequirement> filterRequires(List<YumPackageRequirement> requires) {
return requires.stream().filter((YumPackageRequirement requirement) -> !requirement.getName().startsWith("rpmlib(")).collect(toList());
}
private void writePrimaryFiles(PreparedStatement ps, YumPackage yumPackage, int pkgKey,
Predicate<YumPackageFile> predicate) throws SQLException {
int counter = 0;
for (YumPackageDir dir : yumPackage.getPackageDirs()) {
for (YumPackageFile file : dir.getFiles().stream().filter(predicate).collect(toList())) {
ps.setString(1, file.getDir() + file.getName());
ps.setString(2, file.getType().toString().toLowerCase());
ps.setInt(3, pkgKey);
ps.addBatch();
counter++;
}
}
if (counter > 0) {
ps.executeBatch();
}
}
public static boolean isPrimaryDirName(String dir) {
return dir.contains("bin/") || dir.startsWith("/etc/");
}
private static boolean isPrimaryFileName(YumPackageFile file) {
return isPrimaryDirName(file.getDir()) || "/usr/lib/sendmail".equals(file.getDir() + file.getName());
}
}