From 3a4fd347db12abcfece14f4f192f1da1a008806a Mon Sep 17 00:00:00 2001 From: Hiroki Tokunaga Date: Wed, 27 May 2026 11:20:23 +0900 Subject: [PATCH 1/3] refactor(common): decouple ConfigHttpServer from Swing dialogs Extract config overwrite UI into ConfigHttpUiActions and DB apply logic into ConfigSettingsWriter. Co-authored-by: Cursor --- .../packetproxy/common/ConfigHttpServer.java | 43 +++----------- .../common/ConfigHttpUiActions.java | 12 ++++ .../common/ConfigSettingsWriter.java | 48 +++++++++++++++ .../packetproxy/gui/GUIOptionHubServer.java | 4 +- .../gui/SwingConfigHttpUiActions.java | 59 +++++++++++++++++++ 5 files changed, 131 insertions(+), 35 deletions(-) create mode 100644 src/main/java/core/packetproxy/common/ConfigHttpUiActions.java create mode 100644 src/main/java/core/packetproxy/common/ConfigSettingsWriter.java create mode 100644 src/main/java/core/packetproxy/gui/SwingConfigHttpUiActions.java diff --git a/src/main/java/core/packetproxy/common/ConfigHttpServer.java b/src/main/java/core/packetproxy/common/ConfigHttpServer.java index ca125627..3c6eb294 100644 --- a/src/main/java/core/packetproxy/common/ConfigHttpServer.java +++ b/src/main/java/core/packetproxy/common/ConfigHttpServer.java @@ -7,13 +7,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.swing.*; -import packetproxy.gui.GUIMain; import packetproxy.model.*; public class ConfigHttpServer extends NanoHTTPD { private final String allowedAccessToken; + private final ConfigHttpUiActions uiActions; + private final ConfigSettingsWriter settingsWriter; private static class DaoHub { @@ -30,9 +30,12 @@ private static class DaoHub { List sslPassThroughList; } - public ConfigHttpServer(String hostname, int port, String allowedAccessToken) { + public ConfigHttpServer(String hostname, int port, String allowedAccessToken, ConfigHttpUiActions uiActions, + ConfigSettingsWriter settingsWriter) { super(hostname, port); this.allowedAccessToken = allowedAccessToken; + this.uiActions = uiActions; + this.settingsWriter = settingsWriter; } private void fixUpServerList(Map serverMap, List serverList) { @@ -133,18 +136,9 @@ public Response serve(IHTTPSession session) { try { - GUIMain.getInstance().setAlwaysOnTop(true); - GUIMain.getInstance().setVisible(true); + uiActions.showOptionsTab(); - GUIMain.getInstance().getTabbedPane().setSelectedIndex(GUIMain.Panes.OPTIONS.ordinal()); - - int option = JOptionPane.showConfirmDialog(GUIMain.getInstance(), - I18nString.get("Do you want to overwrite config?"), I18nString.get("Loading config"), - JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); - - GUIMain.getInstance().setAlwaysOnTop(false); - - if (option == JOptionPane.NO_OPTION) { + if (!uiActions.confirmOverwriteConfig()) { return NanoHTTPD.newFixedLengthResponse(Response.Status.UNAUTHORIZED, MIME_HTML, null); } @@ -153,26 +147,7 @@ public Response serve(IHTTPSession session) { session.parseBody(map); String json = map.get("postData"); - DaoHub daoHub = new Gson().fromJson(json, DaoHub.class); - - Database.getInstance().dropConfigs(); - - for (ListenPort listenPort : daoHub.listenPortList) { - - ListenPorts.getInstance().create(listenPort); - } - for (Server server : daoHub.serverList) { - - Servers.getInstance().create(server); - } - for (Modification mod : daoHub.modificationList) { - - Modifications.getInstance().create(mod); - } - for (SSLPassThrough passThrough : daoHub.sslPassThroughList) { - - SSLPassThroughs.getInstance().create(passThrough); - } + settingsWriter.applyFromJson(json); Response res = NanoHTTPD.newFixedLengthResponse(Response.Status.OK, "application/json", "{\"status\": \"ok\"}"); diff --git a/src/main/java/core/packetproxy/common/ConfigHttpUiActions.java b/src/main/java/core/packetproxy/common/ConfigHttpUiActions.java new file mode 100644 index 00000000..38f7c405 --- /dev/null +++ b/src/main/java/core/packetproxy/common/ConfigHttpUiActions.java @@ -0,0 +1,12 @@ +package packetproxy.common; + +/** リモート設定 HTTP API から必要な GUI 操作。 */ +public interface ConfigHttpUiActions { + + void showOptionsTab(); + + /** + * @return 設定上書きを許可する場合 true + */ + boolean confirmOverwriteConfig(); +} diff --git a/src/main/java/core/packetproxy/common/ConfigSettingsWriter.java b/src/main/java/core/packetproxy/common/ConfigSettingsWriter.java new file mode 100644 index 00000000..a602a419 --- /dev/null +++ b/src/main/java/core/packetproxy/common/ConfigSettingsWriter.java @@ -0,0 +1,48 @@ +package packetproxy.common; + +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; +import java.util.List; +import packetproxy.model.*; + +/** リモート設定 JSON を DB に反映する。 */ +public class ConfigSettingsWriter { + + private static class DaoHub { + + @SerializedName(value = "listenPorts") + List listenPortList; + + @SerializedName(value = "servers") + List serverList; + + @SerializedName(value = "modifications") + List modificationList; + + @SerializedName(value = "sslPassThroughs") + List sslPassThroughList; + } + + public void applyFromJson(String json) throws Exception { + var daoHub = new Gson().fromJson(json, DaoHub.class); + + Database.getInstance().dropConfigs(); + + for (ListenPort listenPort : daoHub.listenPortList) { + + ListenPorts.getInstance().create(listenPort); + } + for (Server server : daoHub.serverList) { + + Servers.getInstance().create(server); + } + for (Modification mod : daoHub.modificationList) { + + Modifications.getInstance().create(mod); + } + for (SSLPassThrough passThrough : daoHub.sslPassThroughList) { + + SSLPassThroughs.getInstance().create(passThrough); + } + } +} diff --git a/src/main/java/core/packetproxy/gui/GUIOptionHubServer.java b/src/main/java/core/packetproxy/gui/GUIOptionHubServer.java index eee56367..b009122c 100644 --- a/src/main/java/core/packetproxy/gui/GUIOptionHubServer.java +++ b/src/main/java/core/packetproxy/gui/GUIOptionHubServer.java @@ -11,6 +11,7 @@ import javax.swing.*; import org.apache.commons.lang3.RandomStringUtils; import packetproxy.common.ConfigHttpServer; +import packetproxy.common.ConfigSettingsWriter; import packetproxy.common.I18nString; import packetproxy.model.ConfigBoolean; import packetproxy.model.ConfigString; @@ -104,7 +105,8 @@ private void stopServer() { private void startServer() throws Exception { String accessToken = new ConfigString("SharingConfigsAccessToken").getString(); - this.server = new ConfigHttpServer("localhost", 32349, accessToken); + this.server = new ConfigHttpServer("localhost", 32349, accessToken, new SwingConfigHttpUiActions(), + new ConfigSettingsWriter()); this.server.start(); } diff --git a/src/main/java/core/packetproxy/gui/SwingConfigHttpUiActions.java b/src/main/java/core/packetproxy/gui/SwingConfigHttpUiActions.java new file mode 100644 index 00000000..5f82c8ec --- /dev/null +++ b/src/main/java/core/packetproxy/gui/SwingConfigHttpUiActions.java @@ -0,0 +1,59 @@ +/* + * Copyright 2026 DeNA Co., Ltd. + * + * 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 packetproxy.gui; + +import javax.swing.JOptionPane; +import packetproxy.common.ConfigHttpUiActions; +import packetproxy.common.I18nString; + +public class SwingConfigHttpUiActions implements ConfigHttpUiActions { + + @Override + public void showOptionsTab() { + try { + showOptionsTabInternal(); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + private void showOptionsTabInternal() throws Exception { + var main = GUIMain.getInstance(); + main.setAlwaysOnTop(true); + main.setVisible(true); + main.getTabbedPane().setSelectedIndex(GUIMain.Panes.OPTIONS.ordinal()); + main.setAlwaysOnTop(false); + } + + @Override + public boolean confirmOverwriteConfig() { + try { + return confirmOverwriteConfigInternal(); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + private boolean confirmOverwriteConfigInternal() throws Exception { + var main = GUIMain.getInstance(); + main.setAlwaysOnTop(true); + main.setVisible(true); + int option = JOptionPane.showConfirmDialog(main, I18nString.get("Do you want to overwrite config?"), + I18nString.get("Loading config"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); + main.setAlwaysOnTop(false); + return option == JOptionPane.YES_OPTION; + } +} From 7ad91bfdd32532c499fb4cd3918ba5655e89d910 Mon Sep 17 00:00:00 2001 From: Hiroki Tokunaga Date: Wed, 27 May 2026 12:06:18 +0900 Subject: [PATCH 2/3] chore: add license headers to ConfigHttp classes Add Apache 2.0 copyright headers to ConfigHttpUiActions and ConfigSettingsWriter. Co-authored-by: Cursor --- .../packetproxy/common/ConfigHttpUiActions.java | 15 +++++++++++++++ .../packetproxy/common/ConfigSettingsWriter.java | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/main/java/core/packetproxy/common/ConfigHttpUiActions.java b/src/main/java/core/packetproxy/common/ConfigHttpUiActions.java index 38f7c405..87e85b72 100644 --- a/src/main/java/core/packetproxy/common/ConfigHttpUiActions.java +++ b/src/main/java/core/packetproxy/common/ConfigHttpUiActions.java @@ -1,3 +1,18 @@ +/* + * Copyright 2026 DeNA Co., Ltd. + * + * 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 packetproxy.common; /** リモート設定 HTTP API から必要な GUI 操作。 */ diff --git a/src/main/java/core/packetproxy/common/ConfigSettingsWriter.java b/src/main/java/core/packetproxy/common/ConfigSettingsWriter.java index a602a419..9fbc82f2 100644 --- a/src/main/java/core/packetproxy/common/ConfigSettingsWriter.java +++ b/src/main/java/core/packetproxy/common/ConfigSettingsWriter.java @@ -1,3 +1,18 @@ +/* + * Copyright 2026 DeNA Co., Ltd. + * + * 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 packetproxy.common; import com.google.gson.Gson; From 75558ffbca88c2c79110542f35d00664e3532023 Mon Sep 17 00:00:00 2001 From: Hiroki Tokunaga Date: Wed, 27 May 2026 12:36:09 +0900 Subject: [PATCH 3/3] refactor(common): extract ConfigDaoHub for config JSON Replace duplicated private DaoHub inner classes in ConfigHttpServer, ConfigSettingsWriter, and ConfigIO with a shared DTO type. Co-authored-by: Cursor --- .../core/packetproxy/common/ConfigDaoHub.java | 36 +++++++++++++++++++ .../packetproxy/common/ConfigHttpServer.java | 20 ++--------- .../core/packetproxy/common/ConfigIO.java | 22 ++---------- .../common/ConfigSettingsWriter.java | 19 +--------- 4 files changed, 42 insertions(+), 55 deletions(-) create mode 100644 src/main/java/core/packetproxy/common/ConfigDaoHub.java diff --git a/src/main/java/core/packetproxy/common/ConfigDaoHub.java b/src/main/java/core/packetproxy/common/ConfigDaoHub.java new file mode 100644 index 00000000..9c959135 --- /dev/null +++ b/src/main/java/core/packetproxy/common/ConfigDaoHub.java @@ -0,0 +1,36 @@ +/* + * Copyright 2026 DeNA Co., Ltd. + * + * 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 packetproxy.common; + +import com.google.gson.annotations.SerializedName; +import java.util.List; +import packetproxy.model.*; + +/** 設定エクスポート/インポート用 JSON の DTO。 */ +public class ConfigDaoHub { + + @SerializedName(value = "listenPorts") + List listenPortList; + + @SerializedName(value = "servers") + List serverList; + + @SerializedName(value = "modifications") + List modificationList; + + @SerializedName(value = "sslPassThroughs") + List sslPassThroughList; +} diff --git a/src/main/java/core/packetproxy/common/ConfigHttpServer.java b/src/main/java/core/packetproxy/common/ConfigHttpServer.java index 3c6eb294..4655e666 100644 --- a/src/main/java/core/packetproxy/common/ConfigHttpServer.java +++ b/src/main/java/core/packetproxy/common/ConfigHttpServer.java @@ -2,7 +2,6 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.annotations.SerializedName; import fi.iki.elonen.NanoHTTPD; import java.util.HashMap; import java.util.List; @@ -15,21 +14,6 @@ public class ConfigHttpServer extends NanoHTTPD { private final ConfigHttpUiActions uiActions; private final ConfigSettingsWriter settingsWriter; - private static class DaoHub { - - @SerializedName(value = "listenPorts") - List listenPortList; - - @SerializedName(value = "servers") - List serverList; - - @SerializedName(value = "modifications") - List modificationList; - - @SerializedName(value = "sslPassThroughs") - List sslPassThroughList; - } - public ConfigHttpServer(String hostname, int port, String allowedAccessToken, ConfigHttpUiActions uiActions, ConfigSettingsWriter settingsWriter) { super(hostname, port); @@ -77,7 +61,7 @@ private void fixUpModificationList(Map serverMap, List serverMap = new HashMap<>(); fixUpServerList(serverMap, daoHub.serverList); fixUpListenPortList(serverMap, daoHub.listenPortList); @@ -110,7 +94,7 @@ public Response serve(IHTTPSession session) { try { - DaoHub daoHub = new DaoHub(); + ConfigDaoHub daoHub = new ConfigDaoHub(); daoHub.listenPortList = ListenPorts.getInstance().queryAll(); daoHub.serverList = Servers.getInstance().queryAll(); diff --git a/src/main/java/core/packetproxy/common/ConfigIO.java b/src/main/java/core/packetproxy/common/ConfigIO.java index bb5c10e4..2831ba25 100644 --- a/src/main/java/core/packetproxy/common/ConfigIO.java +++ b/src/main/java/core/packetproxy/common/ConfigIO.java @@ -2,7 +2,6 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.annotations.SerializedName; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -11,21 +10,6 @@ public class ConfigIO { - private static class DaoHub { - - @SerializedName(value = "listenPorts") - List listenPortList; - - @SerializedName(value = "servers") - List serverList; - - @SerializedName(value = "modifications") - List modificationList; - - @SerializedName(value = "sslPassThroughs") - List sslPassThroughList; - } - public ConfigIO() { } @@ -68,7 +52,7 @@ private void fixUpModificationList(Map serverMap, List serverMap = new HashMap<>(); fixUpServerList(serverMap, daoHub.serverList); fixUpListenPortList(serverMap, daoHub.listenPortList); @@ -76,7 +60,7 @@ private void fixUp(DaoHub daoHub) { } public String getOptions() throws Exception { - DaoHub daoHub = new DaoHub(); + ConfigDaoHub daoHub = new ConfigDaoHub(); daoHub.listenPortList = ListenPorts.getInstance().queryAll(); daoHub.serverList = Servers.getInstance().queryAll(); @@ -92,7 +76,7 @@ public String getOptions() throws Exception { } public void setOptions(String json) throws Exception { - DaoHub daoHub = new Gson().fromJson(json, DaoHub.class); + ConfigDaoHub daoHub = new Gson().fromJson(json, ConfigDaoHub.class); Database.getInstance().dropConfigs(); diff --git a/src/main/java/core/packetproxy/common/ConfigSettingsWriter.java b/src/main/java/core/packetproxy/common/ConfigSettingsWriter.java index 9fbc82f2..7ab499bd 100644 --- a/src/main/java/core/packetproxy/common/ConfigSettingsWriter.java +++ b/src/main/java/core/packetproxy/common/ConfigSettingsWriter.java @@ -16,30 +16,13 @@ package packetproxy.common; import com.google.gson.Gson; -import com.google.gson.annotations.SerializedName; -import java.util.List; import packetproxy.model.*; /** リモート設定 JSON を DB に反映する。 */ public class ConfigSettingsWriter { - private static class DaoHub { - - @SerializedName(value = "listenPorts") - List listenPortList; - - @SerializedName(value = "servers") - List serverList; - - @SerializedName(value = "modifications") - List modificationList; - - @SerializedName(value = "sslPassThroughs") - List sslPassThroughList; - } - public void applyFromJson(String json) throws Exception { - var daoHub = new Gson().fromJson(json, DaoHub.class); + var daoHub = new Gson().fromJson(json, ConfigDaoHub.class); Database.getInstance().dropConfigs();