com.microsoft.intellij.ui.libraries.LibraryPropertiesPanel.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.intellij.ui.libraries.LibraryPropertiesPanel.java

Source

/**
 * Copyright (c) Microsoft Corporation
 * <p/>
 * All rights reserved.
 * <p/>
 * MIT License
 * <p/>
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
 * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 * <p/>
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
 * the Software.
 * <p/>
 * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
 * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.microsoft.intellij.ui.libraries;

import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.openapi.vfs.VirtualFile;
import com.microsoft.intellij.AzurePlugin;
import com.microsoft.intellij.ui.AzureAbstractPanel;
import com.microsoft.intellij.ui.NewCertificateDialog;
import com.microsoft.intellij.ui.util.UIUtils;
import com.microsoft.intellij.util.PluginUtil;
import com.microsoft.wacommon.commoncontrols.NewCertificateDialogData;
import com.microsoftopentechnologies.azurecommons.wacommonutil.CerPfxUtil;
import com.microsoftopentechnologies.azuremanagementutil.util.Base64;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Map;

import static com.microsoft.intellij.ui.messages.AzureBundle.message;

class LibraryPropertiesPanel implements AzureAbstractPanel {
    private static final int BUFF_SIZE = 1024;

    private JPanel rootPanel;
    private JCheckBox depCheck;
    private JPanel acsFilterPanel;
    private JTextField acsTxt;
    private JTextField relTxt;
    private TextFieldWithBrowseButton certTxt;
    private JButton newCertBtn;
    private JTextPane certInfoTxt;
    private JCheckBox embedCertCheck;
    private JCheckBox requiresHttpsCheck;
    private JLabel libraryVersion;
    private JLabel location;
    private AzureLibrary azureLibrary;
    private Module module;

    private boolean isEdit;

    public LibraryPropertiesPanel(Module module, AzureLibrary azureLibrary, boolean isEdit, boolean isExported) {
        this.module = module;
        this.azureLibrary = azureLibrary;
        this.isEdit = isEdit;
        init();
        depCheck.setSelected(isExported);
    }

    public void init() {
        acsTxt.setText(message("acsTxt"));
        certTxt.getTextField().getDocument().addDocumentListener(createCertTxtListener());
        Messages.configureMessagePaneUi(certInfoTxt, message("embedCertDefTxt"));
        FileChooserDescriptor fileChooserDescriptor = new FileChooserDescriptor(true, false, false, false, false,
                false) {
            @Override
            public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
                return file.isDirectory() || (file.getExtension() != null
                        && (file.getExtension().equals("cer") || file.getExtension().equals(".CER")));
            }

            @Override
            public boolean isFileSelectable(VirtualFile file) {
                return (file.getExtension() != null
                        && (file.getExtension().equals("cer") || file.getExtension().equals(".CER")));
            }
        };
        fileChooserDescriptor.setTitle("Select Certificate");
        newCertBtn.addActionListener(createNewCertListener());
        certTxt.addActionListener(UIUtils.createFileChooserListener(certTxt, null, fileChooserDescriptor));
        requiresHttpsCheck.addActionListener(createRequiredHttpsCheckListener());

        if (isEdit()) {
            // Edit library scenario
            try {
                //                com.intellij.psi.search.PsiShortNamesCache.getInstance(module.getProject()).getFilesByName("web.xml");
                ACSFilterHandler editHandler = new ACSFilterHandler(String.format("%s%s%s",
                        PluginUtil.getModulePath(module), File.separator, message("xmlPath")));
                Map<String, String> paramMap = editHandler.getAcsFilterParams();
                acsTxt.setText(paramMap.get(message("acsAttr")));
                relTxt.setText(paramMap.get(message("relAttr")));
                if (paramMap.get(message("certAttr")) != null) {
                    certTxt.setText(paramMap.get(message("certAttr")));
                    certInfoTxt.setText(getCertInfo(certTxt.getText()));
                } else {
                    certInfoTxt.setText(getEmbeddedCertInfo());
                    embedCertCheck.setSelected(true);
                }

                requiresHttpsCheck.setSelected(!Boolean.valueOf(paramMap.get(message("allowHTTPAttr"))));
            } catch (Exception e) {
                AzurePlugin.log(e.getMessage(), e);
            }
        } else {
            // Add library scenario
            depCheck.setSelected(true);
        }
    }

    private ActionListener createNewCertListener() {
        return new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                NewCertificateDialogData data = new NewCertificateDialogData();
                NewCertificateDialog dialog = new NewCertificateDialog(data, "", module.getProject());
                dialog.show();
                if (dialog.isOK()) {
                    String certPath = data.getCerFilePath();
                    certTxt.setText(certPath != null ? certPath.replace('\\', '/') : certPath);
                    certInfoTxt.setText(getCertInfo(certTxt.getText()));
                }
            }
        };
    }

    private DocumentListener createCertTxtListener() {
        return new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                handleUpdate();
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                handleUpdate();
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                handleUpdate();
            }

            private void handleUpdate() {
                String certInfo = getCertInfo(certTxt.getText());
                if (certInfo != null)
                    certInfoTxt.setText(certInfo);
                else
                    certInfoTxt.setText("");
            }
        };
    }

    private ActionListener createRequiredHttpsCheckListener() {
        return new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (requiresHttpsCheck.isSelected()) {
                    //Do nothing
                } else {
                    int choice = Messages.showYesNoDialog(message("requiresHttpsDlgMsg"),
                            message("requiresHttpsDlgTitle"), Messages.getQuestionIcon());
                    if (choice == Messages.NO) {
                        requiresHttpsCheck.setSelected(true);
                    }
                }
            }
        };
    }

    public JComponent prepare() {
        acsFilterPanel.setVisible(azureLibrary == AzureLibrary.ACS_FILTER);
        libraryVersion.setText(azureLibrary.getName());
        location.setText(
                (String.format("%s%s%s", AzurePlugin.pluginFolder, File.separator, azureLibrary.getLocation())));
        rootPanel.revalidate();
        return rootPanel;
    }

    public boolean onFinish() {
        if (azureLibrary == AzureLibrary.ACS_FILTER) {
            if (doValidate() != null) {
                return false;
            }
            configureDeployment();
        }
        return true;
    }

    @Override
    public JComponent getPanel() {
        return prepare();
    }

    @Override
    public String getDisplayName() {
        return message("edtLbrTtl");
    }

    @Override
    public boolean doOKAction() {
        try {
            configureDeployment();
            return true;
        } catch (Exception ex) {
            PluginUtil.displayErrorDialogAndLog(message("error"), "Error saving configuration", ex);
            return false;
        }
    }

    @Override
    public String getSelectedValue() {
        return null;
    }

    public boolean isExported() {
        return depCheck.isSelected();
    }

    public ValidationInfo doValidate() {
        boolean isEdit = isEdit();
        StringBuilder errorMessage = new StringBuilder();

        // Display error if acs login page URL is null. Applicable for first time and edit scenarios.
        if (acsTxt.getText().isEmpty() || acsTxt.getText().equalsIgnoreCase(message("acsTxt")))
            errorMessage.append(message("acsTxtErr")).append("\n");

        // Display error if relying part realm is null. Applicable for first time and edit scenarios.
        if (relTxt.getText().isEmpty())
            errorMessage.append(message("relTxtErr")).append("\n");

        // if certificate location does not end with .cer then display error
        if (!certTxt.getText().isEmpty() && !certTxt.getText().toLowerCase().endsWith(".cer"))
            errorMessage.append(message("certTxtInvalidExt")).append("\n");

        // Display error if cert location is empty for first time and for edit scenarios if
        // embedded cert option is not selected
        if ((!isEdit && certTxt.getText().isEmpty())
                || (isEdit && certTxt.getText().isEmpty() && !embedCertCheck.isSelected()))
            errorMessage.append(message("certTxtErr")).append("\n");

        // For first time , if embedded cert option is selected , display error if file does not exist at source
        if (!isEdit && !certTxt.getText().isEmpty() && embedCertCheck.isSelected() == true) {
            if (!new File(CerPfxUtil.getCertificatePath(certTxt.getText())).exists()) {
                errorMessage.append(message("acsNoValidCert")).append("\n");
            }
        }
        if (errorMessage.length() > 0) {
            return new ValidationInfo(errorMessage.toString());
        } else {
            return null;
        }
    }

    @Override
    public String getHelpTopic() {
        return null;
    }

    /**
     * Method generates key using
     * Advanced Encryption Standard algorithm.
     *
     * @return String
     * @throws Exception
     */
    private String generateKey() throws Exception {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(128);
        SecretKey secretKey = keyGenerator.generateKey();

        byte[] keyInBytes = secretKey.getEncoded();
        String key = Base64.encode(keyInBytes);
        return key;
    }

    /**
     * Method creates web.xml (deployment descriptor)
     * in WebContent\WEB-INF folder of dynamic web project
     * if does not present already.
     *
     * @return String
     */
    private String createWebXml() {
        String path = null;
        try {
            File cmpntFileLoc = new File(String.format("%s%s%s", PluginUtil.getModulePath(module), File.separator,
                    message("depDirLoc")));
            String cmpntFile = String.format("%s%s%s", cmpntFileLoc, File.separator, message("depFileName"));
            if (!cmpntFileLoc.exists()) {
                cmpntFileLoc.mkdirs();
            }
            AzurePlugin.copyResourceFile(message("resFileLoc"), cmpntFile);
            path = cmpntFile;
        } catch (Exception e) {
            PluginUtil.displayErrorDialogAndLog(message("acsErrTtl"), message("fileCrtErrMsg"), e);
        }
        return new File(path).getPath();
    }

    private String getEmbeddedCertInfo() {
        String webinfLoc = String.format("%s%s%s", PluginUtil.getModulePath(module), File.separator,
                message("depDirLoc"));
        String certLoc = String.format("%s%s%s", webinfLoc, File.separator, message("acsCertLoc"));
        return getCertInfo(certLoc);
    }

    public static void copy(File source, final File destination) throws IOException {
        InputStream instream = null;
        if (source.isDirectory()) {
            if (!destination.exists()) {
                destination.mkdirs();
            }
            String[] kid = source.list();
            for (int i = 0; i < kid.length; i++) {
                copy(new File(source, kid[i]), new File(destination, kid[i]));
            }
        } else {
            //InputStream instream = null;
            OutputStream out = null;
            try {
                if (destination != null && destination.isFile() && !destination.getParentFile().exists())
                    destination.getParentFile().mkdirs();

                instream = new FileInputStream(source);
                out = new FileOutputStream(destination);
                byte[] buf = new byte[BUFF_SIZE];
                int len = instream.read(buf);

                while (len > 0) {
                    out.write(buf, 0, len);
                    len = instream.read(buf);
                }
            } finally {
                if (instream != null) {
                    instream.close();
                }
                if (out != null) {
                    out.close();
                }
            }
        }
    }

    public void removeEmbedCert() {
        String webinfLoc = String.format("%s%s%s", PluginUtil.getModulePath(module), File.separator,
                message("depDirLoc"));
        String certLoc = String.format("%s%s%s", webinfLoc, File.separator, message("acsCertLoc"));
        File destination = new File(certLoc);
        if (destination.exists())
            destination.delete();
        if (destination.getParentFile().exists() && destination.getParentFile().list().length == 0)
            destination.getParentFile().delete();
    }

    private static String getCertInfo(String certURL) {
        X509Certificate acsCert = CerPfxUtil.getCert(certURL, null);
        if (acsCert != null) {
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

            StringBuilder certInfo = new StringBuilder();
            certInfo.append(String.format("%1$-10s", "Subject")).append(" : ").append(acsCert.getSubjectDN())
                    .append("\n");
            certInfo.append(String.format("%1$-11s", "Issuer")).append(" : ").append(acsCert.getIssuerDN())
                    .append("\n");
            certInfo.append(String.format("%1$-13s", "Valid")).append(" : ")
                    .append(dateFormat.format(acsCert.getNotBefore())).append(" to ")
                    .append(dateFormat.format(acsCert.getNotAfter()));
            return certInfo.toString();
        } else {
            return null;
        }
    }

    /**
     * Method adds ACS filter and filter mapping tags in web.xml
     * and saves input values given on ACS library page.
     * In case of edit, populates previously set values.
     */
    private void configureDeployment() {
        ACSFilterHandler handler = null;
        try {
            String xmlPath = String.format("%s%s%s", PluginUtil.getModulePath(module), File.separator,
                    message("xmlPath"));
            File webXml = new File(xmlPath);
            if (webXml.exists()) {
                handler = new ACSFilterHandler(xmlPath);
                handler.setAcsFilterParams(message("acsAttr"), acsTxt.getText());
                handler.setAcsFilterParams(message("relAttr"), relTxt.getText());
                if (!embedCertCheck.isSelected()) {
                    handler.setAcsFilterParams(message("certAttr"), certTxt.getText());
                    if (getEmbeddedCertInfo() != null)
                        removeEmbedCert();
                } else {
                    handler.removeParamsIfExists(message("certAttr"));
                    if (!certTxt.getText().isEmpty()) {
                        String webinfLoc = String.format("%s%s%s", PluginUtil.getModulePath(module), File.separator,
                                message("depDirLoc"));
                        String certLoc = String.format("%s%s%s", webinfLoc, File.separator, message("acsCertLoc"));
                        File destination = new File(certLoc);
                        if (!destination.getParentFile().exists())
                            destination.getParentFile().mkdir();
                        copy(new File(CerPfxUtil.getCertificatePath(certTxt.getText())), destination);
                    }
                }
                handler.setAcsFilterParams(message("secretKeyAttr"), generateKey());
                handler.setAcsFilterParams(message("allowHTTPAttr"),
                        requiresHttpsCheck.isSelected() ? "false" : "true");
            } else {
                int choice = Messages.showYesNoDialog(message("depDescMsg"), message("depDescTtl"),
                        Messages.getQuestionIcon());
                if (choice == Messages.YES) {
                    String path = createWebXml();
                    //copy cert into WEB-INF/cert/_acs_signing.cer location if embed cert is selected
                    if (embedCertCheck.isSelected()) {
                        String webinfLoc = String.format("%s%s%s", PluginUtil.getModulePath(module), File.separator,
                                message("depDirLoc"));
                        String certLoc = String.format("%s%s%s", webinfLoc, File.separator, message("acsCertLoc"));
                        File destination = new File(certLoc);
                        if (!destination.getParentFile().exists())
                            destination.getParentFile().mkdir();
                        copy(new File(CerPfxUtil.getCertificatePath(certTxt.getText())), destination);
                    }
                    handler = new ACSFilterHandler(path);
                    handler.setAcsFilterParams(message("acsAttr"), acsTxt.getText());
                    handler.setAcsFilterParams(message("relAttr"), relTxt.getText());
                    if (!embedCertCheck.isSelected()) { //Do not make entry if embed cert is selected
                        handler.setAcsFilterParams(message("certAttr"), certTxt.getText());
                        if (getEmbeddedCertInfo() != null)
                            removeEmbedCert();
                    }
                    handler.setAcsFilterParams(message("secretKeyAttr"), generateKey());
                    handler.setAcsFilterParams(message("allowHTTPAttr"),
                            requiresHttpsCheck.isSelected() ? "false" : "true");
                } else {
                    return;
                }
            }
        } catch (Exception e) {
            PluginUtil.displayErrorDialogAndLog(message("acsErrTtl"), message("acsErrMsg"), e);
        }
        try {
            handler.save();
        } catch (Exception e) {
            PluginUtil.displayErrorDialogAndLog(message("acsErrTtl"), message("saveErrMsg"), e);
        }
    }

    /**
     * @return current window is edit or not
     */
    private boolean isEdit() {
        return isEdit;
    }

    public String getHelpId() {
        return "acs_config_dialog";
    }
}