/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2012 Eugene Fradkin (eugene.fradkin@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.jkiss.dbeaver.tools.transfer.stream.impl;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.data.DBDAttributeBinding;
import org.jkiss.dbeaver.model.data.DBDContent;
import org.jkiss.dbeaver.model.data.DBDContentStorage;
import org.jkiss.dbeaver.model.exec.DBCSession;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.tools.transfer.stream.IStreamDataExporterSite;
import org.jkiss.dbeaver.utils.ContentUtils;
import org.jkiss.utils.CommonUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.List;
/**
* HTML Exporter
*/
public class DataExporterHTML extends StreamExporterAbstract {
private static final int IMAGE_FRAME_SIZE = 200;
private PrintWriter out;
private List<DBDAttributeBinding> columns;
private int rowCount = 0;
@Override
public void init(IStreamDataExporterSite site) throws DBException
{
super.init(site);
out = site.getWriter();
}
@Override
public void dispose()
{
out = null;
super.dispose();
}
@Override
public void exportHeader(DBCSession session) throws DBException, IOException
{
columns = getSite().getAttributes();
printHeader();
}
private void printHeader()
{
out.write("<html>");
out.write("<head><style>" +
"table {font-family:\"Lucida Sans Unicode\", \"Lucida Grande\", Sans-Serif;font-size:12px;text-align:left;border-collapse:collapse;margin:10px;} " +
"th{font-size:14px;font-weight:normal;color:#039;padding:10px 8px;} " +
"td{color:#669;padding:8px;}" +
".odd{background:#e8edff;}" +
"img{padding:5px; border:solid; border-color: #dddddd #aaaaaa #aaaaaa #dddddd; border-width: 1px 2px 2px 1px; background-color:white;}" +
"</style></head>");
out.write("<body><table>");
out.write("<tr>");
for (int i = 0, columnsSize = columns.size(); i < columnsSize; i++) {
String colName = columns.get(i).getLabel();
if (CommonUtils.isEmpty(colName)) {
colName = columns.get(i).getName();
}
writeTextCell(colName, true);
}
out.write("</tr>");
}
@Override
public void exportRow(DBCSession session, Object[] row) throws DBException, IOException
{
out.write("<tr" + (rowCount++ % 2 == 0 ? " class=\"odd\"" : "") + ">");
for (int i = 0; i < row.length; i++) {
DBDAttributeBinding column = columns.get(i);
if (DBUtils.isNullValue(row[i])) {
writeTextCell(null, false);
} else if (row[i] instanceof DBDContent) {
// Content
// Inline textual content and handle binaries in some special way
DBDContent content = (DBDContent)row[i];
try {
DBDContentStorage cs = content.getContents(session.getProgressMonitor());
out.write("<td>");
if (cs != null) {
if (ContentUtils.isTextContent(content)) {
writeCellValue(cs.getContentReader());
} else {
getSite().writeBinaryData(cs);
}
}
out.write("</td>");
}
finally {
content.release();
}
} else {
String stringValue = super.getValueDisplayString(column, row[i]);
boolean isImage = row[i] instanceof File && stringValue != null && stringValue.endsWith(".jpg");
if (isImage) {
writeImageCell((File) row[i]);
}
else {
writeTextCell(stringValue, false);
}
}
}
out.write("</tr>\n");
}
@Override
public void exportFooter(DBRProgressMonitor monitor) throws IOException
{
out.write("</table></body></html>");
}
private void writeTextCell(String value, boolean header)
{
out.write(header ? "<th>" : "<td>");
if (value == null) {
out.write(" ");
}
else {
value = value.replace("<", "<").replace(">", ">").replace("&", "&");
out.write(value);
}
out.write(header ? "</th>" : "</td>");
}
private void writeImageCell(File file) throws DBException
{
out.write("<td>");
if (file == null || !file.exists()) {
out.write(" ");
}
else {
Image image = null;
try {
image = ImageIO.read(file);
} catch (IOException e) {
throw new DBException("Can't read an exported image " + image, e);
}
if (image != null) {
String imagePath = file.getAbsolutePath();
imagePath = "files/" + imagePath.substring(imagePath.lastIndexOf(File.separator));
int width = ((BufferedImage) image).getWidth();
int height = ((BufferedImage) image).getHeight();
int rwidth = width;
int rheight = height;
if (width > IMAGE_FRAME_SIZE || height > IMAGE_FRAME_SIZE) {
float scale = 1;
if (width > height) {
scale = IMAGE_FRAME_SIZE /(float)width;
}
else {
scale = IMAGE_FRAME_SIZE /(float)height;
}
rwidth = (int) (rwidth * scale);
rheight = (int) (rheight * scale);
}
out.write("<a href=\"" + imagePath + "\">");
out.write("<img src=\"" + imagePath + "\" width=\"" + rwidth + "\" height=\"" + rheight + "\" />");
out.write("</a>");
}
else {
out.write(" ");
}
}
out.write("</td>");
}
private void writeCellValue(Reader reader) throws IOException
{
try {
// Copy reader
char buffer[] = new char[2000];
for (;;) {
int count = reader.read(buffer);
if (count <= 0) {
break;
}
for (int i = 0; i < count; i++) {
if (buffer[i] == '<') {
out.write("<");
}
else if (buffer[i] == '>') {
out.write(">");
}
if (buffer[i] == '&') {
out.write("&");
}
out.write(buffer[i]);
}
}
} finally {
ContentUtils.close(reader);
}
}
public boolean saveBinariesAsImages()
{
return true;
}
}