33import atlantafx .base .theme .PrimerLight ;
44import io .github .ozkanpakdil .swaggerific .animation .Preloader ;
55import io .github .ozkanpakdil .swaggerific .model .ShortcutModel ;
6+ import io .github .ozkanpakdil .swaggerific .tools .ProxySettings ;
67import io .github .ozkanpakdil .swaggerific .ui .MainController ;
78import javafx .application .Application ;
89import javafx .fxml .FXMLLoader ;
1617import org .slf4j .LoggerFactory ;
1718
1819import java .io .IOException ;
20+ import java .net .InetSocketAddress ;
21+ import java .net .ProxySelector ;
22+ import java .net .SocketAddress ;
23+ import java .net .URI ;
24+ import java .util .Collections ;
25+ import java .util .List ;
1926import java .util .Objects ;
2027import java .util .prefs .Preferences ;
2128
@@ -40,6 +47,9 @@ public void start(Stage stage) throws IOException {
4047 String fontSize = userPrefs .get (FONT_SIZE , ".93em" );
4148 String selectedFont = userPrefs .get (SELECTED_FONT , "Verdana" );
4249
50+ // Initialize proxy settings
51+ initializeProxySettings ();
52+
4353 Application .setUserAgentStylesheet (new PrimerLight ().getUserAgentStylesheet ());
4454 loadingWindowLookAndLocation ();
4555 FXMLLoader fxmlLoader = new FXMLLoader (getClass ().getResource ("main-view.fxml" ));
@@ -76,9 +86,91 @@ private void loadingWindowLookAndLocation() {
7686 primaryStage .setHeight (userPrefs .getDouble (STAGE_HEIGHT , 600 ));
7787 }
7888
89+ /**
90+ * Initializes proxy settings for the application. This sets up proxy authentication and system properties if needed.
91+ * This method can be called to reinitialize proxy settings after they have been changed.
92+ */
93+ public static void initializeProxySettings () {
94+ log .info ("Initializing proxy settings..." );
95+
96+ if (ProxySettings .useSystemProxy ()) {
97+ System .setProperty ("java.net.useSystemProxies" , "true" );
98+ log .info ("Using system proxy settings" );
99+ } else {
100+ System .setProperty ("java.net.useSystemProxies" , "false" );
101+
102+ String proxyHost = ProxySettings .getProxyServer ();
103+ int proxyPort = ProxySettings .getProxyPort ();
104+
105+ if (proxyHost != null && !proxyHost .isEmpty ()) {
106+ // Set HTTP proxy
107+ System .setProperty ("http.proxyHost" , proxyHost );
108+ System .setProperty ("http.proxyPort" , String .valueOf (proxyPort ));
109+ System .setProperty ("https.proxyHost" , proxyHost );
110+ System .setProperty ("https.proxyPort" , String .valueOf (proxyPort ));
111+ System .setProperty ("ftp.proxyHost" , proxyHost );
112+ System .setProperty ("ftp.proxyPort" , String .valueOf (proxyPort ));
113+ System .setProperty ("socksProxyHost" , proxyHost );
114+ System .setProperty ("socksProxyPort" , String .valueOf (proxyPort ));
115+
116+ String nonProxyHosts = String .join ("|" , ProxySettings .getProxyBypass ());
117+ System .setProperty ("http.nonProxyHosts" , nonProxyHosts );
118+ System .setProperty ("https.nonProxyHosts" , nonProxyHosts );
119+ System .setProperty ("ftp.nonProxyHosts" , nonProxyHosts );
120+
121+ log .info ("Custom proxy configured: {}:{}" , proxyHost , proxyPort );
122+
123+ // Install JVM-wide ProxySelector
124+ ProxySelector .setDefault (new ProxySelector () {
125+ private final ProxySelector defaultSelector = ProxySelector .getDefault ();
126+
127+ @ Override
128+ public List <java .net .Proxy > select (URI uri ) {
129+ if (ProxySettings .shouldBypassProxy (uri .getHost ())) {
130+ return Collections .singletonList (java .net .Proxy .NO_PROXY );
131+ }
132+ java .net .Proxy proxy = new java .net .Proxy (
133+ java .net .Proxy .Type .HTTP ,
134+ new InetSocketAddress (proxyHost , proxyPort )
135+ );
136+ return Collections .singletonList (proxy );
137+ }
138+
139+ @ Override
140+ public void connectFailed (URI uri , SocketAddress sa , IOException ioe ) {
141+ log .error ("Proxy connection failed for {}: {}" , uri , ioe .getMessage ());
142+ if (defaultSelector != null ) {
143+ defaultSelector .connectFailed (uri , sa , ioe );
144+ }
145+ }
146+ });
147+ } else {
148+ // Clear all proxy settings
149+ System .clearProperty ("http.proxyHost" );
150+ System .clearProperty ("http.proxyPort" );
151+ System .clearProperty ("https.proxyHost" );
152+ System .clearProperty ("https.proxyPort" );
153+ System .clearProperty ("ftp.proxyHost" );
154+ System .clearProperty ("ftp.proxyPort" );
155+ System .clearProperty ("socksProxyHost" );
156+ System .clearProperty ("socksProxyPort" );
157+ System .clearProperty ("http.nonProxyHosts" );
158+ ProxySelector .setDefault (null );
159+ log .info ("No proxy configured" );
160+ }
161+ }
162+
163+ // Proxy authentication is now handled on a per-connection basis
164+
165+ // Recreate all HttpClient instances to apply new proxy settings
166+ io .github .ozkanpakdil .swaggerific .tools .http .HttpServiceImpl .recreateAllHttpClients ();
167+
168+ log .info ("Proxy settings reinitialized successfully" );
169+ }
170+
79171 /**
80172 * Applies custom shortcuts from preferences to menu items and other controls.
81- *
173+ *
82174 * @param root The root node of the scene graph
83175 */
84176 private void applyCustomShortcuts (Parent root ) {
@@ -91,9 +183,8 @@ private void applyCustomShortcuts(Parent root) {
91183 }
92184
93185 /**
94- * Static method to apply custom shortcuts to a scene.
95- * This can be called from anywhere to refresh shortcuts.
96- *
186+ * Static method to apply custom shortcuts to a scene. This can be called from anywhere to refresh shortcuts.
187+ *
97188 * @param scene The scene to apply shortcuts to
98189 */
99190 public static void applyCustomShortcutsToScene (Scene scene ) {
@@ -121,8 +212,7 @@ public static void applyCustomShortcutsToScene(Scene scene) {
121212 }
122213
123214 /**
124- * Static method to apply custom shortcuts to all open windows.
125- * This can be called from anywhere to refresh shortcuts.
215+ * Static method to apply custom shortcuts to all open windows. This can be called from anywhere to refresh shortcuts.
126216 */
127217 public void applyCustomShortcutsToAllWindows () {
128218 if (primaryStage == null ) {
@@ -147,7 +237,7 @@ public void applyCustomShortcutsToAllWindows() {
147237
148238 /**
149239 * Recursively finds all controls with shortcuts in the scene graph and applies custom shortcuts.
150- *
240+ *
151241 * @param parent The parent node to search
152242 */
153243 private void findAndApplyShortcuts (Parent parent ) {
@@ -174,7 +264,7 @@ private void findAndApplyShortcuts(Parent parent) {
174264
175265 /**
176266 * Processes a menu and its items, applying custom shortcuts.
177- *
267+ *
178268 * @param menu The menu to process
179269 */
180270 private void processMenu (javafx .scene .control .Menu menu ) {
@@ -192,7 +282,7 @@ private void processMenu(javafx.scene.control.Menu menu) {
192282
193283 /**
194284 * Applies a custom shortcut to a menu item if one exists in preferences.
195- *
285+ *
196286 * @param menuItem The menu item to apply the shortcut to
197287 */
198288 private void applyCustomShortcutToMenuItem (MenuItem menuItem ) {
@@ -223,7 +313,7 @@ private void applyCustomShortcutToMenuItem(MenuItem menuItem) {
223313
224314 /**
225315 * Gets the action name from a menu item.
226- *
316+ *
227317 * @param menuItem The menu item
228318 * @return The action name, or null if not found
229319 */
@@ -260,7 +350,7 @@ private String getActionNameFromMenuItem(MenuItem menuItem) {
260350
261351 /**
262352 * Applies a custom shortcut to a button if one exists in preferences.
263- *
353+ *
264354 * @param button The button to apply the shortcut to
265355 */
266356 private void applyCustomShortcutToButton (javafx .scene .control .Button button ) {
@@ -300,7 +390,7 @@ private void applyCustomShortcutToButton(javafx.scene.control.Button button) {
300390 // Insert underscore before the character to make it a mnemonic
301391 String newText = text .substring (0 , index ) + "_" + text .substring (index );
302392 button .setText (newText );
303- log .info ("Applied custom shortcut {} to button '{}' (action: {})" ,
393+ log .info ("Applied custom shortcut {} to button '{}' (action: {})" ,
304394 customShortcutStr , newText , onAction );
305395 } else {
306396 // If no suitable character is found, append the key code to the button text
@@ -313,10 +403,12 @@ private void applyCustomShortcutToButton(javafx.scene.control.Button button) {
313403 // Insert underscore before the character to make it a mnemonic
314404 newText = newText .substring (0 , index ) + "_" + newText .substring (index );
315405 button .setText (newText );
316- log .info ("Applied custom shortcut {} to button '{}' with appended key code (action: {})" ,
406+ log .info ("Applied custom shortcut {} to button '{}' with appended key code (action: {})" ,
317407 customShortcutStr , newText , onAction );
318408 } else {
319- log .warn ("Could not find a suitable character for mnemonic in button text '{}', even after appending key code" , text );
409+ log .warn (
410+ "Could not find a suitable character for mnemonic in button text '{}', even after appending key code" ,
411+ text );
320412 }
321413 }
322414 }
@@ -328,7 +420,7 @@ private void applyCustomShortcutToButton(javafx.scene.control.Button button) {
328420
329421 /**
330422 * Finds a suitable character index in the text for a mnemonic based on the key code name.
331- *
423+ *
332424 * @param text The text to search in
333425 * @param keyCodeName The key code name to search for
334426 * @return The index of a suitable character, or -1 if none is found
@@ -370,7 +462,7 @@ private int findSuitableCharacterIndex(String text, String keyCodeName) {
370462
371463 /**
372464 * Gets the action name from a button.
373- *
465+ *
374466 * @param button The button
375467 * @return The action name, or null if not found
376468 */
0 commit comments