Skip to content

Commit

Permalink
correcting invalid characters in remarks
Browse files Browse the repository at this point in the history
  • Loading branch information
Wisser committed Apr 25, 2024
1 parent 361f8b5 commit ef89a91
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,7 @@
<Component class="javax.swing.JComboBox" name="schemaComboBox">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="4">
<StringItem index="0" value="Item 1"/>
<StringItem index="1" value="Item 2"/>
<StringItem index="2" value="Item 3"/>
<StringItem index="3" value="Item 4"/>
</StringArray>
<StringArray count="0"/>
</Property>
</Properties>
<AuxValues>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,24 @@
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
Expand All @@ -43,8 +49,15 @@
import javax.swing.WindowConstants;

import org.fife.rsta.ui.EscapableDialog;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.yaml.snakeyaml.representer.Representer;
import org.yaml.snakeyaml.resolver.Resolver;

import liquibase.CatalogAndSchema;
import liquibase.GlobalConfiguration;
import liquibase.LabelExpression;
import liquibase.Liquibase;
import liquibase.change.Change;
Expand All @@ -71,8 +84,6 @@
import liquibase.database.DatabaseConnection;
import liquibase.database.DatabaseFactory;
import liquibase.database.OfflineConnection;
import liquibase.database.core.MSSQLDatabase;
import liquibase.database.core.MockDatabase;
import liquibase.database.jvm.JdbcConnection;
import liquibase.diff.DiffGeneratorFactory;
import liquibase.diff.DiffResult;
Expand All @@ -83,6 +94,7 @@
import liquibase.exception.DatabaseException;
import liquibase.exception.LiquibaseException;
import liquibase.exception.UnexpectedLiquibaseException;
import liquibase.parser.core.yaml.YamlSnapshotParser;
import liquibase.resource.FileSystemResourceAccessor;
import liquibase.snapshot.DatabaseSnapshot;
import liquibase.snapshot.EmptyDatabaseSnapshot;
Expand All @@ -95,6 +107,7 @@
import liquibase.structure.core.Index;
import liquibase.structure.core.PrimaryKey;
import liquibase.structure.core.UniqueConstraint;
import liquibase.util.SnakeYamlUtil;
import liquibase.util.StringUtil;
import net.sf.jailer.ExecutionContext;
import net.sf.jailer.JailerVersion;
Expand Down Expand Up @@ -145,6 +158,7 @@ public DDLScriptGeneratorPanel() {
UIUtil.setTrailingComponent(scriptFileTextField, fileFindButton);
}

