/******************************************************************************* * Copyright (c) 2017 Alex Xu 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: * Alex Xu - initial API and implementation *******************************************************************************/ package org.eclipse.php.internal.server.ui.builtin.editor; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.osgi.util.NLS; import org.eclipse.php.internal.server.core.builtin.IPHPServer; import org.eclipse.php.internal.server.core.builtin.PHPServer; import org.eclipse.php.internal.server.core.builtin.command.SetDocumentRootDirectoryCommand; import org.eclipse.php.internal.server.core.builtin.command.SetTestEnvironmentCommand; import org.eclipse.php.internal.server.ui.builtin.Messages; import org.eclipse.php.internal.server.ui.builtin.PHPServerUIPlugin; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.forms.IFormColors; import org.eclipse.ui.forms.widgets.ExpandableComposite; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.Section; import org.eclipse.ui.help.IWorkbenchHelpSystem; import org.eclipse.wst.server.core.IPublishListener; import org.eclipse.wst.server.core.IRuntime; import org.eclipse.wst.server.core.IServer; import org.eclipse.wst.server.core.util.PublishAdapter; import org.eclipse.wst.server.ui.editor.ServerEditorSection; public class DocumentRootEditorSection extends ServerEditorSection { protected Section section; protected PHPServer phpServer; protected Button serverDirMetadata; protected Button serverDirCustom; protected Text serverDir; protected Button serverDirBrowse; protected boolean updating; protected PropertyChangeListener listener; protected IPublishListener publishListener; protected IPath workspacePath; protected boolean allowRestrictedEditing; protected IPath tempDirPath; protected IPath installDirPath; // Avoid hardcoding this at some point private final static String METADATADIR = ".metadata"; //$NON-NLS-1$ /** * ServerGeneralEditorPart constructor comment. */ public DocumentRootEditorSection() { } /** * Add listeners to detect undo changes and publishing of the server. */ protected void addChangeListeners() { listener = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent event) { if (updating) return; updating = true; if (IPHPServer.PROPERTY_DOCUMENT_ROOT_DIR.equals(event.getPropertyName())) { updateServerDirButtons(); updateServerDirFields(); validate(); } updating = false; } }; server.addPropertyChangeListener(listener); publishListener = new PublishAdapter() { @Override public void publishFinished(IServer server2, IStatus status) { boolean flag = false; if (status.isOK() && server2.getModules().length == 0) flag = true; if (flag != allowRestrictedEditing) { allowRestrictedEditing = flag; // Update the state of the fields PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { @Override public void run() { boolean customServerDir = false; if (!DocumentRootEditorSection.this.serverDirCustom.isDisposed()) customServerDir = DocumentRootEditorSection.this.serverDirCustom.getSelection(); if (!DocumentRootEditorSection.this.serverDirMetadata.isDisposed()) DocumentRootEditorSection.this.serverDirMetadata.setEnabled(allowRestrictedEditing); if (!DocumentRootEditorSection.this.serverDirCustom.isDisposed()) DocumentRootEditorSection.this.serverDirCustom.setEnabled(allowRestrictedEditing); if (!DocumentRootEditorSection.this.serverDir.isDisposed()) DocumentRootEditorSection.this.serverDir .setEnabled(allowRestrictedEditing && customServerDir); if (!DocumentRootEditorSection.this.serverDirBrowse.isDisposed()) DocumentRootEditorSection.this.serverDirBrowse .setEnabled(allowRestrictedEditing && customServerDir); } }); } } }; server.getOriginal().addPublishListener(publishListener); } /** * Creates the SWT controls for this workbench part. * * @param parent * the parent control */ @Override public void createSection(Composite parent) { super.createSection(parent); FormToolkit toolkit = getFormToolkit(parent.getDisplay()); section = toolkit.createSection(parent, ExpandableComposite.TWISTIE | ExpandableComposite.EXPANDED | ExpandableComposite.TITLE_BAR | Section.DESCRIPTION | ExpandableComposite.FOCUS_TITLE); section.setText(Messages.serverEditorLocationsSection); section.setDescription(Messages.serverEditorLocationsDescription); section.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL)); Composite composite = toolkit.createComposite(section); GridLayout layout = new GridLayout(); layout.numColumns = 3; layout.marginHeight = 5; layout.marginWidth = 10; layout.verticalSpacing = 5; layout.horizontalSpacing = 15; composite.setLayout(layout); composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_FILL)); IWorkbenchHelpSystem whs = PlatformUI.getWorkbench().getHelpSystem(); // whs.setHelp(composite, ContextIds.SERVER_EDITOR); // whs.setHelp(section, ContextIds.SERVER_EDITOR); toolkit.paintBordersFor(composite); section.setClient(composite); serverDirMetadata = toolkit.createButton(composite, Messages.serverEditorServerDirMetadata, SWT.RADIO); GridData data = new GridData(SWT.FILL, SWT.CENTER, true, false); data.horizontalSpan = 3; serverDirMetadata.setLayoutData(data); serverDirMetadata.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (updating || !serverDirMetadata.getSelection()) return; updating = true; execute(new SetTestEnvironmentCommand(phpServer)); updateServerDirFields(); updating = false; validate(); } }); serverDirCustom = toolkit.createButton(composite, Messages.serverEditorServerDirCustom, SWT.RADIO); data = new GridData(SWT.FILL, SWT.CENTER, true, false); data.horizontalSpan = 3; serverDirCustom.setLayoutData(data); serverDirCustom.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (updating || !serverDirCustom.getSelection()) return; updating = true; execute(new SetTestEnvironmentCommand(phpServer)); updateServerDirFields(); updating = false; validate(); } }); // server directory Label label = createLabel(toolkit, composite, Messages.serverEditorServerDir); data = new GridData(SWT.BEGINNING, SWT.CENTER, false, false); label.setLayoutData(data); serverDir = toolkit.createText(composite, null, SWT.SINGLE); data = new GridData(SWT.FILL, SWT.CENTER, true, false); data.widthHint = 75; serverDir.setLayoutData(data); serverDir.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { if (updating) return; updating = true; execute(new SetDocumentRootDirectoryCommand(phpServer, getServerDir())); updating = false; validate(); } }); serverDirBrowse = toolkit.createButton(composite, Messages.editorBrowse, SWT.PUSH); serverDirBrowse.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent se) { DirectoryDialog dialog = new DirectoryDialog(serverDir.getShell()); dialog.setMessage(Messages.serverEditorBrowseDeployMessage); dialog.setFilterPath(serverDir.getText()); String selectedDirectory = dialog.open(); if (selectedDirectory != null && !selectedDirectory.equals(serverDir.getText())) { updating = true; // Make relative if relative to the workspace IPath path = new Path(selectedDirectory); if (workspacePath.isPrefixOf(path)) { int cnt = path.matchingFirstSegments(workspacePath); path = path.removeFirstSegments(cnt).setDevice(null); selectedDirectory = path.toOSString(); } execute(new SetDocumentRootDirectoryCommand(phpServer, selectedDirectory)); updateServerDirButtons(); updateServerDirFields(); updating = false; validate(); } } }); serverDirBrowse.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false)); initialize(); } protected Label createLabel(FormToolkit toolkit, Composite parent, String text) { Label label = toolkit.createLabel(parent, text); label.setForeground(toolkit.getColors().getColor(IFormColors.TITLE)); return label; } /** * @see ServerEditorSection#dispose() */ @Override public void dispose() { if (server != null) { server.removePropertyChangeListener(listener); if (server.getOriginal() != null) server.getOriginal().removePublishListener(publishListener); } } /** * @see ServerEditorSection#init(IEditorSite, IEditorInput) */ @Override public void init(IEditorSite site, IEditorInput input) { super.init(site, input); // Cache workspace and default deploy paths IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); workspacePath = root.getLocation(); if (server != null) { phpServer = (PHPServer) server.loadAdapter(PHPServer.class, null); addChangeListeners(); } initialize(); } /** * Initialize the fields in this editor. */ protected void initialize() { if (serverDir == null || phpServer == null) return; updating = true; IRuntime runtime = server.getRuntime(); if (runtime != null) installDirPath = runtime.getLocation(); // determine if editing of locations is allowed allowRestrictedEditing = false; IPath basePath = phpServer.getRuntimeBaseDirectory(); if (!readOnly) { // If server has not been published, or server is published with no // modules, allow editing // TODO Find better way to determine if server hasn't been published if ((basePath != null && !basePath.append("conf").toFile().exists()) //$NON-NLS-1$ || (server.getOriginal().getServerPublishState() == IServer.PUBLISH_STATE_NONE && server.getOriginal().getModules().length == 0)) { allowRestrictedEditing = true; } } // Update server related fields updateServerDirButtons(); updateServerDirFields(); serverDirMetadata.setEnabled(allowRestrictedEditing); serverDirCustom.setEnabled(allowRestrictedEditing); updating = false; validate(); } protected String getServerDir() { String dir = null; if (serverDir != null) { dir = serverDir.getText().trim(); IPath path = new Path(dir); // Adjust if the temp dir is known and has been entered if (tempDirPath != null && tempDirPath.equals(path)) dir = null; // If under the workspace, make relative else if (workspacePath.isPrefixOf(path)) { int cnt = path.matchingFirstSegments(workspacePath); path = path.removeFirstSegments(cnt).setDevice(null); dir = path.toOSString(); } } return dir; } protected void updateServerDirButtons() { if (phpServer.getDocumentRootDirectory() == null) { IPath path = phpServer.getRuntimeBaseDirectory(); if (path != null && path.equals(installDirPath)) { serverDirMetadata.setSelection(false); serverDirCustom.setSelection(false); } else { serverDirMetadata.setSelection(true); serverDirCustom.setSelection(false); } } else { serverDirCustom.setSelection(true); serverDirMetadata.setSelection(false); } } protected void updateServerDirFields() { updateServerDir(); boolean customServerDir = serverDirCustom.getSelection(); serverDir.setEnabled(allowRestrictedEditing && customServerDir); serverDirBrowse.setEnabled(allowRestrictedEditing && customServerDir); } protected void updateServerDir() { IPath path = phpServer.getRuntimeBaseDirectory(); if (path == null) serverDir.setText(""); //$NON-NLS-1$ else if (workspacePath.isPrefixOf(path)) { int cnt = path.matchingFirstSegments(workspacePath); path = path.removeFirstSegments(cnt).setDevice(null); serverDir.setText(path.toOSString()); // cache the relative temp dir path if that is what we have if (tempDirPath == null) { if (phpServer.getDocumentRootDirectory() == null) tempDirPath = path; } } else serverDir.setText(path.toOSString()); } /** * @see ServerEditorSection#getSaveStatus() */ @Override public IStatus[] getSaveStatus() { if (phpServer != null) { // Check the instance directory String dir = phpServer.getDocumentRootDirectory(); if (dir != null) { IPath path = new Path(dir); // Must not be the same as the workspace location if (dir.length() == 0 || workspacePath.equals(path)) { return new IStatus[] { new Status(IStatus.ERROR, PHPServerUIPlugin.PLUGIN_ID, Messages.errorServerDirIsRoot) }; } // User specified value may not be under the ".metadata" folder // of the workspace else if (workspacePath.isPrefixOf(path) || (!path.isAbsolute() && METADATADIR.equals(path.segment(0)))) { int cnt = path.matchingFirstSegments(workspacePath); if (METADATADIR.equals(path.segment(cnt))) { return new IStatus[] { new Status(IStatus.ERROR, PHPServerUIPlugin.PLUGIN_ID, NLS.bind(Messages.errorServerDirUnderRoot, METADATADIR)) }; } } else if (path.equals(installDirPath)) return new IStatus[] { new Status(IStatus.ERROR, PHPServerUIPlugin.PLUGIN_ID, NLS.bind(Messages.errorServerDirCustomNotInstall, NLS.bind(Messages.serverEditorServerDirInstall, "").trim())) }; //$NON-NLS-1$ } else { IPath path = phpServer.getRuntimeBaseDirectory(); // If non-custom instance dir is not the install and metadata // isn't the selection, return error if (!path.equals(installDirPath) && !serverDirMetadata.getSelection()) { return new IStatus[] { new Status(IStatus.ERROR, PHPServerUIPlugin.PLUGIN_ID, NLS.bind(Messages.errorServerDirCustomNotMetadata, NLS.bind(Messages.serverEditorServerDirMetadata, "").trim())) }; //$NON-NLS-1$ } } } // use default implementation to return success return super.getSaveStatus(); } protected void validate() { if (phpServer != null) { // Validate instance directory String dir = phpServer.getDocumentRootDirectory(); if (dir != null) { IPath path = new Path(dir); // Must not be the same as the workspace location if (dir.length() == 0 || workspacePath.equals(path)) { setErrorMessage(Messages.errorServerDirIsRoot); return; } // User specified value may not be under the ".metadata" folder // of the workspace else if (workspacePath.isPrefixOf(path) || (!path.isAbsolute() && METADATADIR.equals(path.segment(0)))) { int cnt = path.matchingFirstSegments(workspacePath); if (METADATADIR.equals(path.segment(cnt))) { setErrorMessage(NLS.bind(Messages.errorServerDirUnderRoot, METADATADIR)); return; } } else if (path.equals(installDirPath)) { setErrorMessage(NLS.bind(Messages.errorServerDirCustomNotInstall, NLS.bind(Messages.serverEditorServerDirInstall, "").trim())); //$NON-NLS-1$ return; } } else { IPath path = phpServer.getRuntimeBaseDirectory(); // If non-custom instance dir is not the install and metadata // isn't the selection, return error if (path != null && !path.equals(installDirPath) && !serverDirMetadata.getSelection()) { setErrorMessage(NLS.bind(Messages.errorServerDirCustomNotMetadata, NLS.bind(Messages.serverEditorServerDirMetadata, "").trim())); //$NON-NLS-1$ } } } // All is okay, clear any previous error setErrorMessage(null); } }