/* * 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.code.Nullable; 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.io.File; import java.io.IOException; import java.io.PrintWriter; import java.io.Reader; import java.util.List; /** * XML Exporter */ public class DataExporterXML extends StreamExporterAbstract { private PrintWriter out; private List<DBDAttributeBinding> columns; private String tableName; @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("<?xml version=\"1.0\" ?>\n"); tableName = escapeXmlElementName(getSite().getSource().getName()); out.write("<!DOCTYPE " + tableName + " [\n"); out.write(" <!ELEMENT " + tableName + " (DATA_RECORD*)>\n"); out.write(" <!ELEMENT DATA_RECORD ("); int columnsSize = columns.size(); for (int i = 0; i < columnsSize; i++) { String colName = columns.get(i).getLabel(); if (CommonUtils.isEmpty(colName)) { colName = columns.get(i).getName(); } out.write(escapeXmlElementName(colName) + "?"); if (i < columnsSize - 1) { out.write(","); } } out.write(")+>\n"); for (int i = 0; i < columnsSize; i++) { out.write(" <!ELEMENT " + escapeXmlElementName(columns.get(i).getName()) + " (#PCDATA)>\n"); } out.write("]>\n"); out.write("<" + tableName + ">\n"); } @Override public void exportRow(DBCSession session, Object[] row) throws DBException, IOException { out.write(" <DATA_RECORD>\n"); for (int i = 0; i < row.length; i++) { DBDAttributeBinding column = columns.get(i); String columnName = escapeXmlElementName(column.getName()); out.write(" <" + columnName + ">"); if (DBUtils.isNullValue(row[i])) { writeTextCell(null); } 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()); if (cs != null) { if (ContentUtils.isTextContent(content)) { try (Reader reader = cs.getContentReader()) { writeCellValue(reader); } } else { getSite().writeBinaryData(cs); } } } finally { content.release(); } } else { writeTextCell(super.getValueDisplayString(column, row[i])); } out.write("</" + columnName + ">\n"); } out.write(" </DATA_RECORD>\n"); } @Override public void exportFooter(DBRProgressMonitor monitor) throws IOException { out.write("</" + tableName + ">\n"); } private void writeTextCell(@Nullable String value) { if (value != null) { value = value.replace("<", "<").replace(">", ">").replace("&", "&"); out.write(value); } } private void writeImageCell(File file) throws DBException { if (file != null && file.exists()) { 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)); out.write(imagePath); } } } private void writeCellValue(Reader reader) throws IOException { // 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(">"); } else if (buffer[i] == '&') { out.write("&"); } else { out.write(buffer[i]); } } } } private String escapeXmlElementName(String name) { return name.replaceAll("[^\\p{Alpha}\\p{Digit}]+","_"); } }