Java tutorial
/** * 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.azureroles; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.module.Module; import com.intellij.openapi.options.BaseConfigurable; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.ui.AnActionButton; import com.intellij.ui.AnActionButtonRunnable; import com.intellij.ui.AnActionButtonUpdater; import com.intellij.ui.ToolbarDecorator; import com.intellij.ui.table.TableView; import com.intellij.util.ui.ColumnInfo; import com.intellij.util.ui.ListTableModel; import com.intellij.util.ui.table.ComboBoxTableCellEditor; import com.interopbridges.tools.windowsazure.*; import com.microsoft.intellij.AzurePlugin; import com.microsoft.intellij.ui.AzureWizardModel; import com.microsoft.intellij.ui.StorageAccountPanel; import com.microsoft.intellij.ui.components.DefaultDialogWrapper; import com.microsoft.intellij.ui.util.JdkSrvConfig; import com.microsoft.intellij.ui.util.UIUtils; import com.microsoft.intellij.util.PluginUtil; import com.microsoftopentechnologies.azurecommons.propertypage.Azure; import com.microsoftopentechnologies.azurecommons.roleoperations.WARCachingUtilMethods; import com.microsoftopentechnologies.azurecommons.storageregistry.StorageAccountRegistry; import com.microsoftopentechnologies.azurecommons.storageregistry.StorageRegistryUtilMethods; import org.jdesktop.swingx.JXHyperlink; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.table.TableCellEditor; import java.awt.event.*; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import static com.microsoft.intellij.ui.messages.AzureBundle.message; public class CachingPanel extends BaseConfigurable implements SearchableConfigurable, Configurable.NoScroll { private static final String DASH_AUTO = "-auto"; /** * Default cache memory size. */ private final static int CACH_DFLTVAL = 30; private enum BACKUP_OPTIONS { Yes, No } private enum EXPIRATION_TYPE { NeverExpires, Absolute, SlidingWindow } private JPanel contentPane; private JCheckBox cacheCheck; private JTextPane enblCacheNote; private JPanel tablePanel; private JTextField txtHostName; private JComboBox comboStrgAcc; private JSlider cacheScale; private JXHyperlink accLink; private JTextField txtCache; private JLabel hostNameLbl; private JLabel scaleLbl; private JLabel explNtLbl; private JLabel crdntlLbl; private TableView<WindowsAzureNamedCache> tblCache; private Module module; private WindowsAzureProjectManager waProjManager; private WindowsAzureRole waRole; private Map<String, WindowsAzureNamedCache> mapCache; /** * Boolean field to track whether * cache memory size is set to valid value or not. */ private Boolean isCachPerValid = true; public CachingPanel(Module module, WindowsAzureProjectManager waProjManager, WindowsAzureRole waRole) { this.module = module; this.waProjManager = waProjManager; this.waRole = waRole; /* Check Cache memory setting is present or not * and if enabled show appropriate values on property page */ int cachePercent = 0; try { cachePercent = waRole.getCacheMemoryPercent(); } catch (WindowsAzureInvalidProjectOperationException e) { PluginUtil.displayErrorDialogAndLog(message("cachErrTtl"), message("getCachMemErMsg"), e); } if (cachePercent > 0) { setEnableCaching(true); cacheCheck.setSelected(true); txtCache.setText(String.format("%s%s", cachePercent, "%")); cacheScale.setValue(cachePercent); txtHostName.setText( String.format("%s%s%s", message("dlgDbgLclHost"), "_", waRole.getName().toLowerCase())); try { String accKey = waRole.getCacheStorageAccountKey(); UIUtils.populateStrgNameAsPerKey(accKey, comboStrgAcc); } catch (WindowsAzureInvalidProjectOperationException e) { PluginUtil.displayErrorDialogAndLog(message("cachErrTtl"), message("getStrAccErrMsg"), e); } } else { cacheCheck.setSelected(false); setEnableCaching(false); } try { mapCache = waRole.getNamedCaches(); } catch (WindowsAzureInvalidProjectOperationException e) { PluginUtil.displayErrorDialogAndLog(message("cachErrTtl"), message("cachGetErMsg"), e); mapCache = new HashMap<String, WindowsAzureNamedCache>(); } init(); } private void init() { Messages.configureMessagePaneUi(enblCacheNote, message("enblCachNtLbl")); cacheCheck.addItemListener(createCacheCheckListener()); cacheScale.setPaintTicks(true); cacheScale.setMajorTickSpacing(10); cacheScale.addChangeListener(createCacheScaleListener()); txtCache.addFocusListener(createTxtCacheListener()); accLink.setAction(createAccLinkAction()); comboStrgAcc.addItemListener(createcomboStrgAccListener()); CacheTableModel myModel = new CacheTableModel(new ArrayList<WindowsAzureNamedCache>(mapCache.values())); tblCache.setModelAndUpdateColumns(myModel); tblCache.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); tblCache.setRowHeight(ComboBoxTableCellEditor.INSTANCE.getComponent().getPreferredSize().height); } private ChangeListener createCacheScaleListener() { return new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { setModified(true); JSlider source = (JSlider) e.getSource(); int value = source.getValue(); if (!source.getValueIsAdjusting()) { //done adjusting txtCache.setText(String.format("%s%s", value, "%")); setCachPerMem(value); } else { //value is adjusting; just set the text txtCache.setText(String.valueOf(value)); } } }; } private ItemListener createcomboStrgAccListener() { return new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { setCacheNameKey(); } }; } private FocusListener createTxtCacheListener() { /** * Adjusts scales's position, according to value * entered in the synchronized cache text box. */ return new FocusListener() { private String oldTxt = ""; @Override public void focusGained(FocusEvent e) { oldTxt = txtCache.getText(); } @Override public void focusLost(FocusEvent e) { if (!txtCache.getText().equals(oldTxt)) { setModified(true); int cacheVal = 0; Boolean isNumber = true; try { /* * As '%' is allowed in user's input, * check if '%' is present already * then ignore '%' and take only numeric value */ if (txtCache.getText().endsWith("%")) { cacheVal = Integer.parseInt( txtCache.getText().trim().substring(0, txtCache.getText().length() - 1)); } else { cacheVal = Integer.parseInt(txtCache.getText().trim()); txtCache.setText(String.format("%s%s", cacheVal, "%")); } } catch (NumberFormatException ex) { /* * User has given alphabet * or special character as input * for cache memory size. */ isNumber = false; } /* * Check cache memory size input * is numeric and has value > 0 */ if (isNumber && cacheVal >= 10 && cacheVal <= 100) { setCachPerMem(cacheVal); cacheScale.setValue(cacheVal); } else { /* * User has given zero * or negative number as input. */ isCachPerValid = false; } } } }; } private ItemListener createCacheCheckListener() { return new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { setModified(true); if (cacheCheck.isSelected()) { if (message("txtExtraSmallVM").equals(waRole.getVMSize())) { PluginUtil.displayErrorDialog(message("cacheConfTitle"), message("cacheConfErrMsg")); cacheCheck.setSelected(false); return; } setEnableCaching(true); /* Set cache memory percent * to default value 30 */ setCachPerMem(CACH_DFLTVAL); cacheScale.setValue(CACH_DFLTVAL); txtCache.setText(String.format("%s%s", CACH_DFLTVAL, "%")); txtHostName.setText( String.format("%s%s%s", message("dlgDbgLclHost"), "_", waRole.getName().toLowerCase())); setName(DASH_AUTO); } else { setEnableCaching(false); /* Set cache memory percent to 0 * to disable cache. * Also set storage account name * and key to empty. */ setCachPerMem(0); setName(""); setKey(""); setBlobUrl(""); } tblCache.getListTableModel().setItems(new ArrayList<WindowsAzureNamedCache>(mapCache.values())); } }; } private Action createAccLinkAction() { return new AbstractAction("Accounts...") { @Override public void actionPerformed(ActionEvent e) { final DefaultDialogWrapper storageAccountDialog = new DefaultDialogWrapper(module.getProject(), new StorageAccountPanel(module.getProject())); storageAccountDialog.show(); /* * Update data in every case. * No need to check which button (OK/Cancel) * has been pressed as change is permanent * even though user presses cancel * according to functionality. */ /* * store old value which was selected * previously so that we can populate * the same later. */ String cmbName = (String) comboStrgAcc.getSelectedItem(); String accPgName = storageAccountDialog.getSelectedValue(); String finalNameToSet; /* * If row selected on preference page. * set combo box to it always. * Else keep combo box's previous value * as it is. */ if (!(JdkSrvConfig.NONE_TXT.equals(accPgName) || JdkSrvConfig.AUTO_TXT.equals(accPgName))) { finalNameToSet = accPgName; } else { finalNameToSet = cmbName; } // update storage account combo box JdkSrvConfig.populateStrgAccComboBox(finalNameToSet, comboStrgAcc, null, JdkSrvConfig.AUTO_TXT.equals(finalNameToSet)); setCacheNameKey(); } }; } /** * Method sets cache name and key * as per storage account combo box value. */ private void setCacheNameKey() { String key = AzureWizardModel.getAccessKey(comboStrgAcc); String url = JdkSrvConfig.getBlobEndpointUrl(comboStrgAcc); if (key.isEmpty()) { // auto is selected setName(DASH_AUTO); } else { String name = StorageAccountRegistry.getStrgList() .get(StorageRegistryUtilMethods.getStrgAccIndexAsPerKey(key)).getStrgName(); setName(name); } setKey(key); setBlobUrl(url); setModified(true); } /** * Method sets azure role's * cache storage account key. * * @param key */ private void setKey(String key) { try { waRole.setCacheStorageAccountKey(key); } catch (WindowsAzureInvalidProjectOperationException e) { PluginUtil.displayErrorDialogAndLog(message("cachErrTtl"), message("setAccKyErrMsg"), e); } } /** * Method sets azure role's * cache storage account name. * * @param name */ private void setName(String name) { try { waRole.setCacheStorageAccountName(name); } catch (WindowsAzureInvalidProjectOperationException e) { PluginUtil.displayErrorDialogAndLog(message("cachErrTtl"), message("setAccNmErrMsg"), e); } } /** * Method sets azure role's * cache storage account blob endpoint url. * * @param url */ private void setBlobUrl(String url) { try { waRole.setCacheStorageAccountUrl(url); } catch (WindowsAzureInvalidProjectOperationException e) { PluginUtil.displayErrorDialogAndLog(message("cachErrTtl"), message("setAccUrlErrMsg"), e); } } /** * Method enables or disables * UI components on caching page. * * @param status */ private void setEnableCaching(boolean status) { enblCacheNote.setEnabled(status); scaleLbl.setEnabled(status); cacheScale.setEnabled(status); txtCache.setEnabled(status); tblCache.setEnabled(status); explNtLbl.setEnabled(status); txtHostName.setEnabled(status); hostNameLbl.setEnabled(status); comboStrgAcc.setEnabled(status); crdntlLbl.setEnabled(status); if (status) { JdkSrvConfig.populateStrgAccComboBox("", comboStrgAcc, null, true); } else { cacheScale.setValue(cacheScale.getMinimum()); txtCache.setText(""); comboStrgAcc.removeAllItems(); txtHostName.setText(""); } } private void setCachPerMem(int cachVal) { try { waRole.setCacheMemoryPercent(cachVal); isCachPerValid = true; } catch (Exception e) { /* * User has given input * cachVal < 0 or cachVal > 100 */ isCachPerValid = false; } } @NotNull @Override public String getId() { return getDisplayName(); } @Nullable @Override public Runnable enableSearch(String option) { return null; } @Nls @Override public String getDisplayName() { return message("cmhLblCach"); } @Nullable @Override public String getHelpTopic() { return "windows_azure_caching_page"; } @Nullable @Override public JComponent createComponent() { return contentPane; } @Override public void apply() throws ConfigurationException { boolean okToProceed = false; // Check caching is enabled if (cacheCheck.isSelected()) { /* Check cache memory size * is set to valid value or not */ if (isCachPerValid) { okToProceed = true; } else { PluginUtil.displayErrorDialog(message("cachPerErrTtl"), message("cachPerErrMsg")); } } else { okToProceed = true; } if (okToProceed) { try { waProjManager.save(); setModified(false); LocalFileSystem.getInstance().findFileByPath(PluginUtil.getModulePath(module)).refresh(true, true); } catch (WindowsAzureInvalidProjectOperationException e) { AzurePlugin.log(message("adRolErrMsgBox1") + message("adRolErrMsgBox2", e)); throw new ConfigurationException(message("adRolErrMsgBox1") + message("adRolErrMsgBox2"), message("adRolErrTitle")); } } } @Override public void reset() { setModified(false); } @Override public void disposeUIResources() { } /** * Listener method for add button which opens a dialog * to add new cache entry in cache table. */ protected void addBtnListener() { CacheDialog dialog = new CacheDialog(waRole, mapCache, null, false); dialog.show(); if (dialog.isOK()) { setModified(true); String name = dialog.getCacheName(); tblCache.getListTableModel().addRow(mapCache.get(name)); } } /** * Listener method for edit button which opens a dialog * to edit cache entry. */ protected void editBtnListener() { WindowsAzureNamedCache cachEntry = tblCache.getSelectedObject(); CacheDialog dialog = new CacheDialog(waRole, mapCache, cachEntry.getName(), true); dialog.show(); if (dialog.isOK()) { ((CacheTableModel) tblCache.getModel()).fireTableDataChanged(); setModified(true); } } /** * Listener method for remove button which * deletes the selected cache entry. */ protected void removeBtnListener() { try { int choice = Messages.showYesNoDialog(message("cachRmvMsg"), message("cachRmvTtl"), Messages.getQuestionIcon()); if (choice == Messages.YES) { WindowsAzureNamedCache cachToDel = tblCache.getSelectedObject(); cachToDel.delete(); tblCache.getListTableModel().setItems(new ArrayList<WindowsAzureNamedCache>(mapCache.values())); setModified(true); } } catch (WindowsAzureInvalidProjectOperationException e) { PluginUtil.displayErrorDialogAndLog(message("cachErrTtl"), message("cachDelErMsg"), e); } } private void createUIComponents() { tblCache = new TableView<WindowsAzureNamedCache>(); tablePanel = ToolbarDecorator.createDecorator(tblCache, null).setAddAction(new AnActionButtonRunnable() { @Override public void run(AnActionButton button) { addBtnListener(); } }).setEditAction(new AnActionButtonRunnable() { @Override public void run(AnActionButton anActionButton) { editBtnListener(); } }).setRemoveAction(new AnActionButtonRunnable() { @Override public void run(AnActionButton button) { removeBtnListener(); } }).setEditActionUpdater(new AnActionButtonUpdater() { @Override public boolean isEnabled(AnActionEvent e) { return tblCache.getSelectedObject() != null; } }).setRemoveActionUpdater(new AnActionButtonUpdater() { @Override public boolean isEnabled(AnActionEvent e) { return tblCache.getSelectedObject() != null; } }).disableUpDownActions().createPanel(); } private final ColumnInfo<WindowsAzureNamedCache, String> NAME = new ColumnInfo<WindowsAzureNamedCache, String>( message("colChName")) { public String valueOf(WindowsAzureNamedCache object) { return object.getName(); } @Override public void setValue(WindowsAzureNamedCache cache, String modifiedVal) { try { WARCachingUtilMethods.modifyCacheName(cache, modifiedVal, mapCache); setModified(true); } catch (Exception e) { PluginUtil.displayErrorDialog(message("cachNameErrTtl"), e.getMessage()); } } }; private final ColumnInfo<WindowsAzureNamedCache, BACKUP_OPTIONS> HIGH_AVAILABILITY = new ColumnInfo<WindowsAzureNamedCache, BACKUP_OPTIONS>( message("colBkps")) { public BACKUP_OPTIONS valueOf(WindowsAzureNamedCache object) { if (object.getBackups()) { return BACKUP_OPTIONS.Yes; } else { return BACKUP_OPTIONS.No; } } @Override public TableCellEditor getEditor(final WindowsAzureNamedCache cache) { return ComboBoxTableCellEditor.INSTANCE; } @Override public void setValue(WindowsAzureNamedCache cache, BACKUP_OPTIONS modifiedVal) { try { if (modifiedVal.toString().equals(message("cachBckYes"))) { /* * If user selects backup option * then check virtual machine instances > 2 * otherwise give warning */ int vmCnt = 0; try { vmCnt = Integer.parseInt(waRole.getInstances()); } catch (Exception e) { PluginUtil.displayErrorDialogAndLog(message("genErrTitle"), message("vmInstGetErMsg"), e); } if (vmCnt < 2) { /* * If virtual machine instances < 2 * then set back up to false. */ cache.setBackups(false); Messages.showWarningDialog(message("backWarnMsg"), message("backWarnTtl")); } else { cache.setBackups(true); } } else if (modifiedVal.toString().equals(message("cachBckNo"))) { cache.setBackups(false); } setModified(true); } catch (Exception e) { PluginUtil.displayErrorDialogAndLog(message("cachErrTtl"), message("cachSetErrMsg"), e); } } }; private final ColumnInfo<WindowsAzureNamedCache, EXPIRATION_TYPE> EXPIRATION = new ColumnInfo<WindowsAzureNamedCache, EXPIRATION_TYPE>( message("colExp")) { public EXPIRATION_TYPE valueOf(WindowsAzureNamedCache cache) { if (cache.getExpirationPolicy().equals(WindowsAzureCacheExpirationPolicy.NEVER_EXPIRES)) { return EXPIRATION_TYPE.NeverExpires; } else if (cache.getExpirationPolicy().equals(WindowsAzureCacheExpirationPolicy.ABSOLUTE)) { return EXPIRATION_TYPE.Absolute; } else { return EXPIRATION_TYPE.SlidingWindow; } } @Override public TableCellEditor getEditor(final WindowsAzureNamedCache cache) { return ComboBoxTableCellEditor.INSTANCE; } @Override public void setValue(WindowsAzureNamedCache cache, EXPIRATION_TYPE modifiedVal) { try { WARCachingUtilMethods.modifyExpirationPol(cache, String.valueOf(modifiedVal.ordinal())); setModified(true); } catch (Exception e) { PluginUtil.displayErrorDialog(message("cachNameErrTtl"), e.getMessage()); } } }; private final ColumnInfo<WindowsAzureNamedCache, String> MINUTES_TO_LIVE = new ColumnInfo<WindowsAzureNamedCache, String>( message("colMinToLive")) { public String valueOf(WindowsAzureNamedCache cache) { /* * If expiration policy is NEVER_EXPIRES * then show N/A for minutes to Live column */ if (cache.getExpirationPolicy().equals(WindowsAzureCacheExpirationPolicy.NEVER_EXPIRES)) { return message("dlgDbgNA"); } else { return Integer.toString(cache.getMinutesToLive()); } } @Override public void setValue(WindowsAzureNamedCache cache, String modifiedVal) { try { Boolean isVallidMtl = WARCachingUtilMethods.validateMtl(modifiedVal); if (isVallidMtl) { cache.setMinutesToLive(Integer.parseInt(modifiedVal)); setModified(true); } else { PluginUtil.displayErrorDialog(message("cachMtlErrTtl"), message("cachMtlErrMsg")); } } catch (Exception ex) { PluginUtil.displayErrorDialog(message("cachMtlErrTtl"), message("cachMtlErrMsg")); } } }; private final ColumnInfo<WindowsAzureNamedCache, String> PORT = new ColumnInfo<WindowsAzureNamedCache, String>( message("colPort")) { public String valueOf(WindowsAzureNamedCache cache) { try { return cache.getEndpoint().getPrivatePort(); } catch (WindowsAzureInvalidProjectOperationException e) { PluginUtil.displayErrorDialogAndLog(message("cachErrTtl"), message("cachGetErMsg"), e); return ""; } } @Override public void setValue(WindowsAzureNamedCache cache, String modifiedVal) { try { WARCachingUtilMethods.modifyPort(cache, modifiedVal, waRole); } catch (Exception ex) { PluginUtil.displayErrorDialog(message("cachPortErrTtl"), ex.getMessage()); } } }; private class CacheTableModel extends ListTableModel<WindowsAzureNamedCache> { private CacheTableModel(java.util.List<WindowsAzureNamedCache> namedCaches) { super(new ColumnInfo[] { NAME, HIGH_AVAILABILITY, EXPIRATION, MINUTES_TO_LIVE, PORT }, namedCaches); } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return true; } } }