blob: f99887b90abdf5691f6837b4622d49239389770a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 Rapicorp Corporation 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:
* Rapicorp Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.pde.internal.ui.editor.product;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.osgi.util.TextProcessor;
import org.eclipse.pde.core.IModelChangedEvent;
import org.eclipse.pde.core.build.IBuildEntry;
import org.eclipse.pde.core.plugin.*;
import org.eclipse.pde.internal.core.build.WorkspaceBuildModel;
import org.eclipse.pde.internal.core.iproduct.*;
import org.eclipse.pde.internal.core.project.PDEProject;
import org.eclipse.pde.internal.core.util.PDETextHelper;
import org.eclipse.pde.internal.ui.PDEPlugin;
import org.eclipse.pde.internal.ui.PDEUIMessages;
import org.eclipse.pde.internal.ui.editor.*;
import org.eclipse.pde.internal.ui.wizards.ResizableWizardDialog;
import org.eclipse.pde.internal.ui.wizards.tools.ConvertPreferencesWizard;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.events.IHyperlinkListener;
import org.eclipse.ui.forms.widgets.*;
public class PreferencesSection extends PDESection {
private static final String PREFS_CUSTOMIZATION_FILE = "plugin_customization.ini"; //$NON-NLS-1$
private static final String EXTENSION_PREFS_CUSTOMIZATION = "preferenceCustomization"; //$NON-NLS-1$
public static final String EXTENSION_PRODUCT = "org.eclipse.core.runtime.products"; //$NON-NLS-1$
public static final String ELEMENT_PRODUCT = "product"; //$NON-NLS-1$
FormText configText;
public PreferencesSection(PDEFormPage page, Composite parent) {
super(page, parent, Section.DESCRIPTION);
createClient(getSection(), page.getEditor().getToolkit());
}
/* (non-Javadoc)
* @see org.eclipse.pde.internal.ui.editor.PDESection#createClient(org.eclipse.ui.forms.widgets.Section, org.eclipse.ui.forms.widgets.FormToolkit)
*/
protected void createClient(Section section, FormToolkit toolkit) {
section.setLayout(FormLayoutFactory.createClearTableWrapLayout(false, 1));
TableWrapData data = new TableWrapData(TableWrapData.FILL_GRAB);
section.setLayoutData(data);
section.setText(PDEUIMessages.PreferencesSection_title);
section.setDescription(PDEUIMessages.PreferencesSection_description);
Composite client = toolkit.createComposite(section);
client.setLayout(FormLayoutFactory.createSectionClientTableWrapLayout(false, 1));
client.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB));
configText = toolkit.createFormText(client, true);
String config = getWizardConfigText();
configText.setText(config, true, true);
data = new TableWrapData(TableWrapData.FILL_GRAB);
configText.setLayoutData(data);
configText.addHyperlinkListener(new IHyperlinkListener() {
public void linkEntered(HyperlinkEvent e) {
IStatusLineManager mng = getPage().getEditor().getEditorSite().getActionBars().getStatusLineManager();
mng.setMessage(e.getLabel());
}
public void linkExited(HyperlinkEvent e) {
IStatusLineManager mng = getPage().getEditor().getEditorSite().getActionBars().getStatusLineManager();
mng.setMessage(null);
}
public void linkActivated(HyperlinkEvent e) {
String href = (String) e.getHref();
if (href.equals("command.generate")) { //$NON-NLS-1$
handleGenerate();
} else if (href.equals("navigate.overview")) { //$NON-NLS-1$
getPage().getEditor().setActivePage(OverviewPage.PAGE_ID);
}
}
});
toolkit.paintBordersFor(client);
section.setClient(client);
// Register to be notified when the model changes
getModel().addModelChangedListener(this);
}
private String getWizardConfigText() {
IPreferencesInfo info = getPreferencesInfo();
String[] bindings = new String[3];
bindings[0] = info.getSourceFilePath() == null ? PDEUIMessages.PreferencesSection_epf : "<br></br><b>" + TextProcessor.process(info.getSourceFilePath()) + "</b><br></br><br></br>"; //$NON-NLS-1$ //$NON-NLS-2$
bindings[1] = info.getPreferenceCustomizationPath() == null ? PDEUIMessages.PreferencesSection_customize : "<br></br><b>" + TextProcessor.process(info.getPreferenceCustomizationPath()) + "</b><br></br>"; //$NON-NLS-1$ //$NON-NLS-2$
bindings[2] = getOverwrite() ? PDEUIMessages.PreferencesSection_overwrite : PDEUIMessages.PreferencesSection_merge;
String configText = NLS.bind(PDEUIMessages.PreferencesSection_generate, bindings);
return configText;
}
void handleGenerate() {
String preferenceCustomizationPath = null;
String id = getProduct().getDefiningPluginId();
IPluginModelBase model = PluginRegistry.findModel(id);
if (model == null || model.getUnderlyingResource() == null) {
MessageDialog.openError(getSection().getShell(), NLS.bind(PDEUIMessages.PreferencesSection_errorNoDefiningPluginTitle, id == null ? "" : id), PDEUIMessages.PreferencesSection_errorNoDefiningPlugin); //$NON-NLS-1$
return;
}
// 1 - First look for a plugin_customization.ini defined in the product model.
IProject project = model.getUnderlyingResource().getProject();
IPreferencesInfo info = getPreferencesInfo();
if (info != null) {
preferenceCustomizationPath = info.getPreferenceCustomizationPath();
}
if (preferenceCustomizationPath == null || preferenceCustomizationPath.length() == 0) {
// 2 - None was found in product. See if one has been defined in the plugin extension point
IPluginExtension productExtension = findProductExtension(model);
if (productExtension != null) {
// Find the product element
IPluginElement productElement = findProductElement(productExtension);
if (productElement != null) {
// Find the preference customization property
IPluginElement propertyElement = findPrefCustPropertyElement(productElement);
if (propertyElement != null) {
IPluginAttribute valueAttribute = propertyElement.getAttribute("value"); //$NON-NLS-1$
preferenceCustomizationPath = valueAttribute.getValue();
}
}
}
}
try {
if (preferenceCustomizationPath == null || preferenceCustomizationPath.length() == 0) {
// 3 - If we don't have a file path defined in the extension point, look for one in the defining plugin.
IResource resource = project.findMember(PREFS_CUSTOMIZATION_FILE);
boolean existing = resource != null && resource instanceof IFile;
if (existing) {
preferenceCustomizationPath = ((IFile) resource).getFullPath().toString();
} else {
// Looks like we need to create one. Create plugin_customization.ini as an empty file at project root
IFile customFile = project.getFile(PREFS_CUSTOMIZATION_FILE);
preferenceCustomizationPath = customFile.getFullPath().toString();
byte[] bytes = "".getBytes(); //$NON-NLS-1$
InputStream source = new ByteArrayInputStream(bytes);
customFile.create(source, IResource.NONE, null);
}
}
// Now get a resource from whichever path we found and ensure one last time that it exists. For example, a path might
// have been referenced in the products extension and subsequently deleted.
IFile customizationFile = project.getWorkspace().getRoot().getFile(new Path(preferenceCustomizationPath));
if (!customizationFile.exists()) {
byte[] bytes = "".getBytes(); //$NON-NLS-1$
InputStream source = new ByteArrayInputStream(bytes);
customizationFile.create(source, IResource.NONE, null);
}
// Ensure that any of these paths (existing or not) is in the build.properties
IFile buildProps = PDEProject.getBuildProperties(project);
if (buildProps.exists()) {
WorkspaceBuildModel wkspc = new WorkspaceBuildModel(buildProps);
wkspc.load();
if (wkspc.isLoaded()) {
IBuildEntry entry = wkspc.getBuild().getEntry("bin.includes"); //$NON-NLS-1$
if (entry == null) {
entry = wkspc.getFactory().createEntry("bin.includes"); //$NON-NLS-1$
wkspc.getBuild().add(entry);
}
if (!entry.contains(preferenceCustomizationPath))
entry.addToken(preferenceCustomizationPath);
wkspc.save();
}
}
} catch (CoreException e) {
PDEPlugin.logException(e, null, NLS.bind(PDEUIMessages.PreferencesSection_errorReading, preferenceCustomizationPath));
return;
}
ConvertPreferencesWizard wizard = new ConvertPreferencesWizard(preferenceCustomizationPath, getPreferencesInfo().getSourceFilePath(), getOverwrite());
WizardDialog wd = new ResizableWizardDialog(PDEPlugin.getActiveWorkbenchShell(), wizard);
wd.create();
if (wd.open() == Window.OK) {
info = getPreferencesInfo();
preferenceCustomizationPath = info.getPreferenceCustomizationPath();
info.setPreferenceCustomizationPath(wizard.getPluginCustomizationFilePath());
info.setSourceFilePath(wizard.getPreferencesFilePath());
info.setOverwrite(Boolean.toString(wizard.getOverwrite()));
configText.setText(getWizardConfigText(), true, true);
}
}
private boolean getOverwrite() {
boolean overwrite = false;
if (getPreferencesInfo().getOverwrite() != null) {
overwrite = Boolean.parseBoolean(getPreferencesInfo().getOverwrite());
}
return overwrite;
}
private IPluginElement findPrefCustPropertyElement(IPluginElement productElement) {
// Ensure the produce element has children
if (productElement.getChildCount() == 0) {
return null;
}
// Get the product element children
IPluginObject[] objects = productElement.getChildren();
// Process all children
for (int i = 0; i < objects.length; i++) {
// Ensure we have an element
if ((objects[i] instanceof IPluginElement) == false) {
continue;
}
// Property elements are the only legitimate children of product elements
if (objects[i].getName().equals("property") == false) { //$NON-NLS-1$
continue;
}
IPluginElement element = (IPluginElement) objects[i];
// Get the name
IPluginAttribute nameAttribute = element.getAttribute("name"); //$NON-NLS-1$
// Ensure we have a preference customization property
if (nameAttribute == null) {
continue;
} else if (PDETextHelper.isDefined(nameAttribute.getValue()) == false) {
continue;
} else if (nameAttribute.getValue().equals(EXTENSION_PREFS_CUSTOMIZATION) == false) {
continue;
}
return element;
}
return null;
}
private IPluginElement findProductElement(IPluginExtension extension) {
// The product extension is only allowed one child
if (extension.getChildCount() != 1) {
return null;
}
// Get the one child
IPluginObject pluginObject = extension.getChildren()[0];
// Ensure that the child is an element
if ((pluginObject instanceof IPluginElement) == false) {
return null;
}
// Ensure that the child is a product element
if (pluginObject.getName().equals(ELEMENT_PRODUCT) == false) {
return null;
}
return (IPluginElement) pluginObject;
}
private IPluginExtension findProductExtension(IPluginModelBase model) {
// Get all the extensions
IPluginExtension[] extensions = model.getPluginBase().getExtensions();
// Get the extension matching the product extension point ID
// and product ID
for (int i = 0; i < extensions.length; i++) {
// Get the extension point
String point = extensions[i].getPoint();
// Ensure we have a product extension
if (point.equals(EXTENSION_PRODUCT) == false) {
continue;
}
// Ensure we have the exact product
// Get the fully qualified product ID
String id = model.getPluginBase().getId() + '.' + extensions[i].getId();
if (id.equals(getProduct().getId()) == false) {
continue;
}
return extensions[i];
}
return null;
}
private IPreferencesInfo getPreferencesInfo() {
IPreferencesInfo info = getProduct().getPreferencesInfo();
if (info == null) {
info = getModel().getFactory().createPreferencesInfo();
getProduct().setPreferencesInfo(info);
}
return info;
}
private IProduct getProduct() {
return getModel().getProduct();
}
private IProductModel getModel() {
return (IProductModel) getPage().getPDEEditor().getAggregateModel();
}
public boolean canPaste(Clipboard clipboard) {
Display d = getSection().getDisplay();
Control c = d.getFocusControl();
if (c instanceof Text)
return true;
return false;
}
/* (non-Javadoc)
* @see org.eclipse.pde.internal.ui.editor.PDESection#modelChanged(org.eclipse.pde.core.IModelChangedEvent)
*/
public void modelChanged(IModelChangedEvent e) {
// No need to call super, handling world changed event here
if (e.getChangeType() == IModelChangedEvent.WORLD_CHANGED) {
handleModelEventWorldChanged(e);
}
}
/**
* @param event
*/
private void handleModelEventWorldChanged(IModelChangedEvent event) {
refresh();
}
/* (non-Javadoc)
* @see org.eclipse.ui.forms.AbstractFormPart#dispose()
*/
public void dispose() {
IProductModel model = getModel();
if (model != null) {
model.removeModelChangedListener(this);
}
super.dispose();
}
}