Skip to content

Instantly share code, notes, and snippets.

@egore
Created June 2, 2020 16:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save egore/55e9856cebf267b6bb43ef80aef9e411 to your computer and use it in GitHub Desktop.
Save egore/55e9856cebf267b6bb43ef80aef9e411 to your computer and use it in GitHub Desktop.
Swing UI to delete attachments from confluence pages in batches
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itextpdf.xmp.impl.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import javax.net.ssl.HttpsURLConnection;
import javax.swing.*;
import javax.xml.ws.Holder;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
public class RemoveConfluenceAttachments {
private static final String CONFLUENCE_BASE = "https://YOUR_DOMAIN_HERE/";
public static void main(String[] args) throws IOException {
// Set up our main UI
JFrame mainFrame = new JFrame("Remove attachments");
mainFrame.setSize(400, 400);
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent){
System.exit(0);
}
});
JPanel header = new JPanel();
JTextField input = new JTextField(args.length > 1 ? args[1] : "");
header.add(input, BorderLayout.WEST);
JButton load = new JButton("Load");
header.add(load, BorderLayout.EAST);
mainFrame.add(header, BorderLayout.NORTH);
JPanel comp = new JPanel();
JScrollPane scrollPane = new JScrollPane(comp,
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
mainFrame.add(scrollPane, BorderLayout.CENTER);
Map<JCheckBox, JsonNode> nodes = new LinkedHashMap<>();
Holder<JCheckBox> checkAll = new Holder<>();
initUI(args[0], input.getText(), comp, scrollPane, nodes, checkAll);
load.addActionListener((e) -> new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() {
try {
initUI(args[0], input.getText(), comp, scrollPane, nodes, checkAll);
} catch (IOException ex) {
ex.printStackTrace();
}
return null;
}
}.execute());
JButton buttonRemove = new JButton("Remove selected");
buttonRemove.addActionListener(e -> new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() {
for (Iterator<JCheckBox> iterator = nodes.keySet().iterator(); iterator.hasNext(); ) {
JCheckBox x = iterator.next();
if (x.isSelected()) {
try {
String id = nodes.get(x).get("id").asText();
if (StringUtils.isEmpty(id)) {
System.err.println("empty");
continue;
}
if (delete(CONFLUENCE_BASE + "rest/api/content/" + nodes.get(x).get("id").asText(), args[0])) {
iterator.remove();
nodes.remove(x);
comp.remove(x);
} else {
System.err.println("failed");
}
} catch (IOException ex) {
System.err.println("failed: " + ex.getMessage());
}
}
scrollPane.revalidate();
}
checkAll.value.setSelected(nodes.keySet().stream().allMatch(JCheckBox::isSelected));
comp.updateUI();
return null;
}
}.execute());
mainFrame.add(buttonRemove, BorderLayout.SOUTH);
mainFrame.setVisible(true);
}
private static void initUI(String password, String id, JPanel comp, JScrollPane scrollPane, Map<JCheckBox, JsonNode> nodes, Holder<JCheckBox> checkAll_) throws IOException {
nodes.clear();
comp.removeAll();
if (StringUtils.isEmpty(id)) {
return;
}
JsonNode rootNode = getAsJson(CONFLUENCE_BASE + "rest/api/content/" + id + "/child/attachment", password);
JsonNode results = rootNode.get("results");
comp.setLayout(new GridLayout(results.size() + 2, 1));
JCheckBox checkAll = new JCheckBox("Check all");
checkAll.addChangeListener(e -> nodes.forEach((k, v) -> k.setSelected(checkAll.isSelected())));
comp.add(checkAll);
for (JsonNode i : results) {
JCheckBox checkbox = new JCheckBox(i.get("title").asText());
nodes.put(checkbox, i);
comp.add(checkbox);
}
scrollPane.revalidate();
checkAll_.value = checkAll;
}
private static JsonNode getAsJson(String u, String usernameAndPassword) throws IOException {
URL url = new URL(u);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setRequestProperty("Authorization", "Basic " + Base64.encode(usernameAndPassword));
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(connection.getInputStream());
connection.disconnect();
return rootNode;
}
private static boolean delete(String u, String usernameAndPassword) throws IOException {
URL url = new URL(u);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("DELETE");
connection.setRequestProperty("Authorization", "Basic " + Base64.encode(usernameAndPassword));
boolean result = connection.getResponseCode() >= HttpURLConnection.HTTP_OK && connection.getResponseCode() <= HttpURLConnection.HTTP_NO_CONTENT;
if (!result) {
System.err.println(connection.getResponseCode());
if (connection.getErrorStream() != null) {
System.err.println(IOUtils.toString(connection.getErrorStream(), connection.getContentEncoding()));
}
if (connection.getInputStream() != null) {
System.err.println(IOUtils.toString(connection.getInputStream(), connection.getContentEncoding()));
}
}
connection.disconnect();
return result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment