View Javadoc
1   /*******************************************************************************
2    * Copyhacked (H) 2012-2025.
3    * This program and the accompanying materials
4    * are made available under no term at all, use it like
5    * you want, but share and discuss it
6    * every time possible with every body.
7    * 
8    * Contributors:
9    *      ron190 at ymail dot com - initial implementation
10   ******************************************************************************/
11  package com.jsql.view.swing.panel;
12  
13  import com.formdev.flatlaf.FlatClientProperties;
14  import com.formdev.flatlaf.icons.FlatRadioButtonMenuItemIcon;
15  import com.jsql.model.injection.method.AbstractMethodInjection;
16  import com.jsql.util.I18nUtil;
17  import com.jsql.util.LogLevelUtil;
18  import com.jsql.util.ParameterUtil;
19  import com.jsql.util.StringUtil;
20  import com.jsql.view.swing.panel.address.ActionEnterAddressBar;
21  import com.jsql.view.swing.panel.address.PanelTrailingAddress;
22  import com.jsql.view.swing.panel.address.ModelAddressLine;
23  import com.jsql.view.swing.panel.util.ButtonExpandText;
24  import com.jsql.view.swing.text.*;
25  import com.jsql.view.swing.util.I18nViewUtil;
26  import com.jsql.view.swing.util.MediatorHelper;
27  import com.jsql.view.swing.util.RadioItemNonClosing;
28  import com.jsql.view.swing.util.UiUtil;
29  import org.apache.commons.lang3.StringUtils;
30  import org.apache.logging.log4j.LogManager;
31  import org.apache.logging.log4j.Logger;
32  
33  import javax.swing.*;
34  import javax.swing.text.DefaultEditorKit;
35  import java.awt.*;
36  import java.awt.datatransfer.Clipboard;
37  import java.awt.datatransfer.DataFlavor;
38  import java.awt.datatransfer.UnsupportedFlavorException;
39  import java.awt.event.ActionEvent;
40  import java.awt.event.MouseAdapter;
41  import java.awt.event.MouseEvent;
42  import java.io.IOException;
43  import java.io.Serializable;
44  import java.util.AbstractMap;
45  import java.util.Arrays;
46  import java.util.concurrent.atomic.AtomicReference;
47  import java.util.function.Supplier;
48  import java.util.regex.Pattern;
49  import java.util.stream.Stream;
50  
51  /**
52   * Create panel at the top of the window.
53   * Contains textfields in a panel.
54   */
55  public class PanelAddressBar extends JPanel {
56  
57      private static final Logger LOGGER = LogManager.getRootLogger();
58  
59      private final AtomicReference<JTextField> atomicTextFieldAddress = new AtomicReference<>();  // atomic to build dynamically
60      private final AtomicReference<JTextField> atomicTextFieldRequest = new AtomicReference<>();
61      private final AtomicReference<JTextField> atomicTextFieldHeader = new AtomicReference<>();
62  
63      private final AtomicReference<JRadioButton> atomicRadioRequest = new AtomicReference<>();  // atomic to build dynamically
64      private final AtomicReference<JRadioButton> atomicRadioMethod = new AtomicReference<>();
65      private final AtomicReference<JRadioButton> atomicRadioHeader = new AtomicReference<>();
66  
67      private static final String[] METHODS = {"DELETE", StringUtil.GET, "HEAD", "OPTIONS", StringUtil.POST, "PUT", "TRACE"};
68      private JPopupMenu popupMethods;
69      private JRadioButton radioCustomMethod;
70      private JTextField inputCustomMethod;
71      private AdvancedButtonAdapter advancedButtonAdapter;
72  
73      public static final String NAME_ADVANCED_BUTTON = "advancedButton";
74      private static final String KEY_BUTTON_ADVANCED = "BUTTON_ADVANCED";
75      private static final String KEY_ADDRESS_BAR_PLACEHOLDER = "ADDRESS_BAR_PLACEHOLDER";
76      private static final String HEADER_SEPARATOR = "\\r\\n";
77  
78      // Current injection method
79      private AbstractMethodInjection methodInjection = MediatorHelper.model().getMediatorMethod().getQuery();
80      private String typeRequest = StringUtil.GET;
81  
82      private final PanelTrailingAddress panelTrailingAddress;
83  
84      private boolean isAdvanceActivated = false;
85      
86      public PanelAddressBar() {
87          var buttonGroup = new ButtonGroup();
88  
89          Stream.of(
90              new ModelAddressLine(
91                  "URL",
92                  MediatorHelper.model().getMediatorMethod().getQuery(),
93                  "QUERYSTRING",
94                  this.atomicRadioRequest,
95                  I18nUtil.valueByKey(PanelAddressBar.KEY_ADDRESS_BAR_PLACEHOLDER),
96                  this.atomicTextFieldAddress
97              ),
98              new ModelAddressLine(
99                  StringUtil.GET,
100                 MediatorHelper.model().getMediatorMethod().getRequest(),
101                 "REQUEST",
102                 this.atomicRadioMethod,
103                 "e.g. key=value&injectMe=",
104                 this.atomicTextFieldRequest
105             ),
106             new ModelAddressLine(
107                 "Header",
108                 MediatorHelper.model().getMediatorMethod().getHeader(),
109                 "HEADER",
110                 this.atomicRadioHeader,
111                 String.format(
112                     "e.g. key: value\\r\\nCookie: cKey1=cValue1; cKey2=cValue2\\r\\n%s: %s %s\\r\\ninjectMe:",
113                     "Authorization",
114                     "Basic",
115                     "dXNlcjpwYXNz"
116                 ),
117                 this.atomicTextFieldHeader
118             )
119         )
120         .forEach(modelLine -> {
121             var i18nTooltip = String.format("FIELD_%s_TOOLTIP", modelLine.i18n());
122             var tooltipTextfield = new AtomicReference<>(new JToolTipI18n(I18nUtil.valueByKey(i18nTooltip)));
123             modelLine.textfield().set(new JPopupTextField(new JTextFieldPlaceholder(
124                 modelLine.placeholder(),
125                 modelLine.radio() == this.atomicRadioRequest ? 18 : 0
126             ) {
127                 @Override
128                 public JToolTip createToolTip() {
129                     return tooltipTextfield.get();
130                 }
131             }).getProxy());
132             I18nViewUtil.addComponentForKey(i18nTooltip, tooltipTextfield.get());
133             modelLine.textfield().get().addActionListener(new ActionEnterAddressBar(this));
134             modelLine.textfield().get().setVisible(false);  // query will be set back to visible
135             modelLine.textfield().get().setToolTipText(I18nUtil.valueByKey(i18nTooltip));
136 
137             var i18nRadio = String.format("METHOD_%s_TOOLTIP", modelLine.i18n());
138             var tooltipRadio = new AtomicReference<>(new JToolTipI18n(I18nUtil.valueByKey(i18nRadio)));
139             modelLine.radio().set(
140                 new JRadioButton(modelLine.request()) {
141                     @Override
142                     public JToolTip createToolTip() {
143                         return tooltipRadio.get();
144                     }
145                 }
146             );
147             I18nViewUtil.addComponentForKey(i18nRadio, tooltipRadio.get());
148             modelLine.radio().get().setToolTipText(I18nUtil.valueByKey(i18nRadio));
149             modelLine.radio().get().setSelected(modelLine.radio() == this.atomicRadioRequest);
150             modelLine.radio().get().setHorizontalTextPosition(SwingConstants.LEFT);
151             modelLine.radio().get().setVisible(false);
152             modelLine.radio().get().setBorder(BorderFactory.createEmptyBorder(
153                 modelLine.radio() == this.atomicRadioRequest ? 0 : 6, 3, 0, 3
154             ));
155             modelLine.radio().get().addActionListener(e -> MediatorHelper.panelAddressBar().setMethodInjection(modelLine.method()));
156             buttonGroup.add(modelLine.radio().get());
157         });
158 
159         Action originalPaste = this.atomicTextFieldAddress.get().getActionMap().get(DefaultEditorKit.pasteAction);
160         this.atomicTextFieldAddress.get().getActionMap().put(DefaultEditorKit.pasteAction, new PasteAction(originalPaste));
161 
162         this.atomicTextFieldAddress.get().setFont(UiUtil.FONT_NON_MONO_BIG);
163         this.atomicTextFieldAddress.get().setName("textFieldAddress");
164         this.atomicTextFieldAddress.get().setPreferredSize(new Dimension(50, 32));  // required to set correct height
165         this.atomicTextFieldAddress.get().setVisible(true);
166         I18nViewUtil.addComponentForKey(PanelAddressBar.KEY_ADDRESS_BAR_PLACEHOLDER, this.atomicTextFieldAddress.get());  // only i18n placeholder
167 
168         this.panelTrailingAddress = new PanelTrailingAddress(this);
169         this.atomicTextFieldAddress.get().putClientProperty(FlatClientProperties.TEXT_FIELD_TRAILING_COMPONENT, this.panelTrailingAddress);
170         this.atomicTextFieldAddress.get().putClientProperty(FlatClientProperties.TEXT_FIELD_LEADING_ICON, UiUtil.GLOBE.getIcon());
171         this.atomicTextFieldRequest.get().putClientProperty(
172             FlatClientProperties.TEXT_FIELD_TRAILING_COMPONENT,
173             new ButtonExpandText(this.atomicTextFieldRequest.get())
174         );
175         this.atomicTextFieldHeader.get().putClientProperty(
176             FlatClientProperties.TEXT_FIELD_TRAILING_COMPONENT,
177             new ButtonExpandText(this.atomicTextFieldHeader.get())
178         );
179 
180         this.initLayout();
181     }
182 
183     private void initLayout() {
184         final JLabel advancedButton = this.initAdvancedButton();
185         
186         this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
187         
188         // First panel at the top, contains text components
189         var panelTextFields = new JPanel();
190         var groupLayout = new GroupLayout(panelTextFields);
191         panelTextFields.setLayout(groupLayout);
192         panelTextFields.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 0));
193         this.add(panelTextFields);
194 
195         this.popupMethods = new JPopupMenu();
196         final var buttonGroupMethods = new ButtonGroup();
197 
198         for (String method: PanelAddressBar.METHODS) {
199             final JMenuItem newMenuItem = new RadioItemNonClosing(method, StringUtil.GET.equals(method));
200             newMenuItem.addActionListener(actionEvent -> {
201                 this.typeRequest = newMenuItem.getText();
202                 this.atomicRadioMethod.get().setText(this.typeRequest);
203                 this.atomicRadioMethod.get().requestFocusInWindow();  // required to set proper focus
204             });
205             this.popupMethods.add(newMenuItem);
206             buttonGroupMethods.add(newMenuItem);
207         }
208 
209         var tooltipMethods = new AtomicReference<>(new JToolTipI18n(I18nUtil.valueByKey("METHOD_CUSTOM_TOOLTIP")));
210         var panelCustomMethod = new JPanel(new BorderLayout()) {
211             @Override
212             public JToolTip createToolTip() {
213                 return tooltipMethods.get();
214             }
215         };
216         I18nViewUtil.addComponentForKey("METHOD_CUSTOM_TOOLTIP", tooltipMethods.get());
217         Supplier<Color> colorBackground = () -> UIManager.getColor("MenuItem.background");  // adapt to current theme
218         Supplier<Color> colorSelectionBackground = () -> UIManager.getColor("MenuItem.selectionBackground");  // adapt to current theme
219         panelCustomMethod.setBackground(colorBackground.get());  // required for correct color
220 
221         this.radioCustomMethod = new JRadioButton() {
222             @Override
223             public JToolTip createToolTip() {
224                 return tooltipMethods.get();
225             }
226         };
227         this.radioCustomMethod.setBorder(BorderFactory.createEmptyBorder(0, 6, 0, 0));
228         this.radioCustomMethod.setIcon(new FlatRadioButtonMenuItemIcon());
229         this.radioCustomMethod.setBackground(colorBackground.get());  // required for correct color
230         buttonGroupMethods.add(this.radioCustomMethod);
231 
232         this.inputCustomMethod = new JPopupTextField("CUSTOM"){
233             @Override
234             public JToolTip createToolTip() {
235                 return tooltipMethods.get();
236             }
237         }.getProxy();
238         this.radioCustomMethod.addActionListener(actionEvent -> this.validate(this.inputCustomMethod));
239 
240         var tooltipCustomMethod = "<html>Set user defined HTTP method.<br/>" +
241             "A valid method is limited to chars:<br>" +
242             "!#$%&'*+-.^_`|~0123456789<br>" +
243             "abcdefghijklmnopqrstuvwxyz<br>" +
244             "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
245         "</html>";
246         MouseAdapter mouseAdapterSetBackground = new MouseAdapter() {
247             @Override
248             public void mouseEntered(MouseEvent e) {
249                 super.mouseEntered(e);
250                 panelCustomMethod.setBackground(colorSelectionBackground.get());
251                 PanelAddressBar.this.radioCustomMethod.setBackground(colorSelectionBackground.get());
252             }
253             @Override
254             public void mouseExited(MouseEvent e) {
255                 super.mouseExited(e);
256                 panelCustomMethod.setBackground(colorBackground.get());
257                 PanelAddressBar.this.radioCustomMethod.setBackground(colorBackground.get());
258             }
259         };
260         Arrays.asList(this.radioCustomMethod, this.inputCustomMethod, panelCustomMethod).forEach(component -> {
261             component.addMouseListener(mouseAdapterSetBackground);
262             component.setToolTipText(tooltipCustomMethod);
263         });
264 
265         panelCustomMethod.add(this.radioCustomMethod, BorderLayout.LINE_START);
266         panelCustomMethod.add(this.inputCustomMethod, BorderLayout.CENTER);
267         this.popupMethods.insert(panelCustomMethod, this.popupMethods.getComponentCount());
268 
269         this.atomicRadioMethod.get().addMouseListener(new MouseAdapter() {
270             @Override
271             public void mousePressed(MouseEvent e) {
272                 Arrays.stream(PanelAddressBar.this.popupMethods.getComponents()).map(a -> (JComponent) a).forEach(JComponent::updateUI);  // required: incorrect when dark/light mode switch
273                 PanelAddressBar.this.radioCustomMethod.setIcon(new FlatRadioButtonMenuItemIcon());
274                 PanelAddressBar.this.radioCustomMethod.updateUI();  // required: incorrect when dark/light mode switch
275                 PanelAddressBar.this.inputCustomMethod.updateUI();  // required: incorrect when dark/light mode switch
276                 PanelAddressBar.this.popupMethods.updateUI();  // required: incorrect when dark/light mode switch
277 
278                 if (ComponentOrientation.RIGHT_TO_LEFT.equals(ComponentOrientation.getOrientation(I18nUtil.getCurrentLocale()))) {
279                     PanelAddressBar.this.radioCustomMethod.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 6));
280                 } else {
281                     PanelAddressBar.this.radioCustomMethod.setBorder(BorderFactory.createEmptyBorder(0, 6, 0, 0));
282                 }
283 
284                 PanelAddressBar.this.popupMethods.show(
285                     e.getComponent(),
286                     ComponentOrientation.RIGHT_TO_LEFT.equals(ComponentOrientation.getOrientation(I18nUtil.getCurrentLocale()))
287                         ? e.getComponent().getX() - e.getComponent().getWidth() - PanelAddressBar.this.popupMethods.getWidth()
288                         : e.getComponent().getX(),
289                     e.getComponent().getY() + e.getComponent().getHeight()
290                 );
291                 PanelAddressBar.this.popupMethods.setLocation(  // required for proper location
292                     ComponentOrientation.RIGHT_TO_LEFT.equals(ComponentOrientation.getOrientation(I18nUtil.getCurrentLocale()))
293                         ? e.getComponent().getLocationOnScreen().x + e.getComponent().getWidth() - PanelAddressBar.this.popupMethods.getWidth()
294                         : e.getComponent().getLocationOnScreen().x,
295                     e.getComponent().getLocationOnScreen().y + e.getComponent().getHeight()
296                 );
297 
298                 // Orientation set after popup placement, Fix #96032: NullPointerException on show() when arabic
299                 PanelAddressBar.this.popupMethods.applyComponentOrientation(ComponentOrientation.getOrientation(I18nUtil.getCurrentLocale()));
300             }
301         });
302 
303         groupLayout.setHorizontalGroup(
304             groupLayout
305             .createSequentialGroup()
306             .addGroup(
307                 groupLayout
308                 .createParallelGroup(GroupLayout.Alignment.TRAILING, false)
309                 .addComponent(this.atomicRadioRequest.get())
310                 .addComponent(this.atomicRadioMethod.get())
311                 .addComponent(this.atomicRadioHeader.get())
312             )
313             .addGroup(
314                 groupLayout
315                 .createParallelGroup()
316                 .addComponent(this.atomicTextFieldAddress.get())
317                 .addComponent(this.atomicTextFieldRequest.get())
318                 .addComponent(this.atomicTextFieldHeader.get())
319             )
320             .addGroup(
321                 groupLayout
322                 .createParallelGroup(GroupLayout.Alignment.LEADING, false)
323                 .addComponent(advancedButton)
324             )
325         );
326 
327         groupLayout.setVerticalGroup(
328             groupLayout
329             .createSequentialGroup()
330             .addGroup(
331                 groupLayout
332                 .createParallelGroup(GroupLayout.Alignment.CENTER, false)
333                 .addComponent(this.atomicRadioRequest.get())
334                 .addComponent(this.atomicTextFieldAddress.get())
335                 .addComponent(advancedButton)
336             )
337             .addGroup(
338                 groupLayout
339                 .createParallelGroup(GroupLayout.Alignment.BASELINE)
340                 .addComponent(this.atomicRadioMethod.get())
341                 .addComponent(this.atomicTextFieldRequest.get())
342             )
343             .addGroup(
344                 groupLayout
345                 .createParallelGroup(GroupLayout.Alignment.BASELINE)
346                 .addComponent(this.atomicRadioHeader.get())
347                 .addComponent(this.atomicTextFieldHeader.get())
348             )
349         );
350     }
351 
352     private void validate(JTextField inputCustomMethod) {
353         if (StringUtils.isEmpty(inputCustomMethod.getText())) {
354             LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Missing custom request method, forcing GET");
355             Arrays.stream(this.popupMethods.getSubElements())
356             .map(JMenuItem.class::cast)
357             .filter(jMenuItem -> StringUtil.GET.equals(jMenuItem.getText()))
358             .findFirst()
359             .ifPresent(jMenuItem -> jMenuItem.setSelected(true));
360         } else if (ParameterUtil.isInvalidName(inputCustomMethod.getText())) {
361             LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Illegal request method: {}", inputCustomMethod.getText());
362         } else {
363             this.typeRequest = inputCustomMethod.getText();
364             this.atomicRadioMethod.get().setText(this.typeRequest);
365         }
366     }
367 
368     private JLabel initAdvancedButton() {
369         var tooltip = new AtomicReference<>(new JToolTipI18n(I18nUtil.valueByKey(PanelAddressBar.KEY_BUTTON_ADVANCED)));
370         var advancedButton = new JLabel(UiUtil.ARROW_DOWN.getIcon()) {
371             @Override
372             public JToolTip createToolTip() {
373                 return tooltip.get();
374             }
375         };
376         advancedButton.setName(PanelAddressBar.NAME_ADVANCED_BUTTON);
377         advancedButton.setToolTipText(I18nUtil.valueByKey(PanelAddressBar.KEY_BUTTON_ADVANCED));
378         I18nViewUtil.addComponentForKey(PanelAddressBar.KEY_BUTTON_ADVANCED, tooltip.get());
379         this.advancedButtonAdapter = new AdvancedButtonAdapter(advancedButton);
380         advancedButton.addMouseListener(this.advancedButtonAdapter);
381         return advancedButton;
382     }
383 
384     private class AdvancedButtonAdapter extends MouseAdapter implements Serializable {
385 
386         private final JLabel advancedButton;
387 
388         public AdvancedButtonAdapter(JLabel advancedButton) {
389             this.advancedButton = advancedButton;
390         }
391 
392         public void mouseClicked(boolean isVisible) {
393             PanelAddressBar.this.atomicTextFieldRequest.get().setVisible(isVisible);
394             PanelAddressBar.this.atomicTextFieldHeader.get().setVisible(isVisible);
395             PanelAddressBar.this.atomicRadioRequest.get().setVisible(isVisible);
396             PanelAddressBar.this.atomicRadioMethod.get().setVisible(isVisible);
397             PanelAddressBar.this.atomicRadioHeader.get().setVisible(isVisible);
398             PanelAddressBar.this.isAdvanceActivated = isVisible;
399             MediatorHelper.menubar().setVisible(isVisible);
400             this.advancedButton.setIcon(isVisible ? UiUtil.ARROW_UP.getIcon() : UiUtil.ARROW_DOWN.getIcon());
401         }
402 
403         @Override
404         public void mouseClicked(MouseEvent e) {
405             boolean isVisible = this.advancedButton.getIcon() == UiUtil.ARROW_DOWN.getIcon();
406             this.mouseClicked(isVisible);
407         }
408     }
409 
410 
411     // Getter and setter
412 
413     public void setMethodInjection(AbstractMethodInjection methodInjection) {
414         this.methodInjection = methodInjection;
415     }
416 
417     public boolean isAdvanceActivated() {
418         return !this.isAdvanceActivated;
419     }
420 
421     public JTextField getTextFieldAddress() {
422         return this.atomicTextFieldAddress.get();
423     }
424 
425     public JTextField getTextFieldRequest() {
426         return this.atomicTextFieldRequest.get();
427     }
428 
429     public JTextField getTextFieldHeader() {
430         return this.atomicTextFieldHeader.get();
431     }
432 
433     public AbstractMethodInjection getMethodInjection() {
434         return this.methodInjection;
435     }
436 
437     public PanelTrailingAddress getPanelTrailingAddress() {
438         return this.panelTrailingAddress;
439     }
440 
441     public String getTypeRequest() {
442         return this.typeRequest;
443     }
444 
445     public JRadioButton getAtomicRadioRequest() {
446         return this.atomicRadioRequest.get();
447     }
448 
449     public JRadioButton getAtomicRadioMethod() {
450         return this.atomicRadioMethod.get();
451     }
452 
453     public JRadioButton getAtomicRadioHeader() {
454         return this.atomicRadioHeader.get();
455     }
456 
457     private class PasteAction extends AbstractAction {
458 
459         private final transient Action originalPaste;
460 
461         public PasteAction(Action originalPaste) {
462             this.originalPaste = originalPaste;
463         }
464 
465         @Override
466         public void actionPerformed(ActionEvent actionEvent) {
467             try {
468                 Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
469                 String text = (String) cb.getData(DataFlavor.stringFlavor);
470                 text = text.replace("\n", "\r\n").replace("\r\r\n", "\r\n");  // restore non-standardized
471 
472                 String regexStartLine = "([^"+ PanelAddressBar.HEADER_SEPARATOR +"]+)";
473                 String regexHeaders = "((?:[^"+ PanelAddressBar.HEADER_SEPARATOR +"]+"+ PanelAddressBar.HEADER_SEPARATOR +")*)";
474                 String regexBody = "(.*)";
475                 var matcher = Pattern.compile(
476                     "(?s)" + regexStartLine + PanelAddressBar.HEADER_SEPARATOR + regexHeaders + PanelAddressBar.HEADER_SEPARATOR + regexBody
477                 ).matcher(text);
478                 if (!matcher.find()) {  // no match, default paste
479                     this.originalPaste.actionPerformed(actionEvent);
480                     return;
481                 }
482 
483                 LOGGER.log(LogLevelUtil.CONSOLE_INFORM, "HTTP request detected");
484                 String startLine = matcher.group(1);
485                 var matcherStartLine = Pattern.compile("([^ ]+) +([^ ]+) +([^ ]+)").matcher(startLine);
486                 if (!matcherStartLine.find()) {
487                     LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Incorrect HTTP request start line: missing method, request-target or HTTP-version");
488                     return;
489                 }
490 
491                 var method = matcherStartLine.group(1);
492                 var requestTarget = matcherStartLine.group(2);  // absolute-form, authority-form and asterisk-form not managed
493                 // httpVersion unused
494                 var headers = matcher.group(2).trim();
495                 var body = matcher.group(3).trim();
496 
497                 // Configure URL
498                 if (requestTarget.startsWith("/")) {  // origin-form
499                     var listHeaders = Pattern.compile(PanelAddressBar.HEADER_SEPARATOR)
500                         .splitAsStream(headers)
501                         .map(keyValue -> Arrays.copyOf(keyValue.split(":"), 2))
502                         .map(keyValue -> new AbstractMap.SimpleEntry<>(
503                             keyValue[0],
504                             keyValue[1] == null ? StringUtils.EMPTY : keyValue[1]
505                         )).toList();
506                     var host = listHeaders.stream()
507                         .filter(e -> "Host".equalsIgnoreCase(e.getKey())).findFirst()
508                         .orElse(new AbstractMap.SimpleEntry<>("Host", StringUtils.EMPTY));
509                     if (host.getValue().isBlank()) {
510                         LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Incorrect HTTP request origin form: missing Host");
511                         return;
512                     }
513                     requestTarget = "https://" + host.getValue().trim() + requestTarget;
514                 }
515                 PanelAddressBar.this.atomicTextFieldAddress.get().setText(requestTarget);
516 
517                 // Configure method
518                 PanelAddressBar.this.atomicRadioMethod.get().setText(method);
519                 if (!Arrays.asList(PanelAddressBar.METHODS).contains(method)) {
520                     PanelAddressBar.this.inputCustomMethod.setText(method);
521                     PanelAddressBar.this.radioCustomMethod.setSelected(true);
522                 } else {
523                     Arrays.stream(PanelAddressBar.this.popupMethods.getSubElements())
524                     .map(JMenuItem.class::cast)
525                     .filter(jMenuItem -> method.equals(jMenuItem.getText()))
526                     .findFirst()
527                     .ifPresent(jMenuItem -> jMenuItem.setSelected(true));
528                 }
529 
530                 PanelAddressBar.this.atomicTextFieldRequest.get().setText(
531                     body
532                     .replace("\n", "\\n")
533                     .replace("\r", "\\r")
534                 );
535                 PanelAddressBar.this.atomicTextFieldHeader.get().setText(
536                     headers
537                     .replace("\n", "\\n")
538                     .replace("\r", "\\r")
539                 );
540 
541                 PanelAddressBar.this.advancedButtonAdapter.mouseClicked(true);
542             } catch (IOException | UnsupportedFlavorException e) {
543                 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
544             }
545         }
546     }
547 }