Skip to content

Commit cdb6ec0

Browse files
committed
Fix some SonarQube issues, which cause logic change
In RupsController the dimensions are now copied in the constructor. This shouldn't change anything in practice, as, from what I can tell, if screen dimensions change, it should just give you a different dimensions object instead of modifying the existing one. Try-with-resources is used now during save, which changes the error handling logic a bit, but not in a way, that really matters. 3 pixel offset in ContextMenuMouseListener pop-up was removed to make it in line with all the other context menus we have in the app. In DictionaryTableModel oldName init was moved closer to usage, as getCorrectKey doesn't affect the keys array. In StreamTrackingPdfCanvasProcessor Stack was replaced with Deque, shouldn't change anything in practice there. ".trim().length() == 0" string checks were replaced with ".isBlank()", which is _not_ 100% the same, but should be fine here. There are some minor changes in the SaveTo* dialog code, but the only one, that should be visible to the user is that now a failure to save will also be shown in a Toast at the bottom. As for the encoding changes, they are not that obvious... Before it was using the default encoding, which, most likely, would have been UTF-8, at least on *nix. For places, like console logs, where it doesn't really matter, I've changed encoding explicitly to UTF-8. But in places, when using text was already a hack (like loading and saving binary PDF streams), I've set encoding explicitly to Latin-1. Don't think, that will change a lot in practice. Hopefully I'll be able to fix that properly with the new content stream editor.
1 parent ee71132 commit cdb6ec0

14 files changed

+111
-131
lines changed

src/main/java/com/itextpdf/rups/controller/RupsController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public RupsController(Dimension dimension, RupsTabbedPane rupsTabbedPane) {
8484
this.rupsTabbedPane.addChangeListener(this::onTabChanged);
8585
this.rupsTabbedPane.addTabClosedListener(this::onTabClosed);
8686

87-
this.dimension = dimension;
87+
this.dimension = new Dimension(dimension);
8888
}
8989