@SuppressWarnings("rawtypes")
private void initTargetDBMS(Session session) {
DefaultComboBoxModel<DBMS> aModel = new DefaultComboBoxModel<DBMS>(DBMS.values());
DBMS sourceDBMS = session.dbms;
Expand All @@ -155,10 +169,10 @@ private void initTargetDBMS(Session session) {
dbmsComboBox.setRenderer(new DefaultListCellRenderer() {
ListCellRenderer renderer = dbmsComboBox.getRenderer();

@SuppressWarnings("rawtypes")
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
@SuppressWarnings({ "unchecked" })
Component render = renderer.getListCellRendererComponent(list,
value instanceof DBMS ? ((DBMS) value).getDisplayName() : value, index, isSelected,
cellHasFocus);
Expand Down Expand Up @@ -288,7 +302,7 @@ private boolean doGenerate(String fileName, AtomicBoolean isCancelled) {
Liquibase liquibase = null;
String dbmsName = null;
File baseDir = Configuration.getInstance().createTempFile();
File changeLogFile = new File(baseDir.getPath() + ".json");
File changeLogFile = new File(baseDir.getPath() + ".yaml");
File databaseChangeLogFile = new File(baseDir.getPath() + ".csv");
FileSystemResourceAccessor resourceAccessor = new FileSystemResourceAccessor(baseDir.getParent());
String shortName;
Expand Down Expand Up @@ -359,6 +373,7 @@ public boolean supports(Database database) {
}

if (createRadioButton.isSelected() || createAndDropRadioButton.isSelected()) {
checkRemarks(changeLogFile);
out.println("-- Create objects:");
out.println();

Expand All @@ -374,9 +389,6 @@ public boolean supports(Database database) {
AtomicBoolean uiPending = new AtomicBoolean(false);
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
if (isCancelled.get()) {
throw new RuntimeException("cancelled");
}
for (int i = 0; i < len; ++i) {
char c = cbuf[i + off];
if (c == '\n') {
Expand All @@ -398,6 +410,9 @@ public void write(char[] cbuf, int off, int len) throws IOException {
newType = 5;
}
}
if (isCancelled.get()) {
throw new RuntimeException("cancelled");
}
if (thisLineHadSemicolon && type >= 0 && newType >= 0 && type != newType) {
out.println();
}
Expand All @@ -414,7 +429,9 @@ public void write(char[] cbuf, int off, int len) throws IOException {
if (!uiPending.get()) {
uiPending.set(true);
UIUtil.invokeLater(() -> {
statusLabel.setText(count.get() + " Statements written");
if (!isCancelled.get()) {
statusLabel.setText(count.get() + " Statements written");
}
uiPending.set(false);
});
}
Expand Down Expand Up @@ -468,7 +485,7 @@ public void close() throws IOException {
return true;
}

private String dropDatabaseObjects(Database database, Database targetDatabase, CatalogAndSchema schemaToDrop, CatalogAndSchema targetCatalogAndSchema) throws LiquibaseException {
private String dropDatabaseObjects(Database database, Database targetDatabase, CatalogAndSchema schemaToDrop, CatalogAndSchema targetCatalogAndSchema) throws LiquibaseException {
SnapshotControl snapshotControl = new SnapshotControl(database);
try {
DatabaseSnapshot snapshot;
Expand Down Expand Up @@ -777,7 +794,6 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
gridBagConstraints.insets = new java.awt.Insets(4, 0, 0, 0);
jPanel1.add(jLabel6, gridBagConstraints);

schemaComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 12;
Expand Down Expand Up @@ -921,8 +937,8 @@ private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-F
close();
} else {
statusLabelCancelled.setVisible(true);
toggleEnable(true);
cancel();
toggleEnable(true);
}
}//GEN-LAST:event_closeButtonActionPerformed

Expand Down Expand Up @@ -1006,6 +1022,106 @@ private void fileFindButtonActionPerformed(java.awt.event.ActionEvent evt) {//GE
}
}//GEN-LAST:event_fileFindButtonActionPerformed

/**
* Replace any characters that will cause problems when parsing remarks in the change log file with '?'.
*/
private void checkRemarks(File changeLogFile) {
LoaderOptions loaderOptions = new LoaderOptions();
SnakeYamlUtil.setCodePointLimitSafely(loaderOptions, YamlSnapshotParser.CODE_POINT_LIMIT);
Representer representer = new Representer(new DumperOptions());
DumperOptions dumperOptions = new DumperOptions();
dumperOptions.setDefaultFlowStyle(representer.getDefaultFlowStyle());
dumperOptions.setDefaultScalarStyle(representer.getDefaultScalarStyle());
dumperOptions
.setAllowReadOnlyProperties(representer.getPropertyUtils().isAllowReadOnlyProperties());
dumperOptions.setTimeZone(representer.getTimeZone());
Yaml yaml = new Yaml(new SafeConstructor(loaderOptions), representer, dumperOptions, loaderOptions, new Resolver());

try {
Object parsedYaml;
try (InputStream stream = new FileInputStream(changeLogFile)) {
try (InputStreamReader inputStreamReader = new InputStreamReader(stream,
GlobalConfiguration.OUTPUT_FILE_ENCODING.getCurrentValue())) {
parsedYaml = yaml.load(inputStreamReader);
}
}
if (checkRemarks(parsedYaml)) {
try (Writer outWriter = new FileWriter(changeLogFile)) {
yaml.dump(parsedYaml, outWriter);
}
}
} catch (Exception e) {
LogUtil.warn(e);
}
}

@SuppressWarnings({ "rawtypes", "unchecked" })
private boolean checkRemarks(Object yaml) {
boolean modified = false;

if (yaml instanceof Map) {
HashSet<?> keys = new HashSet<>(((Map) yaml).keySet());
for (Object key: keys) {
Object value = ((Map) yaml).get(key);
if ("remarks".equals(key) && value instanceof byte[]) {
modified = true;
((Map) yaml).put(key, checkRemark(new String((byte[]) value)));
}
if (checkRemarks(value)) {
modified = true;
}
}
} else if (yaml instanceof Collection) {
for (Object item : ((Collection) yaml)) {
if (checkRemarks(item)) {
modified = true;
}
}
}
return modified;
}

/**
* Replace any characters that will cause problems when parsing the change log file with '?'.
*/
private String checkRemark(String text) throws UnexpectedLiquibaseException {
if (null == text || text.isEmpty()) {
return text;
}

final int len = text.length();
char current;
int codePoint;
boolean modified = false;

StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i++) {
current = text.charAt(i);
if (Character.isHighSurrogate(current) && i + 1 < len && Character.isLowSurrogate(text.charAt(i + 1))) {
codePoint = text.codePointAt(i++);
} else {
codePoint = current;
}
if ((codePoint == '\n')
|| (codePoint == '\r')
|| (codePoint == '\t')
|| (codePoint == 0xB)
|| (codePoint == 0xC)
|| ((codePoint >= 0x20) && (codePoint <= 0x7E))
|| ((codePoint >= 0xA0) && (codePoint <= 0xD7FF))
|| ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
|| ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF))
) {
sb.append(current);
} else {
sb.append('?');
modified = true;
}
}

return modified? sb.toString() : text;
}

private String toFileName(String f) {
if (!new File(f).isAbsolute()) {
return Environment.newFile(f).getAbsolutePath();
Expand Down

0 comments on commit ef89a91

Please sign in to comment.