/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Thomas Reinhardt <thomas@reinhardt.com> - [build path] user library dialog should allow to select JAR from workspace - http://bugs.eclipse.org/300542
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.preferences;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.eclipse.equinox.bidi.StructuredTextTypeHandlerFactory;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.StatusDialog;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.resource.StringConverter;
import org.eclipse.jface.util.BidiUtils;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.window.Window;

import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

import org.eclipse.jdt.core.ClasspathContainerInitializer;
import org.eclipse.jdt.core.IAccessRule;
import org.eclipse.jdt.core.IClasspathAttribute;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;

import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.wizards.BuildPathDialogAccess;
import org.eclipse.jdt.ui.wizards.ClasspathAttributeConfiguration;

import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
import org.eclipse.jdt.internal.ui.IUIConstants;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.AccessRulesDialog;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.ArchiveFileFilter;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathSupport;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElement;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElementAttribute;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListElementSorter;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPListLabelProvider;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.CPUserLibraryElement;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.ClasspathAttributeConfigurationDescriptors;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.ModuleEncapsulationDetail;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.SourceAttachmentBlock;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.CheckedListDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IStringButtonAdapter;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.ITreeListAdapter;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.SelectionButtonDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringButtonDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.StringDialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.TreeListDialogField;

public class UserLibraryPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {

	public static final String ID= JavaUI.ID_USER_LIBRARY_PREFERENCE_PAGE;

	public static final String DATA_DO_CREATE= "do_create"; //$NON-NLS-1$
	public static final String DATA_LIBRARY_TO_SELECT= "select_library"; //$NON-NLS-1$

	public static class LibraryNameDialog extends StatusDialog implements IDialogFieldListener {

		private StringDialogField fNameField;
		private SelectionButtonDialogField fIsSystemField;

		private CPUserLibraryElement fElementToEdit;
		private List<CPUserLibraryElement> fExistingLibraries;

		public LibraryNameDialog(Shell parent, CPUserLibraryElement elementToEdit, List<CPUserLibraryElement> existingLibraries) {
			super(parent);
			if (elementToEdit == null) {
				setTitle(PreferencesMessages.UserLibraryPreferencePage_LibraryNameDialog_new_title);
			} else {
				setTitle(PreferencesMessages.UserLibraryPreferencePage_LibraryNameDialog_edit_title);
			}

			fElementToEdit= elementToEdit;
			fExistingLibraries= existingLibraries;

			fNameField= new StringDialogField();
			fNameField.setDialogFieldListener(this);
			fNameField.setLabelText(PreferencesMessages.UserLibraryPreferencePage_LibraryNameDialog_name_label);

			fIsSystemField= new SelectionButtonDialogField(SWT.CHECK);
			fIsSystemField.setLabelText(PreferencesMessages.UserLibraryPreferencePage_LibraryNameDialog_issystem_label);

			if (elementToEdit != null) {
				fNameField.setText(elementToEdit.getName());
				fIsSystemField.setSelection(elementToEdit.isSystemLibrary());
			} else {
				fNameField.setText(""); //$NON-NLS-1$
				fIsSystemField.setSelection(false);
			}
		}

		@Override
		protected Control createDialogArea(Composite parent) {
			Composite composite= (Composite) super.createDialogArea(parent);
			LayoutUtil.doDefaultLayout(composite, new DialogField[] { fNameField, fIsSystemField }, true, SWT.DEFAULT, SWT.DEFAULT);
			fNameField.postSetFocusOnDialogField(parent.getDisplay());

			Dialog.applyDialogFont(composite);

			PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IJavaHelpContextIds.CP_EDIT_USER_LIBRARY);

			return composite;
		}

		@Override
		public void dialogFieldChanged(DialogField field) {
			if (field == fNameField) {
				updateStatus(validateSettings());
			}
		}

		private IStatus validateSettings() {
			String name= fNameField.getText();
			if (name.length() == 0) {
				return new StatusInfo(IStatus.ERROR, PreferencesMessages.UserLibraryPreferencePage_LibraryNameDialog_name_error_entername);
			}
			for (CPUserLibraryElement curr : fExistingLibraries) {
				if (curr != fElementToEdit && name.equals(curr.getName())) {
					return new StatusInfo(IStatus.ERROR, Messages.format(PreferencesMessages.UserLibraryPreferencePage_LibraryNameDialog_name_error_exists, name));
				}
			}
			IStatus status= ResourcesPlugin.getWorkspace().validateName(name, IResource.FILE);
			if (status.matches(IStatus.ERROR)) {
				return new StatusInfo(IStatus.ERROR, "Name contains invalid characters."); //$NON-NLS-1$
			}
			return StatusInfo.OK_STATUS;
		}