9090
/**

src/main/java/com/itextpdf/rups/controller/RupsInstanceController.java

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,6 @@ public void loadFile(File file, boolean requireEditable) {
216216
* @param file java.io.File file to save
217217
*/
218218
public void saveFile(File file) {
219-
OutputStream fos = null;
220219
File localFile = file;
221220
try {
222221
if (!localFile.getName().endsWith(PDF_FILE_SUFFIX)) {
@@ -236,8 +235,9 @@ public void saveFile(File file) {
236235
closeRoutine();
237236
if (bos != null) {
238237
bos.close();
239-
fos = Files.newOutputStream(localFile.toPath());
240-
bos.writeTo(fos);
238+
try (final OutputStream fos = Files.newOutputStream(localFile.toPath())) {
239+
bos.writeTo(fos);
240+
}
241241
}
242242

243243
JOptionPane.showMessageDialog(masterComponent, Language.SAVE_SUCCESS.getString(),
@@ -246,14 +246,6 @@ public void saveFile(File file) {
246246
} catch (PdfException | IOException | com.itextpdf.io.exceptions.IOException de) {
247247
JOptionPane.showMessageDialog(masterComponent, de.getMessage(), Language.DIALOG.getString(),
248248
JOptionPane.ERROR_MESSAGE);
249-
} finally {
250-
try {
251-
if (fos != null) {
252-
fos.close();
253-
}
254-
} catch (IOException e) {
255-
LoggerHelper.error(Language.ERROR_CLOSING_STREAM.getString(), e, getClass());
256-
}
257249
}
258250
}
259251

src/main/java/com/itextpdf/rups/io/TextAreaOutputStream.java

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,9 @@ This file is part of the iText (R) project.
4242
*/
4343
package com.itextpdf.rups.io;
4444

45-
import javax.swing.JTextArea;
46-
import java.io.ByteArrayInputStream;
47-
import java.io.IOException;
4845
import java.io.OutputStream;
4946
import java.nio.charset.StandardCharsets;
47+
import javax.swing.JTextArea;
5048

5149
/**
5250
* Everything writing to this OutputStream will be shown in a JTextArea.
@@ -64,45 +62,30 @@ public final class TextAreaOutputStream extends OutputStream {
6462
*/
6563
public TextAreaOutputStream(JTextArea text) {
6664
this.text = text;
67-
clear();
68-
}
69-
70-
/**
71-
* Clear the text area.
72-
*/
73-
public void clear() {
74-
text.setText("");
65+
this.text.setText("");
7566
}
7667

7768
/**
7869
* @see java.io.OutputStream#write(int)
7970
*/
8071
@Override
8172
public void write(int i) {
82-
final byte[] b = {(byte) i};
83-
write(b, 0, 1);
73+
write(new byte[] {(byte) i}, 0, 1);
8474
}
8575

8676
/**
87-
* @see java.io.OutputStream#write(byte[], int, int)
77+
* @see java.io.OutputStream#write(byte[])
8878
*/
8979
@Override
90-
public void write(byte[] b, int off, int len) {
91-
final String snippet = new String(b, off, len, StandardCharsets.UTF_8);
92-
text.append(snippet);
80+
public void write(byte[] b) {
81+
write(b, 0, b.length);
9382
}
9483

9584
/**
96-
* @see java.io.OutputStream#write(byte[])
85+
* @see java.io.OutputStream#write(byte[], int, int)
9786
*/
9887
@Override
99-
public void write(byte[] b) throws IOException {
100-
final ByteArrayInputStream bais = new ByteArrayInputStream(b);
101-
final int bufferSize = 1024;
102-
final byte[] snippet = new byte[bufferSize];
103-
int bytesread;
104-
while ((bytesread = bais.read(snippet)) > 0) {
105-
write(snippet, 0, bytesread);
106-
}
88+
public void write(byte[] b, int off, int len) {
89+
text.append(new String(b, off, len, StandardCharsets.UTF_8));
10790
}
10891
}

src/main/java/com/itextpdf/rups/model/PdfSyntaxParser.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ This file is part of the iText (R) project.
5454
import com.itextpdf.kernel.pdf.canvas.parser.util.PdfCanvasParser;
5555
import com.itextpdf.rups.view.Language;
5656

57+
import java.nio.charset.StandardCharsets;
5758
import javax.swing.JOptionPane;
5859
import java.awt.Component;
5960
import java.io.IOException;
@@ -89,7 +90,11 @@ private PdfObject parseString(String s, Component requester, boolean failOnError
8990
unrecognizedChunks.clear();
9091
openArraysCount = 0;
9192
openDictionaryCount = 0;
92-
final byte[] bytesToParse = s.getBytes();
93+
/*
94+
* This is not that great, as this API prevents us from adding Unicode
95+
* string into arrays and dictionaries...
96+
*/
97+
final byte[] bytesToParse = s.getBytes(StandardCharsets.ISO_8859_1);
9398
final RandomAccessSourceFactory factory = new RandomAccessSourceFactory();
9499
final PdfTokenizer tokenizer =
95100
new PdfTokenizer(new RandomAccessFileOrArray(factory.createSource(bytesToParse)));

src/main/java/com/itextpdf/rups/view/Console.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ This file is part of the iText (R) project.
4545
import com.itextpdf.rups.model.IRupsEventListener;
4646
import com.itextpdf.rups.model.ObjectLoader;
4747

48+
import java.nio.charset.StandardCharsets;
4849
import java.util.List;
4950
import java.util.Objects;
5051
import java.util.concurrent.CopyOnWriteArrayList;
@@ -189,7 +190,9 @@ public void write(final int b) {
189190

190191
@Override
191192
public void write(byte[] b, int off, int len) {
192-
Console.getInstance().updateTextPane(new String(b, off, len), type);
193+
Console.getInstance().updateTextPane(
194+
new String(b, off, len, StandardCharsets.UTF_8), type
195+
);
193196
}
194197

195198
@Override

src/main/java/com/itextpdf/rups/view/DebugView.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ This file is part of the iText (R) project.
4242
*/
4343
package com.itextpdf.rups.view;
4444

45+
import java.nio.charset.StandardCharsets;
4546
import javax.swing.JTextArea;
4647
import javax.swing.SwingUtilities;
4748
import javax.swing.text.BadLocationException;
@@ -121,7 +122,7 @@ public void write(final int b) {
121122

122123
@Override
123124
public void write(byte[] b, int off, int len) {
124-
updateTextPane(new String(b, off, len));
125+
updateTextPane(new String(b, off, len, StandardCharsets.UTF_8));
125126
}
126127

127128
@Override

src/main/java/com/itextpdf/rups/view/contextmenu/ContextMenuMouseListener.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public ContextMenuMouseListener(JPopupMenu popup, JComponent component) {
6565

6666
private void showMenuIfPopupTrigger(MouseEvent e) {
6767
if (e.isPopupTrigger() && showPopupHook(e)) {
68-
popup.show(component, e.getX() + 3, e.getY() + 3);
68+
popup.show(component, e.getX(), e.getY());
6969
}
7070
}
7171

src/main/java/com/itextpdf/rups/view/contextmenu/CopyToClipboardAction.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ public void actionPerformed(ActionEvent e) {
6262
boolean nothingSelected = false;
6363
JTextPane textPane = (JTextPane) invoker;
6464

65-
if (textPane.getSelectedText() == null || textPane.getSelectedText().trim().length() == 0) {
65+
final String selectedText = textPane.getSelectedText();
66+
if (selectedText == null || selectedText.isBlank()) {
6667
nothingSelected = true;
6768
textPane.selectAll();
6869
}

src/main/java/com/itextpdf/rups/view/contextmenu/SaveToFileJTextPaneAction.java

Lines changed: 40 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,19 @@ This file is part of the iText (R) project.
4242
*/
4343
package com.itextpdf.rups.view.contextmenu;
4444

45+
import com.itextpdf.rups.Rups;
4546
import com.itextpdf.rups.model.LoggerHelper;
4647
import com.itextpdf.rups.view.Language;
4748

49+
import java.io.Writer;
50+
import java.nio.charset.StandardCharsets;
51+
import java.nio.file.Files;
52+
import java.nio.file.Path;
4853
import javax.swing.JFileChooser;
4954
import javax.swing.JTextPane;
5055
import javax.swing.SwingUtilities;
5156
import java.awt.Component;
5257
import java.awt.event.ActionEvent;
53-
import java.io.BufferedWriter;
54-
import java.io.FileWriter;
5558
import java.io.IOException;
5659

5760
/**
@@ -65,50 +68,40 @@ public SaveToFileJTextPaneAction(String name, Component invoker) {
6568
}
6669

6770
public void actionPerformed(ActionEvent event) {
68-
final Runnable saveRunnable = new Runnable() {
69-
@Override public void run() {
70-
// get saving location
71-
final JFileChooser fileChooser = new JFileChooser();
72-
73-
final int choice = fileChooser.showSaveDialog(null);
74-
final String path;
75-
76-
if (choice == JFileChooser.APPROVE_OPTION) {
77-
path = fileChooser.getSelectedFile().getPath();
78-
79-
boolean nothingSelected = false;
80-
final JTextPane textPane = (JTextPane) invoker;
81-
82-
if (textPane.getSelectedText() == null || textPane.getSelectedText().trim().length() == 0) {
83-
nothingSelected = true;
84-
textPane.selectAll();
85-
}
86-
87-
BufferedWriter writer = null;
88-
89-
try {
90-
writer = new BufferedWriter(new FileWriter(path));
91-
writer.write(textPane.getSelectedText());
92-
93-
} catch (IOException e) { //TODO
94-
LoggerHelper.warn(Language.ERROR_WRITING_FILE.getString(), e, getClass());
95-
} finally {
96-
try {
97-
if (writer != null) {
98-
writer.close();
99-
}
100-
} catch (IOException e) { //TODO
101-
LoggerHelper.error(Language.ERROR_CLOSING_STREAM.getString(), e, getClass());
102-
}
103-
}
104-
105-
if (nothingSelected) {
106-
textPane.select(0, 0);
107-
}
108-
}
109-
}
110-
};
111-
112-
SwingUtilities.invokeLater(saveRunnable);
71+
SwingUtilities.invokeLater(this::handleAction);
72+
}
73+
74+
private void handleAction() {
75+
// get saving location
76+
final JFileChooser fileChooser = new JFileChooser();
77+
78+
final int choice = fileChooser.showSaveDialog(null);
79+
80+
// Early exit on cancel
81+
if (choice != JFileChooser.APPROVE_OPTION) {
82+
return;
83+
}
84+
final Path path = fileChooser.getSelectedFile().toPath();
85+
86+
final JTextPane textPane = (JTextPane) invoker;
87+
88+
String text = textPane.getSelectedText();
89+
if (text == null || text.isBlank()) {
90+
text = textPane.getText();
91+
}
92+
93+
/*
94+
* This doesn't look that nice. This logic was there before with the
95+
* default charset, and I've changed it to Latin-1, which somewhat
96+
* matches the text pane initialization. But streams themselves are
97+
* binary data, so this is not ideal...
98+
*/
99+
try (final Writer writer = Files.newBufferedWriter(path, StandardCharsets.ISO_8859_1)) {
100+
writer.write(text);
101+
} catch (IOException e) {
102+
final String errorMessage = Language.ERROR_WRITING_FILE.getString();
103+
LoggerHelper.error(errorMessage, e, getClass());
104+
Rups.showBriefMessage(errorMessage);
105+
}
113106
}
114107
}

src/main/java/com/itextpdf/rups/view/contextmenu/SaveToFilePdfTreeAction.java

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ This file is part of the iText (R) project.
4545
import com.itextpdf.kernel.pdf.PdfObject;
4646
import com.itextpdf.kernel.pdf.PdfStream;
4747
import com.itextpdf.kernel.pdf.PdfString;
48+
import com.itextpdf.rups.Rups;
4849
import com.itextpdf.rups.model.LoggerHelper;
4950
import com.itextpdf.rups.view.Language;
5051
import com.itextpdf.rups.view.itext.PdfTree;
@@ -78,38 +79,37 @@ public SaveToFilePdfTreeAction(String name, Component invoker, boolean raw) {
7879
}
7980

8081
public void actionPerformed(ActionEvent event) {
81-
final Runnable saveRunnable = new Runnable() {
82-
@Override
83-
public void run() {
84-
// get saving location
85-
final JFileChooser fileChooser = new JFileChooser();
86-
87-
if (saveRawBytes) {
88-
fileChooser.setDialogTitle(fileChooser.getDialogTitle() + Language.RAW_BYTES.getString());
89-
}
90-
91-
final int choice = fileChooser.showSaveDialog(null);
92-
final String path;
93-
94-
if (choice == JFileChooser.APPROVE_OPTION) {
95-
path = fileChooser.getSelectedFile().getPath();
96-
97-
// Get path to the node
98-
final PdfTree tree = (PdfTree) invoker;
99-
final TreeSelectionModel selectionModel = tree.getSelectionModel();
100-
final TreePath[] paths = selectionModel.getSelectionPaths();
101-
102-
// get the bytes and write away
103-
try (final OutputStream fos = Files.newOutputStream(Path.of(path))) {
104-
writeBytes(fos, paths, saveRawBytes);
105-
} catch (IOException e) { // TODO : Catch this exception properly
106-
LoggerHelper.error(Language.ERROR_WRITING_FILE.getString(), e, getClass());
107-
}
108-
}
109-
}
110-
};
111-
112-
SwingUtilities.invokeLater(saveRunnable);
82+
SwingUtilities.invokeLater(this::handleAction);
83+
}
84+
85+
private void handleAction() {
86+
// get saving location
87+
final JFileChooser fileChooser = new JFileChooser();
88+
89+
if (saveRawBytes) {
90+
fileChooser.setDialogTitle(fileChooser.getDialogTitle() + Language.RAW_BYTES.getString());
91+
}
92+
93+
final int choice = fileChooser.showSaveDialog(null);
94+
// Early exit on cancel
95+
if (choice != JFileChooser.APPROVE_OPTION) {
96+
return;
97+
}
98+
final Path path = fileChooser.getSelectedFile().toPath();
99+
100+
// Get path to the node
101+
final PdfTree tree = (PdfTree) invoker;
102+
final TreeSelectionModel selectionModel = tree.getSelectionModel();
103+
final TreePath[] paths = selectionModel.getSelectionPaths();
104+
105+
// get the bytes and write away
106+
try (final OutputStream fos = Files.newOutputStream(path)) {
107+
writeBytes(fos, paths, saveRawBytes);
108+
} catch (IOException e) {
109+
final String errorMessage = Language.ERROR_WRITING_FILE.getString();
110+
LoggerHelper.error(errorMessage, e, getClass());
111+
Rups.showBriefMessage(errorMessage);
112+
}
113113
}
114114

115115
private static void writeBytes(OutputStream os, TreePath[] paths, boolean raw)

0 commit comments

Comments
 (0)