/******************************************************************************* * Copyright (c) 2006-2010 eBay Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 *******************************************************************************/ package org.ebayopensource.turmeric.eclipse.services.ui.properties; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.lang.StringUtils; import org.ebayopensource.turmeric.eclipse.buildsystem.utils.ProjectProtoBufFileUtil; import org.ebayopensource.turmeric.eclipse.buildsystem.utils.PropertiesUtil; import org.ebayopensource.turmeric.eclipse.core.logging.SOALogger; import org.ebayopensource.turmeric.eclipse.core.resources.constants.SOAProjectConstants; import org.ebayopensource.turmeric.eclipse.core.resources.constants.SOAProjectConstants.Binding; import org.ebayopensource.turmeric.eclipse.core.resources.constants.SOAProjectConstants.DataBinding; import org.ebayopensource.turmeric.eclipse.core.resources.constants.SOAProjectConstants.MessageProtocol; import org.ebayopensource.turmeric.eclipse.exception.resources.SOAResourceModifyFailedException; import org.ebayopensource.turmeric.eclipse.repositorysystem.core.GlobalRepositorySystem; import org.ebayopensource.turmeric.eclipse.repositorysystem.core.ISOAAssetRegistry; import org.ebayopensource.turmeric.eclipse.repositorysystem.utils.TurmericServiceUtils; import org.ebayopensource.turmeric.eclipse.resources.model.ISOAConsumerProject.SOAClientConfig; import org.ebayopensource.turmeric.eclipse.resources.model.ISOAConsumerProject.SOAClientEnvironment; import org.ebayopensource.turmeric.eclipse.resources.model.ISOAProject; import org.ebayopensource.turmeric.eclipse.resources.model.ProjectInfo; import org.ebayopensource.turmeric.eclipse.resources.model.SOAIntfProject; import org.ebayopensource.turmeric.eclipse.resources.util.SOAConsumerUtil; import org.ebayopensource.turmeric.eclipse.resources.util.SOAConsumerUtil.EnvironmentItem; import org.ebayopensource.turmeric.eclipse.resources.util.SOAIntfUtil; import org.ebayopensource.turmeric.eclipse.ui.components.SOAConsumerServicesViewer; import org.ebayopensource.turmeric.eclipse.ui.components.SimpleComboBoxEditor; import org.ebayopensource.turmeric.eclipse.utils.io.PropertiesFileUtil; import org.ebayopensource.turmeric.eclipse.utils.plugin.EclipseMessageUtils; import org.ebayopensource.turmeric.eclipse.utils.plugin.ProgressUtil; import org.ebayopensource.turmeric.eclipse.utils.plugin.WorkspaceUtil; import org.ebayopensource.turmeric.eclipse.utils.ui.UIUtil; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.preference.FieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.StringFieldEditor; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Layout; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.IWorkbenchPropertyPage; import org.eclipse.ui.actions.WorkspaceModifyOperation; import org.jdom.JDOMException; /** * @author yayu * */ public class SOAServiceDependenciesPage extends FieldEditorPreferencePage implements IWorkbenchPropertyPage { public static final String REQUIRED_SERVICES_DELIMITER = ","; private IProject project; private boolean isOldClientConfigDirStructure = false; private Map<FieldEditor, Composite> editorParentMap = new ConcurrentHashMap<FieldEditor, Composite>(); // single selection list private SOAConsumerServicesViewer serviceList; private StringFieldEditor serviceLocationEditor; private SimpleComboBoxEditor serviceBindingEditor; private SimpleComboBoxEditor serviceRequestBindingEditor; private SimpleComboBoxEditor serviceResponseBindingEditor; private SimpleComboBoxEditor messageProtocolEditor; private String currentAdminName = null; private boolean currentCanUseProtoBuf = false; private String currentServiceLocation = ""; private static final SOALogger logger = SOALogger.getLogger(); private static String[][] FULL_PROTOCOL_LIST; private static String[][] DEFAULT_PROTOCOL_LIST; private boolean isEnvEmpty = true; static { FULL_PROTOCOL_LIST = new String[DataBinding.values().length][2]; DEFAULT_PROTOCOL_LIST = new String[DataBinding.values().length - 1][2]; int index = 0; int defaultIndex = 0; for (DataBinding binding : DataBinding.values()) { String bindingName = binding.name(); FULL_PROTOCOL_LIST[index][0] = bindingName; FULL_PROTOCOL_LIST[index][1] = bindingName; index++; if ("PROTOBUF".equalsIgnoreCase(bindingName) == false) { DEFAULT_PROTOCOL_LIST[defaultIndex][0] = bindingName; DEFAULT_PROTOCOL_LIST[defaultIndex][1] = bindingName; defaultIndex++; } } } public SOAServiceDependenciesPage() { super(FieldEditorPreferencePage.GRID); noDefaultAndApplyButton(); } @Override protected void createFieldEditors() { if (project != null) { try { addServiceDependenciesList(); // create a group Composite parent = getFieldEditorParent(); Group group = new Group(parent, SWT.NONE); group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1));// why 2? 2 is the max num of controls group.setText("Client Config Details"); // add controls in the group addServiceLocation(group); addServiceBinding(group); addServiceRequestDataBinding(group); addServiceResponseDataBinding(group); addMessageProtocol(group); /* * Do not move the following 6 lines of code above, the * createControl method of FieldEditor would always create a new * layout for group. so we create a new layout after all * controls are inited and thus re-layout the page. */ GridLayout layout = new GridLayout(2, false); initGridLayout(layout, true); group.setLayout(layout); Layout parentLayout = parent.getLayout(); if (parentLayout instanceof GridLayout) { ((GridLayout) parentLayout).verticalSpacing = 12; } } catch (Exception e) { logger.error(e); UIUtil.showErrorDialog(e); } } } private GridLayout initGridLayout(GridLayout layout, boolean margins) { layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); if (margins) { layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); } else { layout.marginWidth = 0; layout.marginHeight = 0; } return layout; } public IAdaptable getElement() { return null; } private SOAClientEnvironment getCurrentSelectedService() { if (serviceList != null && serviceList.getTree().getSelectionCount() == 1) { TreeItem item = serviceList.getTree().getSelection()[0]; if (item.getParentItem() == null) return null; Object parentObj = item.getParentItem().getData(); currentAdminName = item.getData().toString(); if (parentObj instanceof EnvironmentItem) { String envName = isOldClientConfigDirStructure ? null : ((EnvironmentItem) parentObj).getName(); return new SOAClientEnvironment(envName, currentAdminName); } } return null; } private void addServiceDependenciesList() throws CoreException, IOException { Composite parent = getFieldEditorParent(); /* * { Composite composite = new Composite(parent, SWT.NONE); * composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); * composite.setLayout(new GridLayout(2, false)); Label label = new * Label(composite, SWT.NONE); label.setText("Client Name:"); Text text * = new Text(composite, SWT.BORDER); text.setEditable(false); * text.setText(SOAConsumerUtil.getServiceClientName(project)); * text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); } */ final Group listComposite = new Group(parent, SWT.NONE); GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1); gridData.heightHint = 200; listComposite.setLayoutData(gridData); listComposite.setLayout(new GridLayout(1, false)); listComposite.setText("Client Configurations"); serviceList = new SOAConsumerServicesViewer(listComposite, false); List<EnvironmentItem> envList = SOAConsumerUtil .getClientConfigStructure(project); isEnvEmpty = envList == null || envList.isEmpty(); serviceList.setInput(envList); this.serviceList .addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { try { load(); } catch (Exception eX) { logger.error(eX); UIUtil.showErrorDialog(eX); } } }); } private void addServiceLocation(Group group) { serviceLocationEditor = new StringFieldEditor("", "Service Location: ", group); // serviceLocationEditor.getTextControl(group).setEnabled(false); editorParentMap.put(serviceLocationEditor, group); addField(serviceLocationEditor); } @Override protected void initialize() { super.initialize(); try { isOldClientConfigDirStructure = SOAConsumerUtil .isOldClientConfigDirStructure(project); if (isOldClientConfigDirStructure) { String message = GlobalRepositorySystem.instanceOf() .getActiveRepositorySystem().getProjectHealthChecker() .getWarningMessageConsumeProjectStructureOld(); setMessage(message, IStatus.WARNING); } } catch (CoreException e) { logger.warning(e); } if (this.serviceList != null && this.serviceList.getTree().getItemCount() > 0) { TreeItem item = this.serviceList.getTree().getItem(0); if (item.getData() instanceof EnvironmentItem && item.getItemCount() > 0) { item = item.getItem(0); } this.serviceList.getTree().setSelection(item); try { load(); } catch (Exception e) { logger.error(e); UIUtil.showErrorDialog(e); } } else { setFieldEditorEnabled(false, true); } } private void load() throws IOException, JDOMException { final SOAClientEnvironment clientEnv = getCurrentSelectedService(); if (clientEnv == null) { // currently selected is the environment setFieldEditorEnabled(false, true); return; } SOAClientConfig config = null; try { if (isOldClientConfigDirStructure) { config = SOAConsumerUtil.loadClientConfig(project, null, clientEnv.getServiceName()); } else { config = SOAConsumerUtil.loadClientConfig(project, clientEnv.getEnvironment(), clientEnv.getServiceName()); } } catch (CoreException e) { logger.error(e); } if (config != null) { final String serviceLocation = config != null && config.getServiceLocation() != null ? config .getServiceLocation() : ""; currentServiceLocation = serviceLocation; currentCanUseProtoBuf = validateProtoBuf(serviceLocation); String[][] nvPares = DEFAULT_PROTOCOL_LIST; if (currentCanUseProtoBuf == true) { nvPares = FULL_PROTOCOL_LIST; } final String serviceBinding = config != null && config.getServiceBinding() != null ? config .getServiceBinding() : Binding.LOCAL.name(); final String requestBinding = config != null && config.getRequestDataBinding() != null ? config .getRequestDataBinding() : DataBinding.XML.name(); final String responseBinding = config != null && config.getResponseDataBinding() != null ? config .getResponseDataBinding() : DataBinding.XML.name(); final String messageProtocol = config != null && config.getMessageProtocol() != null ? config .getMessageProtocol() : MessageProtocol.NONE.name(); serviceLocationEditor.setStringValue(serviceLocation); serviceRequestBindingEditor.updateProtocolList(requestBinding, nvPares); serviceResponseBindingEditor.updateProtocolList(responseBinding, nvPares); // serviceRequestBindingEditor.getComboBoxControl( // editorParentMap.get(serviceRequestBindingEditor)).setText( // requestBinding); // serviceResponseBindingEditor.getComboBoxControl( // editorParentMap.get(serviceResponseBindingEditor)).setText( // responseBinding); messageProtocolEditor.getComboBoxControl( editorParentMap.get(messageProtocolEditor)).setText( messageProtocol); // invoke this so that the modify listener will be triggered. serviceBindingEditor.getComboBoxControl( editorParentMap.get(serviceBindingEditor)).setText( serviceBinding); setFieldEditorEnabled(true, false); } } private boolean validateProtoBuf(String serviceLocation) { try { // if this project is intf project and have nonXSDFormats=protobuf // in sipp, return true; IProject project = WorkspaceUtil.getProject(currentAdminName); if (project.isAccessible() == true) { ISOAProject soaProject = GlobalRepositorySystem.instanceOf() .getActiveRepositorySystem().getAssetRegistry() .getSOAProject(project); if (soaProject instanceof SOAIntfProject) { IFile sipp = project .getFile(SOAProjectConstants.PROPS_FILE_SERVICE_INTERFACE); if (sipp.isAccessible()) { String noXSDSchema = PropertiesFileUtil .getPropertyValueByKey( sipp.getContents(), SOAProjectConstants.PROP_KEY_NON_XSD_FORMATS); if (noXSDSchema != null && noXSDSchema .contains(SOAProjectConstants.SVC_PROTOCOL_BUF)) { return true; } } return false; } } // try to find service in service jar String noXSDSchema = getValueFromServiceProps(currentAdminName, SOAProjectConstants.PROP_KEY_NON_XSD_FORMATS); if (noXSDSchema != null && noXSDSchema .contains(SOAProjectConstants.SVC_PROTOCOL_BUF)) { return true; } // try to access service location?proto String content = ProjectProtoBufFileUtil .getProtoBufFile(serviceLocation); return StringUtils.isNotBlank(content); } catch (Exception e) { return false; } } private static String getValueFromServiceProps(final String serviceName, final String key) throws Exception { final ISOAAssetRegistry registry = GlobalRepositorySystem.instanceOf() .getActiveRepositorySystem().getAssetRegistry(); final String assetLocation = registry.getAssetLocation(serviceName); final Properties props = SOAIntfUtil.loadMetadataProps(assetLocation, serviceName); if (props != null) { return StringUtils.trim(props.getProperty(key)); } return null; } private void setFieldEditorEnabled(boolean enabled, boolean clearData) { for (FieldEditor editor : editorParentMap.keySet()) { if (editor instanceof SimpleComboBoxEditor) { ((SimpleComboBoxEditor) editor).getComboBoxControl( editorParentMap.get(editor)).setEnabled(enabled); if (clearData == true) ((SimpleComboBoxEditor) editor).getComboBoxControl( editorParentMap.get(editor)).clearSelection(); } else if (editor instanceof StringFieldEditor) { ((StringFieldEditor) editor).getTextControl( editorParentMap.get(editor)).setEnabled(enabled); if (clearData == true) ((StringFieldEditor) editor).getTextControl( editorParentMap.get(editor)).setText(""); } } } private void addServiceBinding(Group group) { String strArray[][] = new String[Binding.values().length][2]; int index = 0; for (Binding binding : Binding.values()) { strArray[index][0] = binding.name(); strArray[index][1] = binding.name(); index++; } serviceBindingEditor = new SimpleComboBoxEditor("", "Service Binding:", strArray, group); addField(serviceBindingEditor); editorParentMap.put(serviceBindingEditor, group); final Combo bindingList = serviceBindingEditor .getComboBoxControl(editorParentMap.get(serviceBindingEditor)); bindingList.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { String bindingStr = bindingList.getText(); Text svcLoctext = serviceLocationEditor .getTextControl(editorParentMap .get(serviceLocationEditor)); if (Binding.LOCAL.name().equals(bindingStr)) { svcLoctext.setText(currentServiceLocation); svcLoctext.setEditable(false); } else { svcLoctext.setEditable(true); } } }); } private void addServiceRequestDataBinding(Group group) { serviceRequestBindingEditor = new SimpleComboBoxEditor("", "Request DataBinding:", FULL_PROTOCOL_LIST, group); addField(serviceRequestBindingEditor); editorParentMap.put(serviceRequestBindingEditor, group); } private void addServiceResponseDataBinding(Group group) { serviceResponseBindingEditor = new SimpleComboBoxEditor("", "Response DataBinding:", FULL_PROTOCOL_LIST, group); addField(serviceResponseBindingEditor); editorParentMap.put(serviceResponseBindingEditor, group); } private IStatus validateProtocol() { if (currentCanUseProtoBuf == true) { return Status.OK_STATUS; } String newRequestDataBinding = getText(serviceRequestBindingEditor); String newResponseDataBinding = getText(serviceResponseBindingEditor); if ("protobuf".equalsIgnoreCase(newRequestDataBinding) || "protobuf".equalsIgnoreCase(newResponseDataBinding)) { return EclipseMessageUtils.createErrorStatus( "ProtoBuf is not supported by current service.", null); } return Status.OK_STATUS; } private void addMessageProtocol(Group group) { String strArray[][] = new String[MessageProtocol.values().length][2]; int index = 0; for (MessageProtocol protocol : MessageProtocol.values()) { strArray[index][0] = protocol.name(); strArray[index][1] = protocol.name(); index++; } messageProtocolEditor = new SimpleComboBoxEditor("", "Message Protocol:", strArray, group); addField(messageProtocolEditor); editorParentMap.put(messageProtocolEditor, group); } public void setElement(IAdaptable element) { try { if (element.getAdapter(IProject.class) instanceof IProject) { project = (IProject) element.getAdapter(IProject.class); } } catch (Exception exception) { logger.error(exception); UIUtil.showErrorDialog(exception); } } private String getText(StringFieldEditor stringFieldEditor) { return stringFieldEditor.getTextControl( editorParentMap.get(stringFieldEditor)).getText(); } private String getText(SimpleComboBoxEditor simpleComboEditor) { return simpleComboEditor.getComboBoxControl( editorParentMap.get(simpleComboEditor)).getText(); } @Override public boolean performOk() { try { // so we should collect all required information right now. final SOAClientEnvironment clientEnv = getCurrentSelectedService(); if (clientEnv == null) // no service selected return true; final String serviceName = clientEnv.getServiceName(); final String newServiceLocation = getText(serviceLocationEditor); final String newServiceBinding = getText(serviceBindingEditor); final String newMessageProtocol = getText(messageProtocolEditor); final String newRequestDataBinding = getText(serviceRequestBindingEditor); final String newResponseDataBinding = getText(serviceResponseBindingEditor); final String[] requiredServices = {};// serviceList.getItems(); final ProjectInfo intfProjectInfo = GlobalRepositorySystem .instanceOf().getActiveRepositorySystem() .getAssetRegistry().getProjectInfo(serviceName); final String implProjectName = intfProjectInfo .getImplementationProjectName(); IStatus status = PropertiesUtil.validate(serviceName, implProjectName, newServiceLocation, newServiceBinding); IStatus statusProtocol = validateProtocol(); if (statusProtocol != Status.OK_STATUS) { setErrorMessage(status.getMessage()); Throwable t = null; UIUtil.showErrorDialog(getShell(), "Validation Failed", status.getMessage(), t); return false; } if (status == Status.OK_STATUS) { setErrorMessage(null); final WorkspaceModifyOperation operation = new WorkspaceModifyOperation() { @Override protected void execute(IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException { monitor.beginTask( "Modifying the properties and dependencies for SOA service -> " + serviceName, ProgressUtil.PROGRESS_STEP * 15); try { PropertiesUtil.modifyServiceDependencies(project, clientEnv.getEnvironment(), serviceName, implProjectName, newServiceLocation, newServiceBinding, newMessageProtocol, newRequestDataBinding, newResponseDataBinding, requiredServices, monitor); } catch (Exception e) { throw new SOAResourceModifyFailedException( "Failed to modify dependencies and/or properties for SOA service -> " + serviceName, e); } finally { monitor.done(); } } }; new ProgressMonitorDialog(getControl().getShell()).run(true, true, operation); } else { setErrorMessage(status.getMessage()); Throwable t = null; UIUtil.showErrorDialog(getShell(), "Validation Failed", status.getMessage(), t); } } catch (Exception e) { logger.error(e); UIUtil.showErrorDialog(e); return false; } return true; } @Override protected void checkState() { try { if (TurmericServiceUtils.isSOAImplProject(project)) { // if the underlying project is impl, we should skip the // validation. return; } } catch (CoreException e) { logger.error(e); UIUtil.showErrorDialog(e); } super.checkState(); if (isValid() == false && isEnvEmpty == true) { setValid(true); } } }