/** * Copyright (c) 2011, 2013 Gunnar Wagenknecht and others. * All rights reserved. * * This program and the accompanying materials are made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Gunnar Wagenknecht - initial API and implementation * Andreas Mihm - rework new admin ui */ package org.eclipse.gyrex.admin.ui.http.internal; import java.text.Collator; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.SortedMap; import java.util.TreeMap; import java.util.TreeSet; import org.eclipse.gyrex.admin.ui.internal.widgets.NonBlockingStatusDialog; import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.ComboDialogField; import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.DialogField; import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.IDialogFieldListener; import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.IListAdapter; import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.LayoutUtil; import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.ListDialogField; import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.ListDialogField.ColumnsDescription; import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.Separator; import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.StringDialogField; import org.eclipse.gyrex.common.identifiers.IdHelper; import org.eclipse.gyrex.context.IRuntimeContext; import org.eclipse.gyrex.context.definitions.ContextDefinition; import org.eclipse.gyrex.context.internal.ContextActivator; import org.eclipse.gyrex.context.registry.IRuntimeContextRegistry; import org.eclipse.gyrex.http.internal.HttpActivator; import org.eclipse.gyrex.http.internal.application.manager.ApplicationManager; import org.eclipse.gyrex.http.internal.application.manager.ApplicationProviderRegistration; import org.eclipse.gyrex.http.internal.application.manager.ApplicationRegistration; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.fieldassist.ContentProposal; import org.eclipse.jface.fieldassist.IContentProposal; import org.eclipse.jface.fieldassist.IContentProposalProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.jface.window.Window; import org.eclipse.rap.rwt.widgets.DialogCallback; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.apache.commons.lang.StringUtils; @SuppressWarnings("restriction") public class EditApplicationDialog extends NonBlockingStatusDialog { private static final class PropertiesFieldLabelProvider extends LabelProvider implements ITableLabelProvider { /** serialVersionUID */ private static final long serialVersionUID = 1L; @Override public Image getColumnImage(final Object element, final int columnIndex) { // no image return null; } @Override public String getColumnText(final Object element, final int columnIndex) { if (element instanceof String[]) return ((String[]) element)[columnIndex]; return getText(element); } } /** serialVersionUID */ private static final long serialVersionUID = 1L; private final StringDialogField idField = new StringDialogField(); private final ComboDialogField providerField = new ComboDialogField(SWT.DROP_DOWN | SWT.READ_ONLY); private final Map<String, String> providerItemToIdMap = new HashMap<String, String>(); private final StringDialogField contextPathField = new StringDialogField(); private final ListDialogField propertiesField; { propertiesField = new ListDialogField(new IListAdapter() { @Override public void customButtonPressed(final ListDialogField field, final int index) { switch (index) { case 0: addNewProperty(); break; case 1: editSelectedProperty(); break; } } @Override public void doubleClicked(final ListDialogField field) { editSelectedProperty(); } @Override public void selectionChanged(final ListDialogField field) { // nothing to do } }, new String[] { "Add...", "Edit...", "Remove" }, new PropertiesFieldLabelProvider()) { @Override protected int getListStyle() { return SWT.BORDER | SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION; } }; propertiesField.setRemoveButtonIndex(2); propertiesField.setTableColumns(new ColumnsDescription(new String[] { "Key", "Value" }, true)); } private final ListDialogField mountsField; { mountsField = new ListDialogField(new IListAdapter() { @Override public void customButtonPressed(final ListDialogField field, final int index) { switch (index) { case 0: addNewMount(); break; } } @Override public void doubleClicked(final ListDialogField field) { editSelectedProperty(); } @Override public void selectionChanged(final ListDialogField field) { // nothing to do } }, new String[] { "Add...", "Remove" }, new LabelProvider()); mountsField.setRemoveButtonIndex(1); mountsField.setViewerComparator(new ViewerComparator(Collator.getInstance(Locale.US))); } private final ApplicationManager applicationManager; private final SortedMap<String, String> applicationProperties = new TreeMap<String, String>(); private final ApplicationRegistration applicationRegistration; /** * Creates a new instance. * * @param parent */ public EditApplicationDialog(final Shell parent, final ApplicationManager applicationManager, final ApplicationRegistration applicationRegistration) { super(parent); this.applicationManager = applicationManager; this.applicationRegistration = applicationRegistration; setTitle(null == applicationRegistration ? "New Application" : "Edit Application"); setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.APPLICATION_MODAL); } void addNewMount() { final MountApplicationDialog dialog = new MountApplicationDialog(getParentShell()); dialog.openNonBlocking(new DialogCallback() { /** serialVersionUID */ private static final long serialVersionUID = 1L; @Override public void dialogClosed(final int returnCode) { if (returnCode == Window.OK) { mountsField.addElement(dialog.getUrl().toExternalForm()); } } }); } void addNewProperty() { final EditPropertyDialog dialog = new EditPropertyDialog(getParentShell(), null, null); dialog.openNonBlocking(new DialogCallback() { /** serialVersionUID */ private static final long serialVersionUID = 1L; @Override public void dialogClosed(final int returnCode) { if (returnCode == Window.OK) { applicationProperties.put(dialog.getKey(), dialog.getValue()); refreshProperties(); } } }); } @Override protected Control createDialogArea(final Composite parent) { final Composite composite = (Composite) super.createDialogArea(parent); final GridData gd = (GridData) composite.getLayoutData(); gd.minimumHeight = convertVerticalDLUsToPixels(200); gd.minimumWidth = convertHorizontalDLUsToPixels(400); idField.setLabelText("Id"); contextPathField.setLabelText("Context"); providerField.setLabelText("Provider"); final IDialogFieldListener validateListener = new IDialogFieldListener() { @Override public void dialogFieldChanged(final DialogField field) { validate(); } }; idField.setDialogFieldListener(validateListener); contextPathField.setDialogFieldListener(validateListener); providerField.setDialogFieldListener(validateListener); providerItemToIdMap.clear(); final TreeSet<String> providerItems = new TreeSet<String>(); final Collection<ApplicationProviderRegistration> providers = HttpActivator.getInstance().getProviderRegistry().getRegisteredProviders().values(); for (final ApplicationProviderRegistration registration : providers) { final String label = HttpUiAdapter.getLabel(registration); providerItemToIdMap.put(label, registration.getProviderId()); providerItems.add(label); } providerField.setItems(providerItems.toArray(new String[providerItems.size()])); contextPathField.setContentProposalProcessor(new IContentProposalProvider() { /** serialVersionUID */ private static final long serialVersionUID = 1L; @Override public IContentProposal[] getProposals(final String contents, final int position) { final List<IContentProposal> resultList = new ArrayList<IContentProposal>(); final String patternString = StringUtils.trimToNull(StringUtils.substring(contents, 0, position)); final Collection<ContextDefinition> contexts = ContextActivator.getInstance().getContextRegistryImpl().getDefinedContexts(); for (final ContextDefinition contextDefinition : contexts) { if ((null == patternString) || StringUtils.contains(contextDefinition.getPath().toString(), patternString)) { resultList.add(new ContentProposal(contextDefinition.getPath().toString(), contextDefinition.toString())); } } return resultList.toArray(new IContentProposal[resultList.size()]); } }); propertiesField.setLabelText("Properties"); mountsField.setLabelText("Mounts"); final Text warning = new Text(composite, SWT.WRAP | SWT.READ_ONLY); warning.setText("Warning: this dialog is ugly. Please help us improve the UI. Any mockups and/or patches are very much appreciated!"); warning.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false)); LayoutUtil.doDefaultLayout(composite, new DialogField[] { new Separator(), idField, providerField, contextPathField, new Separator(), propertiesField, mountsField }, false); LayoutUtil.setHorizontalGrabbing(idField.getTextControl(null)); LayoutUtil.setHorizontalGrabbing(providerField.getComboControl(null)); LayoutUtil.setHorizontalGrabbing(contextPathField.getTextControl(null)); LayoutUtil.setHorizontalGrabbing(propertiesField.getListControl(null)); LayoutUtil.setHorizontalGrabbing(mountsField.getListControl(null)); if (null != applicationRegistration) { idField.setText(applicationRegistration.getApplicationId()); idField.setEnabled(false); contextPathField.setText(applicationRegistration.getContext().getContextPath().toString()); contextPathField.setEnabled(false); for (final Entry<String, String> e : providerItemToIdMap.entrySet()) { if (e.getValue().equals(applicationRegistration.getProviderId())) { providerField.selectItem(e.getKey()); } } providerField.setEnabled(false); applicationProperties.putAll(applicationRegistration.getInitProperties()); mountsField.setElements(applicationManager.getMounts(applicationRegistration.getApplicationId())); } refreshProperties(); final GridLayout masterLayout = (GridLayout) composite.getLayout(); masterLayout.marginWidth = 5; masterLayout.marginHeight = 5; LayoutUtil.setHorizontalSpan(warning, masterLayout.numColumns); return composite; } void editSelectedProperty() { final List selectedElements = propertiesField.getSelectedElements(); if (selectedElements.isEmpty()) return; final String[] elem = (String[]) selectedElements.get(0); final EditPropertyDialog dialog = new EditPropertyDialog(getParentShell(), elem[0], elem[1]); dialog.openNonBlocking(new DialogCallback() { /** serialVersionUID */ private static final long serialVersionUID = 1L; @Override public void dialogClosed(final int returnCode) { if (returnCode == Window.OK) { applicationProperties.put(dialog.getKey(), dialog.getValue()); refreshProperties(); } } }); } @Override protected void okPressed() { validate(); if (!getStatus().isOK()) return; try { // refresh properties applicationProperties.clear(); for (final Object property : propertiesField.getElements()) { applicationProperties.put(((String[]) property)[0], ((String[]) property)[1]); } // create/update application if (null == applicationRegistration) { final String id = idField.getText(); final String providerId = providerItemToIdMap.get(providerField.getText()); final String contextPath = contextPathField.getText(); final IRuntimeContext context = HttpUiActivator.getInstance().getService(IRuntimeContextRegistry.class).get(new Path(contextPath).makeAbsolute().addTrailingSeparator()); applicationManager.register(id, providerId, context, applicationProperties); } else { applicationManager.setProperties(applicationRegistration.getApplicationId(), applicationProperties); } // update mounts final List applicationMounts = mountsField.getElements(); final Collection<String> existingMounts = null != applicationRegistration ? applicationManager.getMounts(applicationRegistration.getApplicationId()) : new ArrayList<String>(1); for (final String url : existingMounts) { if (!applicationMounts.contains(url)) { applicationManager.unmount(url); } } for (final Object url : applicationMounts) { if (!existingMounts.contains(url)) { applicationManager.mount((String) url, null != applicationRegistration ? applicationRegistration.getApplicationId() : idField.getText()); } } } catch (final Exception e) { ErrorDialog.openError(getParentShell(), "Error", "An error occured saving the application.", getStatus()); // don't abort, i.e. close window } super.okPressed(); } private void refreshProperties() { final List<String[]> elements = new ArrayList<String[]>(applicationProperties.size()); for (final Entry<String, String> entry : applicationProperties.entrySet()) { elements.add(new String[] { entry.getKey(), entry.getValue() }); } propertiesField.setElements(elements); } void setError(final String message) { updateStatus(new Status(IStatus.ERROR, HttpUiActivator.SYMBOLIC_NAME, message)); getShell().pack(true); } void setInfo(final String message) { updateStatus(new Status(IStatus.INFO, HttpUiActivator.SYMBOLIC_NAME, message)); } void setWarning(final String message) { updateStatus(new Status(IStatus.WARNING, HttpUiActivator.SYMBOLIC_NAME, message)); } void validate() { final String id = idField.getText(); if (StringUtils.isBlank(id)) { setInfo("Please enter an id."); return; } if (!IdHelper.isValidId(id)) { setError("The entered id is invalid. It may only contain ASCII chars a-z, 0-9, '.', '-' and/or '_'."); return; } final String providerLabel = providerField.getText(); if (StringUtils.isBlank(providerLabel)) { setInfo("Please select a provider."); return; } final String path = contextPathField.getText(); if (StringUtils.isBlank(path)) { setInfo("Please enter a context path."); return; } if (!Path.EMPTY.isValidPath(path)) { setError("The entered context path is invalid. It may only contain ASCII chars a-z, 0-9, '.', '-' and/or '_' and '/' as separator."); return; } final IRuntimeContextRegistry registry = HttpUiActivator.getInstance().getService(IRuntimeContextRegistry.class); final IRuntimeContext context = registry.get(new Path(path)); if (null == context) { setError("The context is not defined!"); return; } updateStatus(Status.OK_STATUS); } }