		public CPUserLibraryElement getNewLibrary() {
			CPListElement[] entries= null;
			if (fElementToEdit != null) {
				entries= fElementToEdit.getChildren();
			}
			return new CPUserLibraryElement(fNameField.getText(), fIsSystemField.isSelected(), entries);
		}

	}

	public static class LoadSaveDialog extends StatusDialog implements IStringButtonAdapter, IDialogFieldListener, IListAdapter<CPUserLibraryElement> {


		private static final String VERSION1= "1"; //$NON-NLS-1$ // using OS strings for archive path and source attachment
		private static final String CURRENT_VERSION= "2"; //$NON-NLS-1$

		private static final String TAG_ROOT= "eclipse-userlibraries"; //$NON-NLS-1$
		private static final String TAG_VERSION= "version"; //$NON-NLS-1$
		private static final String TAG_LIBRARY= "library"; //$NON-NLS-1$
		private static final String TAG_SOURCEATTACHMENT= "source"; //$NON-NLS-1$
		private static final String TAG_SOURCE_ATTACHMENT_ENCODING= "source_encoding"; //$NON-NLS-1$
		private static final String TAG_ARCHIVE_PATH= "path"; //$NON-NLS-1$
		private static final String TAG_ARCHIVE= "archive"; //$NON-NLS-1$
		private static final String TAG_SYSTEMLIBRARY= "systemlibrary"; //$NON-NLS-1$
		private static final String TAG_NAME= "name"; //$NON-NLS-1$
		private static final String TAG_JAVADOC= "javadoc"; //$NON-NLS-1$
		private static final String TAG_NATIVELIB_PATHS= "nativelibpaths"; //$NON-NLS-1$
		private static final String TAG_ACCESSRULES= "accessrules"; //$NON-NLS-1$
		private static final String TAG_ACCESSRULE= "accessrule"; //$NON-NLS-1$
		private static final String TAG_RULE_KIND= "kind"; //$NON-NLS-1$
		private static final String TAG_RULE_PATTERN= "pattern"; //$NON-NLS-1$

		private static final String PREF_LASTPATH= JavaUI.ID_PLUGIN + ".lastuserlibrary"; //$NON-NLS-1$
		private static final String PREF_USER_LIBRARY_LOADSAVE_SIZE= "UserLibraryLoadSaveDialog.size"; //$NON-NLS-1$

		private List<CPUserLibraryElement> fExistingLibraries;
		private IDialogSettings fSettings;

		private File fLastFile;

		private StringButtonDialogField fLocationField;
		private CheckedListDialogField<CPUserLibraryElement> fExportImportList;
		private Point fInitialSize;
		private final boolean fIsSave;

		public LoadSaveDialog(Shell shell, boolean isSave, List<CPUserLibraryElement> existingLibraries, IDialogSettings dialogSettings) {
			super(shell);
			initializeDialogUnits(shell);

			fExistingLibraries= existingLibraries;
			fSettings= dialogSettings;
			fLastFile= null;
			fIsSave= isSave;

			int defaultWidth= convertWidthInCharsToPixels(80);
			int defaultHeigth= convertHeightInCharsToPixels(34);
			String lastSize= fSettings.get(PREF_USER_LIBRARY_LOADSAVE_SIZE);
			if (lastSize != null) {
				fInitialSize= StringConverter.asPoint(lastSize, new Point(defaultWidth, defaultHeigth));
			} else {
				fInitialSize= new Point(defaultWidth, defaultHeigth);
			}

			if (isSave()) {
				setTitle(PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_save_title);
			} else {
				setTitle(PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_load_title);
			}

			fLocationField= new StringButtonDialogField(this);
			fLocationField.setLabelText(PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_location_label);
			fLocationField.setButtonLabel(PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_location_button);
			fLocationField.setDialogFieldListener(this);

			String[] buttonNames= new String[] {
					PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_list_selectall_button,
					PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_list_deselectall_button
			};
			fExportImportList= new CheckedListDialogField<>(this, buttonNames, new CPListLabelProvider());
			fExportImportList.setCheckAllButtonIndex(0);
			fExportImportList.setUncheckAllButtonIndex(1);
			fExportImportList.setViewerComparator(new CPListElementSorter());
			fExportImportList.setDialogFieldListener(this);
			if (isSave()) {
				fExportImportList.setLabelText(PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_list_save_label);
				fExportImportList.setElements(fExistingLibraries);
				fExportImportList.checkAll(true);
			} else {
				fExportImportList.setLabelText(PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_list_load_label);
			}
			String lastPath= fSettings.get(PREF_LASTPATH);
			if (lastPath != null) {
				fLocationField.setText(lastPath);
			} else {
				fLocationField.setText(""); //$NON-NLS-1$
			}
		}

		/*
		 * @see org.eclipse.jface.dialogs.Dialog#isResizable()
		 * @since 3.4
		 */
		@Override
		protected boolean isResizable() {
			return true;
		}

		@Override
		protected Point getInitialSize() {
			return fInitialSize;
		}

		private boolean isSave() {
			return fIsSave;
		}

		@Override
		protected Control createDialogArea(Composite parent) {
			Composite composite= (Composite) super.createDialogArea(parent);
			DialogField[] fields;
			if (isSave()) {
				fields= new DialogField[] { fExportImportList, fLocationField };
			} else {
				fields= new DialogField[] { fLocationField, fExportImportList };
			}
			LayoutUtil.doDefaultLayout(composite, fields, true, SWT.DEFAULT, SWT.DEFAULT);
			fExportImportList.getListControl(null).setLayoutData(new GridData(GridData.FILL_BOTH));

			fLocationField.postSetFocusOnDialogField(parent.getDisplay());
			BidiUtils.applyBidiProcessing(fLocationField.getTextControl(parent), StructuredTextTypeHandlerFactory.FILE);

			Dialog.applyDialogFont(composite);

			if (isSave()) {
				PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IJavaHelpContextIds.CP_EXPORT_USER_LIBRARY);
			} else {
				PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, IJavaHelpContextIds.CP_IMPORT_USER_LIBRARY);
			}

			return composite;
		}


		@Override
		public void changeControlPressed(DialogField field) {
			String label= isSave() ? PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_filedialog_save_title : PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_filedialog_load_title;
			FileDialog dialog= new FileDialog(getShell(), SWT.SHEET | (isSave() ? SWT.SAVE : SWT.OPEN));
			dialog.setText(label);
			dialog.setFilterExtensions(new String[] {"*.userlibraries", "*.*"}); //$NON-NLS-1$ //$NON-NLS-2$
			String lastPath= fLocationField.getText();
			if (lastPath.length() == 0 || !new File(lastPath).exists()) {
				lastPath= fSettings.get(PREF_LASTPATH);
			}
			if (lastPath != null) {
				dialog.setFileName(lastPath);
			}
			String fileName= dialog.open();
			if (fileName != null) {
				fSettings.put(PREF_LASTPATH, fileName);
				fLocationField.setText(fileName);
			}
		}

		private IStatus updateShownLibraries(IStatus status) {
			if (!status.isOK()) {
				fExportImportList.removeAllElements();
				fExportImportList.setEnabled(false);
				fLastFile= null;
			} else {
				File file= new File(fLocationField.getText());
				if (!file.equals(fLastFile)) {
					fLastFile= file;
					try {
						List<CPUserLibraryElement> elements= loadLibraries(file);
						fExportImportList.setElements(elements);
						fExportImportList.checkAll(true);
						fExportImportList.setEnabled(true);
						if (elements.isEmpty()) {
							return new StatusInfo(IStatus.ERROR, PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_error_empty);
						}
					} catch (IOException e) {
						fExportImportList.removeAllElements();
						fExportImportList.setEnabled(false);
						return new StatusInfo(IStatus.ERROR, PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_error_invalidfile);
					}
				}
			}
			return status;
		}

		@Override
		public void dialogFieldChanged(DialogField field) {
			if (field == fLocationField) {
				IStatus status= validateSettings();
				if (!isSave()) {
					status= updateShownLibraries(status);
				}
				updateStatus(status);
			} else if (field == fExportImportList) {
				updateStatus(validateSettings());
			}
		}

		@Override
		public void customButtonPressed(ListDialogField<CPUserLibraryElement> field, int index) {
		}

		@Override
		public void selectionChanged(ListDialogField<CPUserLibraryElement> field) {
		}

		@Override
		public void doubleClicked(ListDialogField<CPUserLibraryElement> field) {
			List<CPUserLibraryElement> selectedElements= fExportImportList.getSelectedElements();
			if (selectedElements.size() == 1) {
				CPUserLibraryElement elem= selectedElements.get(0);
				fExportImportList.setChecked(elem, !fExportImportList.isChecked(elem));
			}
		}

		@Override
		protected void okPressed() {
			if (isSave()) {
				final File file= new File(fLocationField.getText());
				if (file.exists()) {
					String title= PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_overwrite_title;
					String message= PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_overwrite_message;
					if (!MessageDialog.openQuestion(getShell(), title, message)) {
						return;
					}
				}
				try {
					String encoding= "UTF-8"; //$NON-NLS-1$
					IPath filePath= Path.fromOSString(file.getCanonicalPath());
					final IPath workspacePath= ResourcesPlugin.getWorkspace().getRoot().getLocation();
					if (filePath.matchingFirstSegments(workspacePath) == workspacePath.segmentCount()) {
						IPath path= filePath.removeFirstSegments(workspacePath.segmentCount());
						if (path.segmentCount() > 1) {
							IFile result= ResourcesPlugin.getWorkspace().getRoot().getFile(path);
							try {
								encoding= result.getCharset(true);
							} catch (CoreException exception) {
								JavaPlugin.log(exception);
							}
						}
					}
					final List<CPUserLibraryElement> elements= fExportImportList.getCheckedElements();
					final String charset= encoding;
					IRunnableContext context= PlatformUI.getWorkbench().getProgressService();
					try {
						context.run(true, true, new IRunnableWithProgress() {
							@Override
							public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
								try {
									saveLibraries(elements, file, charset, monitor);
								} catch (IOException e) {
									throw new InvocationTargetException(e);
								}
							}
						});
						fSettings.put(PREF_LASTPATH, file.getPath());
					} catch (InvocationTargetException e) {
						String errorTitle= PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_save_errordialog_title;
						String errorMessage= Messages.format(PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_save_errordialog_message, e.getMessage());
						ExceptionHandler.handle(e, getShell(), errorTitle, errorMessage);
						return;
					} catch (InterruptedException e) {
						// cancelled
						return;
					}
					String savedTitle= PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_save_ok_title;
					String savedMessage= PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_save_ok_message;
					MessageDialog.openInformation(getShell(), savedTitle, savedMessage);
				} catch (IOException exception) {
					JavaPlugin.log(exception);
				}
			} else {
				HashSet<String> map= new HashSet<>(fExistingLibraries.size());
				for (CPUserLibraryElement elem : fExistingLibraries) {
					map.add(elem.getName());
				}
				int nReplaced= 0;
				List<CPUserLibraryElement> elements= getLoadedLibraries();
				for (CPUserLibraryElement curr : elements) {
					if (map.contains(curr.getName())) {
						nReplaced++;
					}
				}
				if (nReplaced > 0) {
					String replaceTitle= PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_load_replace_title;
					String replaceMessage;
					if (nReplaced == 1) {
						replaceMessage= PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_load_replace_message;
					} else {
						replaceMessage= Messages.format(PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_load_replace_multiple_message, String.valueOf(nReplaced));
					}
					if (!MessageDialog.openConfirm(getShell(), replaceTitle, replaceMessage)) {
						return;
					}
				}
			}
			super.okPressed();
		}

		@Override
		public boolean close() {
			Point point= getShell().getSize();
			fSettings.put(PREF_USER_LIBRARY_LOADSAVE_SIZE, StringConverter.asString(point));
			return super.close();
		}

		private IStatus validateSettings() {
			String name= fLocationField.getText();
			fLastFile= null;
			if (isSave()) {
				if (name.length() == 0) {
					return new StatusInfo(IStatus.ERROR, PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_location_error_save_enterlocation);
				}
				File file= new File(name);
				if (file.isDirectory()) {
					return new StatusInfo(IStatus.ERROR, PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_location_error_save_invalid);
				}
				if (fExportImportList.getCheckedSize() == 0) {
					return new StatusInfo(IStatus.ERROR, PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_list_error_save_nothingselected);
				}
				fLastFile= file;
			} else {
				if (name.length() == 0) {
					return new StatusInfo(IStatus.ERROR, PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_location_error_load_enterlocation);
				}
				if (!new File(name).isFile()) {
					return new StatusInfo(IStatus.ERROR, PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_location_error_load_invalid);
				}
				if (fExportImportList.getSize() > 0 && fExportImportList.getCheckedSize() == 0) {
					return new StatusInfo(IStatus.ERROR, PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_list_error_load_nothingselected);
				}
			}
			return new StatusInfo();
		}

		protected static void saveLibraries(List<CPUserLibraryElement> libraries, File file, String encoding, IProgressMonitor monitor) throws IOException {
			OutputStream stream= new FileOutputStream(file);
			try {
				DocumentBuilder docBuilder= null;
				DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
				factory.setValidating(false);
				docBuilder= factory.newDocumentBuilder();
				Document document= docBuilder.newDocument();

				// Create the document
				Element rootElement= document.createElement(TAG_ROOT);
				document.appendChild(rootElement);

				rootElement.setAttribute(TAG_VERSION, CURRENT_VERSION);

				for (CPUserLibraryElement curr : libraries) {
					Element libraryElement= document.createElement(TAG_LIBRARY);
					rootElement.appendChild(libraryElement);

					libraryElement.setAttribute(TAG_NAME, curr.getName());
					libraryElement.setAttribute(TAG_SYSTEMLIBRARY, String.valueOf(curr.isSystemLibrary()));

					for (CPListElement child : curr.getChildren()) {
						Element childElement= document.createElement(TAG_ARCHIVE);
						libraryElement.appendChild(childElement);

						childElement.setAttribute(TAG_ARCHIVE_PATH, child.getPath().toPortableString());
						IPath sourceAttachment= (IPath) child.getAttribute(CPListElement.SOURCEATTACHMENT);
						if (sourceAttachment != null) {
							childElement.setAttribute(TAG_SOURCEATTACHMENT, sourceAttachment.toPortableString());
						}
						String sourceEncoding= (String) child.getAttribute(CPListElement.SOURCE_ATTACHMENT_ENCODING);
						if (sourceEncoding != null) {
							childElement.setAttribute(TAG_SOURCE_ATTACHMENT_ENCODING, sourceEncoding);
						}
						String javadocLocation= (String) child.getAttribute(CPListElement.JAVADOC);
						if (javadocLocation != null) {
							childElement.setAttribute(TAG_JAVADOC, javadocLocation);
						}
						String nativeLibPath= (String) child.getAttribute(CPListElement.NATIVE_LIB_PATH);
						if (nativeLibPath != null) {
							childElement.setAttribute(TAG_NATIVELIB_PATHS, nativeLibPath);
						}
						IAccessRule[] accessRules= (IAccessRule[]) child.getAttribute(CPListElement.ACCESSRULES);
						if (accessRules != null && accessRules.length > 0) {
							Element rulesElement= document.createElement(TAG_ACCESSRULES);
							childElement.appendChild(rulesElement);
							for (IAccessRule rule : accessRules) {
								Element ruleElement= document.createElement(TAG_ACCESSRULE);
								rulesElement.appendChild(ruleElement);
								ruleElement.setAttribute(TAG_RULE_KIND, String.valueOf(rule.getKind()));
								ruleElement.setAttribute(TAG_RULE_PATTERN, rule.getPattern().toPortableString());
							}
						}
					}
				}

				// Write the document to the stream
				Transformer transformer=TransformerFactory.newInstance().newTransformer();
				transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
				transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
				transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
				transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount","4"); //$NON-NLS-1$ //$NON-NLS-2$

				DOMSource source = new DOMSource(document);
				StreamResult result = new StreamResult(stream);
				transformer.transform(source, result);
			} catch (ParserConfigurationException | TransformerException e) {
				throw new IOException(e.getMessage());
			} finally {
				try {
					stream.close();
				} catch (IOException e) {
					// ignore
				}
				if (monitor != null) {
					monitor.done();
				}
			}
		}

		private static List<CPUserLibraryElement> loadLibraries(File file) throws IOException {
			InputStream stream= new FileInputStream(file);
			Element cpElement;
			try {
				DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
				parser.setErrorHandler(new DefaultHandler());
				cpElement = parser.parse(new InputSource(stream)).getDocumentElement();
			} catch (SAXException | ParserConfigurationException e) {
				throw new IOException(PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_load_badformat);
			} finally {
				stream.close();
			}

			if (!cpElement.getNodeName().equalsIgnoreCase(TAG_ROOT)) {
				throw new IOException(PreferencesMessages.UserLibraryPreferencePage_LoadSaveDialog_load_badformat);
			}

			String version= cpElement.getAttribute(TAG_VERSION);

			NodeList libList= cpElement.getElementsByTagName(TAG_LIBRARY);
			int length = libList.getLength();

			IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();

			ArrayList<CPUserLibraryElement> result= new ArrayList<>(length);
			for (int i= 0; i < length; i++) {
				Node lib= libList.item(i);
				if (!(lib instanceof Element)) {
					continue;
				}
				Element libElement= (Element) lib;
				String name= libElement.getAttribute(TAG_NAME);
				boolean isSystem= Boolean.parseBoolean(libElement.getAttribute(TAG_SYSTEMLIBRARY));

				CPUserLibraryElement newLibrary= new CPUserLibraryElement(name, isSystem, null);
				result.add(newLibrary);

				NodeList archiveList= libElement.getElementsByTagName(TAG_ARCHIVE);
				for (int k= 0; k < archiveList.getLength(); k++) {
					Node archiveNode= archiveList.item(k);
					if (!(archiveNode instanceof Element)) {
						continue;
					}
					Element archiveElement= (Element) archiveNode;

					String pathString= archiveElement.getAttribute(TAG_ARCHIVE_PATH);
					IPath path= version.equals(VERSION1) ? Path.fromOSString(pathString) : Path.fromPortableString(pathString);
					path= path.makeAbsolute(); // only necessary for manually edited files: bug 202373

					IResource resource= root.findMember(path); // support internal JARs: bug 133191
					if (!(resource instanceof IFile)) {
						resource= null;
					}

					CPListElement newArchive= new CPListElement(newLibrary, null, IClasspathEntry.CPE_LIBRARY, path, resource);
					newLibrary.add(newArchive);

					if (archiveElement.hasAttribute(TAG_SOURCEATTACHMENT)) {
						String sourceAttachString= archiveElement.getAttribute(TAG_SOURCEATTACHMENT);
						IPath sourceAttach= version.equals(VERSION1) ? Path.fromOSString(sourceAttachString) : Path.fromPortableString(sourceAttachString);
						newArchive.setAttribute(CPListElement.SOURCEATTACHMENT, sourceAttach);
					}
					if (archiveElement.hasAttribute(TAG_SOURCE_ATTACHMENT_ENCODING)) {
						String javadoc= archiveElement.getAttribute(TAG_SOURCE_ATTACHMENT_ENCODING);
						newArchive.setAttribute(CPListElement.SOURCE_ATTACHMENT_ENCODING, javadoc);
					}
					if (archiveElement.hasAttribute(TAG_JAVADOC)) {
						String javadoc= archiveElement.getAttribute(TAG_JAVADOC);
						newArchive.setAttribute(CPListElement.JAVADOC, javadoc);
					}
					if (archiveElement.hasAttribute(TAG_NATIVELIB_PATHS)) {
						String nativeLibPath= archiveElement.getAttribute(TAG_NATIVELIB_PATHS);
						newArchive.setAttribute(CPListElement.NATIVE_LIB_PATH, nativeLibPath);
					}
					NodeList rulesParentNodes= archiveElement.getElementsByTagName(TAG_ACCESSRULES);
					if (rulesParentNodes.getLength() > 0 && rulesParentNodes.item(0) instanceof Element) {
						Element ruleParentElement= (Element) rulesParentNodes.item(0); // take first, ignore others
						NodeList ruleElements= ruleParentElement.getElementsByTagName(TAG_ACCESSRULE);
						int nRuleElements= ruleElements.getLength();
						if (nRuleElements > 0) {
							ArrayList<IAccessRule> resultingRules= new ArrayList<>(nRuleElements);
							for (int n= 0; n < nRuleElements; n++) {
								Node node= ruleElements.item(n);
								if (node instanceof Element) {
									Element ruleElement= (Element) node;
									try {
										int kind= Integer.parseInt(ruleElement.getAttribute(TAG_RULE_KIND));
										IPath pattern= Path.fromPortableString(ruleElement.getAttribute(TAG_RULE_PATTERN));
										resultingRules.add(JavaCore.newAccessRule(pattern, kind));
									} catch (NumberFormatException e) {
										// ignore
									}
								}
							}
							newArchive.setAttribute(CPListElement.ACCESSRULES, resultingRules.toArray(new IAccessRule[resultingRules.size()]));
						}
					}
				}
			}
			return result;
		}

		public List<CPUserLibraryElement> getLoadedLibraries() {
			return fExportImportList.getCheckedElements();
		}
	}

	private IWorkbench fWorkbench;
	private IDialogSettings fDialogSettings;
	private TreeListDialogField<CPUserLibraryElement> fLibraryList;
	private IJavaProject fDummyProject;
	private ClasspathAttributeConfigurationDescriptors fAttributeDescriptors;

	private static final int IDX_NEW= 0;
	private static final int IDX_EDIT= 1;
	private static final int IDX_ADD= 2;
	private static final int IDX_ADD_EXTERNAL= 3;
	private static final int IDX_REMOVE= 4;
	private static final int IDX_UP= 6;
	private static final int IDX_DOWN= 7;
	private static final int IDX_LOAD= 9;
	private static final int IDX_SAVE= 10;

	/**
	 * Constructor for ClasspathVariablesPreferencePage
	 */
	public UserLibraryPreferencePage() {
		setPreferenceStore(JavaPlugin.getDefault().getPreferenceStore());
		fDummyProject= createPlaceholderProject();

		fAttributeDescriptors= JavaPlugin.getDefault().getClasspathAttributeConfigurationDescriptors();

		// title only used when page is shown programatically
		setTitle(PreferencesMessages.UserLibraryPreferencePage_title);
		setDescription(PreferencesMessages.UserLibraryPreferencePage_description);
		noDefaultAndApplyButton();

		fDialogSettings= JavaPlugin.getDefault().getDialogSettings();

		UserLibraryAdapter adapter= new UserLibraryAdapter();
		String[] buttonLabels= new String[] {
				PreferencesMessages.UserLibraryPreferencePage_libraries_new_button,
				PreferencesMessages.UserLibraryPreferencePage_libraries_edit_button,
				PreferencesMessages.UserLibraryPreferencePage_libraries_addjar_button,
				PreferencesMessages.UserLibraryPreferencePage_libraries_addexternaljar_button,
				PreferencesMessages.UserLibraryPreferencePage_libraries_remove_button,
				null,
				PreferencesMessages.UserLibraryPreferencePage_UserLibraryPreferencePage_libraries_up_button,
				PreferencesMessages.UserLibraryPreferencePage_UserLibraryPreferencePage_libraries_down_button,
				null,

				PreferencesMessages.UserLibraryPreferencePage_libraries_load_button,
				PreferencesMessages.UserLibraryPreferencePage_libraries_save_button
		};

		fLibraryList= new TreeListDialogField<>(adapter, buttonLabels, new CPListLabelProvider());
		fLibraryList.setLabelText(PreferencesMessages.UserLibraryPreferencePage_libraries_label);

		ArrayList<CPUserLibraryElement> elements= new ArrayList<>();

		for (String name : JavaCore.getUserLibraryNames()) {
			IPath path= new Path(JavaCore.USER_LIBRARY_CONTAINER_ID).append(name);
			try {
				IClasspathContainer container= JavaCore.getClasspathContainer(path, fDummyProject);
				elements.add(new CPUserLibraryElement(name, container, fDummyProject));
			} catch (JavaModelException e) {
				JavaPlugin.log(e);
				// ignore
			}
		}
		fLibraryList.setElements(elements);
		fLibraryList.setViewerComparator(new CPListElementSorter());

		doSelectionChanged(fLibraryList); //update button enable state
	}

	private static IJavaProject createPlaceholderProject() {
		String name= "####internal"; //$NON-NLS-1$
		IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
		while (true) {
			IProject project= root.getProject(name);
			if (!project.exists()) {
				return JavaCore.create(project);
			}
			name += '1';
		}
	}


	@Override
	public void applyData(Object data) {
		if (data instanceof Map) {
			@SuppressWarnings("unchecked")
			Map<String, Object> map= (Map<String, Object>) data;
			Object selectedLibrary= map.get(DATA_LIBRARY_TO_SELECT);
			boolean createIfNotExists= Boolean.TRUE.equals(map.get(DATA_DO_CREATE));
			if (selectedLibrary instanceof String) {
				for (CPUserLibraryElement curr : fLibraryList.getElements()) {
					if (curr.getName().equals(selectedLibrary)) {
						fLibraryList.selectElements(new StructuredSelection(curr));
						fLibraryList.expandElement(curr, 1);
						break;
					}
				}
				if (createIfNotExists) {
					CPUserLibraryElement elem= new CPUserLibraryElement((String) selectedLibrary, null, createPlaceholderProject());
					fLibraryList.addElement(elem);
					fLibraryList.selectElements(new StructuredSelection(elem));
				}
			}
		}
	}


	@Override
	public void createControl(Composite parent) {
		super.createControl(parent);
		PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IJavaHelpContextIds.CP_USERLIBRARIES_PREFERENCE_PAGE);
	}

	/*
	 * @see PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
	 */
	@Override
	protected Control createContents(Composite parent) {
		Composite composite= new Composite(parent, SWT.NONE);
		composite.setFont(parent.getFont());
		LayoutUtil.doDefaultLayout(composite, new DialogField[] { fLibraryList }, true);
		LayoutUtil.setHorizontalGrabbing(fLibraryList.getTreeControl(null));
		Dialog.applyDialogFont(composite);
		return composite;
	}

	/*
	 * @see IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
	 */
	@Override
	public void init(IWorkbench workbench) {
		fWorkbench= workbench;
	}

	/*
	 * @see PreferencePage#performDefaults()
	 */
	@Override
	protected void performDefaults() {
		super.performDefaults();
	}

	/*
	 * @see PreferencePage#performOk()
	 */
	@Override
	public boolean performOk() {
		try {
			PlatformUI.getWorkbench().getProgressService().run(true, true, new IRunnableWithProgress() {
				@Override
				public void run(IProgressMonitor monitor) throws InvocationTargetException {
					try {
						if (monitor != null) {
							monitor= new NullProgressMonitor();
						}

						updateUserLibararies(monitor);
					} catch (CoreException e) {
						throw new InvocationTargetException(e);
					} finally {
						monitor.done();
					}
				}
			});
		} catch (InterruptedException e) {
			// cancelled by user
		} catch (InvocationTargetException e) {
			String title= PreferencesMessages.UserLibraryPreferencePage_config_error_title;
			String message= PreferencesMessages.UserLibraryPreferencePage_config_error_message;
			ExceptionHandler.handle(e, getShell(), title, message);
		}
		return true;
	}


	private void updateUserLibararies(IProgressMonitor monitor) throws CoreException {
		List<CPUserLibraryElement> list= fLibraryList.getElements();
		HashSet<String> oldNames= new HashSet<>(Arrays.asList(JavaCore.getUserLibraryNames()));
		int nExisting= list.size();

		HashSet<CPUserLibraryElement> newEntries= new HashSet<>(list.size());
		for (CPUserLibraryElement element : list) {
			boolean contained= oldNames.remove(element.getName());
			if (!contained) {
				newEntries.add(element);
			}
		}

		int len= nExisting + oldNames.size();
		monitor.beginTask(PreferencesMessages.UserLibraryPreferencePage_operation, len);
		MultiStatus multiStatus= new MultiStatus(JavaUI.ID_PLUGIN, IStatus.OK, PreferencesMessages.UserLibraryPreferencePage_operation_error, null);

		ClasspathContainerInitializer initializer= JavaCore.getClasspathContainerInitializer(JavaCore.USER_LIBRARY_CONTAINER_ID);
		IJavaProject jproject= fDummyProject;

		for (int i= 0; i < nExisting; i++) {
			CPUserLibraryElement element= list.get(i);
			IPath path= element.getPath();
			if (newEntries.contains(element) || element.hasChanges(JavaCore.getClasspathContainer(path, jproject))) {
				IClasspathContainer updatedContainer= element.getUpdatedContainer();
				try {
					initializer.requestClasspathContainerUpdate(path, jproject, updatedContainer);
				} catch (CoreException e) {
					multiStatus.add(e.getStatus());
				}
			}
			monitor.worked(1);
		}

		Iterator<String> iter= oldNames.iterator();
		while (iter.hasNext()) {
			String name= iter.next();

			IPath path= new Path(JavaCore.USER_LIBRARY_CONTAINER_ID).append(name);
			try {
				initializer.requestClasspathContainerUpdate(path, jproject, null);
			} catch (CoreException e) {
				multiStatus.add(e.getStatus());
			}
			monitor.worked(1);
		}

		if (!multiStatus.isOK()) {
			throw new CoreException(multiStatus);
		}
	}

	private CPUserLibraryElement getSingleSelectedLibrary(List<Object> selected) {
		if (selected.size() == 1 && selected.get(0) instanceof CPUserLibraryElement) {
			return (CPUserLibraryElement) selected.get(0);
		}
		return null;
	}

	private void editAttributeEntry(CPListElementAttribute elem) {
		String key= elem.getKey();
		CPListElement selElement= elem.getParent();
		Object parentContainer= selElement.getParentContainer();

		boolean canEditEncoding= false;
		for (CPListElementAttribute allAttribute : selElement.getAllAttributes()) {
			if (CPListElement.SOURCE_ATTACHMENT_ENCODING.equals(allAttribute.getKey())) {
				canEditEncoding= !allAttribute.isNonModifiable() && !allAttribute.isNotSupported();
			}
		}
		if (key.equals(CPListElement.SOURCEATTACHMENT)) {
			IClasspathEntry result= BuildPathDialogAccess.configureSourceAttachment(getShell(), selElement.getClasspathEntry(), canEditEncoding);
			if (result != null) {
				selElement.setAttribute(CPListElement.SOURCEATTACHMENT, result.getSourceAttachmentPath());
				selElement.setAttribute(CPListElement.SOURCE_ATTACHMENT_ENCODING, SourceAttachmentBlock.getSourceAttachmentEncoding(result));
				fLibraryList.refresh(parentContainer);
				fLibraryList.update(selElement);
			}
		} else if (key.equals(CPListElement.ACCESSRULES)) {
			AccessRulesDialog dialog= new AccessRulesDialog(getShell(), selElement, null, false);
			if (dialog.open() == Window.OK) {
				selElement.setAttribute(CPListElement.ACCESSRULES, dialog.getAccessRules());
				fLibraryList.refresh(parentContainer);
				fLibraryList.expandElement(elem, 2);
			}
		} else if (!elem.isBuiltIn()) {
			ClasspathAttributeConfiguration config= fAttributeDescriptors.get(key);
			if (config != null) {
				IClasspathAttribute result= config.performEdit(getShell(), elem.getClasspathAttributeAccess());
				if (result != null) {
					elem.setValue(result.getValue());
					if(key.equals(CPListElement.TEST) || key.equals(CPListElement.WITHOUT_TEST_CODE)) {
						fLibraryList.refresh(elem.getParent());
					} else {
						fLibraryList.refresh(elem);
					}
					fLibraryList.refresh(parentContainer);
				}
			}
		}
	}

	protected void doSelectionChanged(TreeListDialogField<CPUserLibraryElement> field) {
		List<Object> list= field.getSelectedElements();
		String text;
		if (list.size() == 1
				&& list.get(0) instanceof CPListElementAttribute) {
			String key= ((CPListElementAttribute) list.get(0)).getKey();
			if (CPListElement.TEST.equals(key) || CPListElement.WITHOUT_TEST_CODE.equals(key)) {
				text= PreferencesMessages.UserLibraryPreferencePage_libraries_toggle_button;
			} else {
				text= PreferencesMessages.UserLibraryPreferencePage_libraries_edit_button;
			}
		} else {
			text= PreferencesMessages.UserLibraryPreferencePage_libraries_edit_button;
		}
		Button editButton= field.getButton(IDX_EDIT);
		if (editButton != null)
			editButton.setText(text);
		field.enableButton(IDX_REMOVE, canRemove(list));
		field.enableButton(IDX_EDIT, canEdit(list));
		field.enableButton(IDX_ADD, canAdd(list));
		field.enableButton(IDX_ADD_EXTERNAL, canAdd(list));
		field.enableButton(IDX_UP, canMoveUp(list));
		field.enableButton(IDX_DOWN, canMoveDown(list));
		field.enableButton(IDX_SAVE, field.getSize() > 0);
	}

	protected void doCustomButtonPressed(TreeListDialogField<CPUserLibraryElement> field, int index) {
		switch (index) {
		case IDX_NEW:
			editUserLibraryElement(null);
			break;
		case IDX_ADD:
			doAdd(field.getSelectedElements());
			break;
		case IDX_ADD_EXTERNAL:
			doAddExternal(field.getSelectedElements());
			break;
		case IDX_REMOVE:
			doRemove(field.getSelectedElements());
			break;
		case IDX_EDIT:
			doEdit(field.getSelectedElements());
			break;
		case IDX_SAVE:
			doSave();
			break;
		case IDX_LOAD:
			doLoad();
			break;
		case IDX_UP:
			doMoveUp(field.getSelectedElements());
			break;
		case IDX_DOWN:
			doMoveDown(field.getSelectedElements());
			break;
		default:
			break;
		}
	}

	protected void doDoubleClicked(TreeListDialogField<CPUserLibraryElement> field) {
		List<Object> selected= field.getSelectedElements();
		if (canEdit(selected)) {
			doEdit(field.getSelectedElements());
		}
	}

	protected void doKeyPressed(TreeListDialogField<CPUserLibraryElement> field, KeyEvent event) {
		if (event.character == SWT.DEL && event.stateMask == 0) {
			List<Object> selection= field.getSelectedElements();
			if (canRemove(selection)) {
				doRemove(selection);
			}
		}
	}

	private void doEdit(List<Object> selected) {
		if (selected.size() == 1) {
			Object curr= selected.get(0);
			if (curr instanceof CPListElementAttribute) {
				editAttributeEntry((CPListElementAttribute) curr);
			} else if (curr instanceof CPUserLibraryElement) {
				editUserLibraryElement((CPUserLibraryElement) curr);
			} else if (curr instanceof CPListElement) {
				CPListElement elem= (CPListElement) curr;
				editArchiveElement(elem, (CPUserLibraryElement) elem.getParentContainer());
			}
			doSelectionChanged(fLibraryList);
		}
	}

	private void editUserLibraryElement(CPUserLibraryElement element) {
		LibraryNameDialog dialog= new LibraryNameDialog(getShell(), element, fLibraryList.getElements());
		if (dialog.open() == Window.OK) {
			CPUserLibraryElement newLibrary= dialog.getNewLibrary();
			if (element != null) {
				fLibraryList.replaceElement(element, newLibrary);
			} else {
				fLibraryList.addElement(newLibrary);
			}
			fLibraryList.expandElement(newLibrary, AbstractTreeViewer.ALL_LEVELS);
			fLibraryList.selectElements(new StructuredSelection(newLibrary));
		}
	}

	private void editArchiveElement(CPListElement existingElement, CPUserLibraryElement parent) {
		CPListElement[] elements= openJarFileDialog(existingElement, parent);
		if (elements != null) {
			for (CPListElement element : elements) {
				if (existingElement != null) {
					parent.replace(existingElement, element);
				} else {
					parent.add(element);
				}
			}
			fLibraryList.refresh(parent);
			fLibraryList.selectElements(new StructuredSelection(Arrays.asList(elements)));
			fLibraryList.expandElement(parent, 2);
		}
	}


	private void doRemove(List<Object> selected) {
		Object selectionAfter= null;
		for (Object curr : selected) {
			if (curr instanceof CPUserLibraryElement) {
				fLibraryList.removeElement((CPUserLibraryElement) curr);
			} else if (curr instanceof CPListElement) {
				Object parent= ((CPListElement) curr).getParentContainer();
				if (parent instanceof CPUserLibraryElement) {
					CPUserLibraryElement elem= (CPUserLibraryElement) parent;
					elem.remove((CPListElement) curr);
					fLibraryList.refresh(elem);
					selectionAfter= parent;
				}
			} else if (curr instanceof CPListElementAttribute) {
				CPListElementAttribute attrib= (CPListElementAttribute) curr;
				Object parentContainer= attrib.getParent().getParentContainer();
				if (attrib.isBuiltIn()) {
					Object value= null;
					String key= attrib.getKey();
					if (key.equals(CPListElement.ACCESSRULES)) {
						value= new IAccessRule[0];
					}
					attrib.getParent().setAttribute(key, value);
					fLibraryList.refresh(parentContainer);
				} else {
					ClasspathAttributeConfiguration config= fAttributeDescriptors.get(attrib.getKey());
					if (config != null) {
						IClasspathAttribute result= config.performRemove(attrib.getClasspathAttributeAccess());
						if (result != null) {
							attrib.setValue(result.getValue());
							fLibraryList.refresh(parentContainer);
						}
					}
				}
			}
		}
		if (fLibraryList.getSelectedElements().isEmpty()) {
			if (selectionAfter != null) {
				fLibraryList.selectElements(new StructuredSelection(selectionAfter));
			} else {
				fLibraryList.selectFirstElement();
			}
		} else {
			doSelectionChanged(fLibraryList);
		}
	}

	private void doAdd(List<Object> list) {
		if (canAdd(list)) {
			CPUserLibraryElement parentLibrary = getSingleSelectedLibrary(list);

			IPath selection= getWorkbenchWindowSelection();

			IPath selectedPaths[] = BuildPathDialogAccess.chooseJAREntries(this.getShell(), selection, new IPath[0]);

			if (selectedPaths != null) {
				List<CPListElement> elements = new ArrayList<>();
				for (IPath selectedPath : selectedPaths) {
					CPListElement cpElement = new CPListElement(parentLibrary, fDummyProject, IClasspathEntry.CPE_LIBRARY, selectedPath, null);
					cpElement.setAttribute(CPListElement.SOURCEATTACHMENT, BuildPathSupport.guessSourceAttachment(cpElement));
					cpElement.setAttribute(CPListElement.JAVADOC, BuildPathSupport.guessJavadocLocation(cpElement));

					elements.add(cpElement);

					parentLibrary.add(cpElement);
				}
				fLibraryList.refresh(parentLibrary);
				fLibraryList.selectElements(new StructuredSelection(elements));
				fLibraryList.expandElement(parentLibrary, 2);
			}
		}
	}

	private IPath getWorkbenchWindowSelection() {
		IWorkbenchWindow window= fWorkbench.getActiveWorkbenchWindow();
		if (window != null) {
			ISelection selection= window.getSelectionService().getSelection();
			if (selection instanceof IStructuredSelection) {
				IStructuredSelection structuredSelection= (IStructuredSelection) selection;
				Object element= structuredSelection.getFirstElement();
				if (element != null) {
					Object resource= Platform.getAdapterManager().getAdapter(element, IResource.class);
					if (resource != null) {
						return ((IResource) resource).getFullPath();
					}
					if (structuredSelection instanceof ITreeSelection) {
						TreePath treePath= ((ITreeSelection) structuredSelection).getPaths()[0];
						while ((treePath = treePath.getParentPath()) != null) {
							element= treePath.getLastSegment();
							resource= Platform.getAdapterManager().getAdapter(element, IResource.class);
							if (resource != null) {
								return ((IResource) resource).getFullPath();
							}
						}
					}
				}

			}
		}
		return null;
	}

	private void doAddExternal(List<Object> list) {
		if (canAdd(list)) {
			CPUserLibraryElement element= getSingleSelectedLibrary(list);
			editArchiveElement(null, element);
		}
	}

	private void doLoad() {
		List<CPUserLibraryElement> existing= fLibraryList.getElements();
		LoadSaveDialog dialog= new LoadSaveDialog(getShell(), false, existing, fDialogSettings);
		if (dialog.open() == Window.OK) {
			HashMap<String, CPUserLibraryElement> map= new HashMap<>(existing.size());
			for (CPUserLibraryElement elem : existing) {
				map.put(elem.getName(), elem);
			}

			List<CPUserLibraryElement> list= dialog.getLoadedLibraries();
			for (int i= 0; i < list.size(); i++) {
				CPUserLibraryElement elem= list.get(i);
				CPUserLibraryElement found= map.get(elem.getName());
				if (found == null) {
					existing.add(elem);
					map.put(elem.getName(), elem);
				} else {
					existing.set(existing.indexOf(found), elem); // replace
				}
			}
			fLibraryList.setElements(existing);
			fLibraryList.selectElements(new StructuredSelection(list));
		}
	}

	private void doSave() {
		LoadSaveDialog dialog= new LoadSaveDialog(getShell(), true, fLibraryList.getElements(), fDialogSettings);
		dialog.open();
	}

	private boolean canAdd(List<Object> list) {
		return getSingleSelectedLibrary(list) != null;
	}

	private boolean canEdit(List<Object> list) {
		if (list.size() != 1)
			return false;

		Object firstElement= list.get(0);
		if (firstElement instanceof IAccessRule)
			return false;
		if (firstElement instanceof CPListElementAttribute) {
			CPListElementAttribute attrib= (CPListElementAttribute) firstElement;
			if (!attrib.isBuiltIn()) {
				ClasspathAttributeConfiguration config= fAttributeDescriptors.get(attrib.getKey());
				return config != null && config.canEdit(attrib.getClasspathAttributeAccess());
			}
		}
		return true;
	}

	private boolean canRemove(List<Object> list) {
		if (list.isEmpty()) {
			return false;
		}
		for (Object elem : list) {
			if (elem instanceof CPListElementAttribute) {
				CPListElementAttribute attrib= (CPListElementAttribute) elem;
				if (attrib.isNonModifiable()) {
					return false;
				}
				if (attrib.isBuiltIn()) {
					if (attrib.getKey().equals(CPListElement.ACCESSRULES)) {
						return ((IAccessRule[]) attrib.getValue()).length > 0;
					}
					if (attrib.getValue() == null) {
						return false;
					}
				} else {
					ClasspathAttributeConfiguration config= fAttributeDescriptors.get(attrib.getKey());
					if (config == null || !config.canRemove(attrib.getClasspathAttributeAccess()) ) {
						return false;
					}
				}
			} else if (elem instanceof CPListElement
					|| elem instanceof CPUserLibraryElement) {
				// ok to remove
			} else { // unknown element
				return false;
			}
		}
		return true;
	}

	private CPUserLibraryElement getCommonParent(List<?> list) {
		CPUserLibraryElement parent= null;
		for (Object curr : list) {
			if (curr instanceof CPListElement) {
				Object elemParent= ((CPListElement) curr).getParentContainer();
				if (parent == null) {
					if (elemParent instanceof CPUserLibraryElement) {
						parent= (CPUserLibraryElement) elemParent;
					} else {
						return null;
					}
				} else if (parent != elemParent) {
					return null;
				}
			} else {
				return null;
			}
		}
		return parent;
	}

	private void doMoveUp(List<?> list) {
		CPUserLibraryElement parent= getCommonParent(list);
		if (parent != null) {
			@SuppressWarnings("unchecked")
			List<CPListElement> cpElementList= (List<CPListElement>) list;
			parent.moveUp(cpElementList);
			fLibraryList.refresh(parent);
			doSelectionChanged(fLibraryList);
		}
	}

	private void doMoveDown(List<?> list) {
		CPUserLibraryElement parent= getCommonParent(list);
		if (parent != null) {
			@SuppressWarnings("unchecked")
			List<CPListElement> cpElementList= (List<CPListElement>) list;
			parent.moveDown(cpElementList);
			fLibraryList.refresh(parent);
			doSelectionChanged(fLibraryList);
		}
	}


	private boolean canMoveUp(List<?> list) {
		CPUserLibraryElement parent= getCommonParent(list);
		if (parent != null) {
			CPListElement[] children= parent.getChildren();
			for (int i= 0, len= Math.min(list.size(), children.length); i < len ; i++) {
				if (!list.contains(children[i])) {
					return true;
				}
			}
		}
		return false;
	}

	private boolean canMoveDown(List<?> list) {
		CPUserLibraryElement parent= getCommonParent(list);
		if (parent != null) {
			CPListElement[] children= parent.getChildren();
			for (int i= children.length - 1, end= Math.max(0, children.length - list.size()); i >= end; i--) {
				if (!list.contains(children[i])) {
					return true;
				}
			}
		}
		return false;
	}

	private CPListElement[] openJarFileDialog(CPListElement existing, Object parent) {
		if (existing == null) {
			return doOpenExternalJarFileDialog(existing, parent);
		}

		IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
		IPath path = existing.getPath();

		if (root.exists(path)) {
			return doOpenInternalJarFileDialog(existing, parent);
		}
		return doOpenExternalJarFileDialog(existing, parent);
	}

	private CPListElement[] doOpenInternalJarFileDialog(CPListElement existing, Object parent) {
		IPath path = existing.getPath();
		IPath selectedPaths[] = BuildPathDialogAccess.chooseJAREntries(this.getShell(), path, new IPath[0]);

		if (selectedPaths != null) {
			List<CPListElement> elements = new ArrayList<>();
			for (IPath selectedPath : selectedPaths) {
				CPListElement cpElement = new CPListElement(parent, fDummyProject, IClasspathEntry.CPE_LIBRARY, selectedPath, null);
				cpElement.setAttribute(CPListElement.SOURCEATTACHMENT, BuildPathSupport.guessSourceAttachment(cpElement));
				cpElement.setAttribute(CPListElement.JAVADOC, BuildPathSupport.guessJavadocLocation(cpElement));

				elements.add(cpElement);
			}
			return elements.toArray(new CPListElement[0]);
		}
		return null;
	}

	private CPListElement[] doOpenExternalJarFileDialog(CPListElement existing, Object parent) {
		String lastUsedPath;
		if (existing != null) {
			lastUsedPath= existing.getPath().removeLastSegments(1).toOSString();
		} else {
			lastUsedPath= fDialogSettings.get(IUIConstants.DIALOGSTORE_LASTEXTJAR);
			if (lastUsedPath == null) {
				lastUsedPath= ""; //$NON-NLS-1$
			}
		}
		String title= (existing == null) ? PreferencesMessages.UserLibraryPreferencePage_browsejar_new_title : PreferencesMessages.UserLibraryPreferencePage_browsejar_edit_title;

		FileDialog dialog= new FileDialog(getShell(), SWT.SHEET | (existing == null ? SWT.MULTI : SWT.SINGLE));
		dialog.setText(title);
		dialog.setFilterExtensions(ArchiveFileFilter.ALL_ARCHIVES_FILTER_EXTENSIONS);
		dialog.setFilterPath(lastUsedPath);
		if (existing != null) {
			dialog.setFileName(existing.getPath().lastSegment());
		}

		String res= dialog.open();
		if (res == null) {
			return null;
		}
		String[] fileNames= dialog.getFileNames();
		int nChosen= fileNames.length;

		IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();

		IPath filterPath= Path.fromOSString(dialog.getFilterPath());
		CPListElement[] elems= new CPListElement[nChosen];
		for (int i= 0; i < nChosen; i++) {
			IPath path= filterPath.append(fileNames[i]).makeAbsolute();

			IFile file= root.getFileForLocation(path); // support internal JARs: bug 133191
			if (file != null) {
				path= file.getFullPath();
			}

			CPListElement curr= new CPListElement(parent, null, IClasspathEntry.CPE_LIBRARY, path, file);
			curr.setAttribute(CPListElement.SOURCEATTACHMENT, BuildPathSupport.guessSourceAttachment(curr));
			curr.setAttribute(CPListElement.JAVADOC, BuildPathSupport.guessJavadocLocation(curr));
			elems[i]= curr;
		}
		fDialogSettings.put(IUIConstants.DIALOGSTORE_LASTEXTJAR, dialog.getFilterPath());

		return elems;
	}


	private class UserLibraryAdapter implements ITreeListAdapter<CPUserLibraryElement> {

		private final Object[] EMPTY= new Object[0];

		@Override
		public void customButtonPressed(TreeListDialogField<CPUserLibraryElement> field, int index) {
			doCustomButtonPressed(field, index);
		}

		@Override
		public void selectionChanged(TreeListDialogField<CPUserLibraryElement> field) {
			doSelectionChanged(field);
		}

		@Override
		public void doubleClicked(TreeListDialogField<CPUserLibraryElement> field) {
			doDoubleClicked(field);
		}

		@Override
		public void keyPressed(TreeListDialogField<CPUserLibraryElement> field, KeyEvent event) {
			doKeyPressed(field, event);
		}

		@Override
		public Object[] getChildren(TreeListDialogField<CPUserLibraryElement> field, Object element) {
			if (element instanceof CPUserLibraryElement) {
				CPUserLibraryElement elem= (CPUserLibraryElement) element;
				return elem.getChildren();
			} else if (element instanceof CPListElement) {
				return ((CPListElement)element).getChildren(false);
			} else if (element instanceof CPListElementAttribute) {
				CPListElementAttribute attribute= (CPListElementAttribute) element;
				if (CPListElement.ACCESSRULES.equals(attribute.getKey())) {
					return (IAccessRule[]) attribute.getValue();
				}
				if (CPListElement.MODULE.equals(attribute.getKey())) {
					return (ModuleEncapsulationDetail[]) attribute.getValue();
				}
			}
			return EMPTY;
		}

		@Override
		public Object getParent(TreeListDialogField<CPUserLibraryElement> field, Object element) {
			if (element instanceof CPListElementAttribute) {
				return ((CPListElementAttribute) element).getParent();
			} else if (element instanceof CPListElement) {
				return ((CPListElement) element).getParentContainer();
			}
			return null;
		}

		@Override
		public boolean hasChildren(TreeListDialogField<CPUserLibraryElement> field, Object element) {
			Object[] children= getChildren(field, element);
			return children == null ? false : children.length > 0;
		}

	}


}
