1 /******************************************************************************* 2 * Copyright (c) 2006, 2019 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 * Christian Dietrich (itemis AG) - fix for bug #549409 14 * Alexander Fedorov <alexander.fedorov@arsysop.ru> - Bug 549409 15 ******************************************************************************/ 16 17 package org.eclipse.ui.internal.ide.filesystem; 18 19 import java.io.File; 20 import java.net.URI; 21 import java.util.Collection; 22 import java.util.HashSet; 23 import java.util.stream.Stream; 24 25 import org.eclipse.core.filesystem.IFileInfo; 26 import org.eclipse.core.runtime.CoreException; 27 import org.eclipse.core.runtime.IConfigurationElement; 28 import org.eclipse.core.runtime.IExtension; 29 import org.eclipse.core.runtime.IExtensionPoint; 30 import org.eclipse.core.runtime.ISafeRunnable; 31 import org.eclipse.core.runtime.Platform; 32 import org.eclipse.core.runtime.SafeRunner; 33 import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker; 34 import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler; 35 import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker; 36 import org.eclipse.swt.SWT; 37 import org.eclipse.swt.widgets.DirectoryDialog; 38 import org.eclipse.swt.widgets.Shell; 39 import org.eclipse.ui.PlatformUI; 40 import org.eclipse.ui.ide.fileSystem.FileSystemContributor; 41 import org.eclipse.ui.internal.ide.IDEWorkbenchMessages; 42 import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; 43 import org.eclipse.ui.internal.ide.dialogs.IDEResourceInfoUtils; 44 45 /** 46 * @since 3.2 47 * 48 */ 49 public class FileSystemSupportRegistry implements IExtensionChangeHandler { 50 51 private static final String FILESYSTEM_SUPPORT = "filesystemSupport";//$NON-NLS-1$ 52 53 protected static final String ATT_CLASS = "class"; //$NON-NLS-1$ 54 55 private static final String LABEL = "label";//$NON-NLS-1$ 56 57 private static final String SCHEME = "scheme";//$NON-NLS-1$ 58 59 private static FileSystemSupportRegistry singleton; 60 61 /** 62 * Get the instance of the registry. 63 * 64 * @return MarkerSupportRegistry 65 */ getInstance()66 public static FileSystemSupportRegistry getInstance() { 67 if (singleton == null) { 68 singleton = new FileSystemSupportRegistry(); 69 } 70 return singleton; 71 } 72 73 private Collection<FileSystemConfiguration> registeredContributions = new HashSet<>(0); 74 75 FileSystemConfiguration defaultConfiguration = new FileSystemConfiguration( 76 FileSystemMessages.DefaultFileSystem_name, new FileSystemContributor() { 77 @Override 78 public URI browseFileSystem(String initialPath, Shell shell) { 79 80 DirectoryDialog dialog = new DirectoryDialog(shell, SWT.SHEET); 81 dialog 82 .setMessage(IDEWorkbenchMessages.ProjectLocationSelectionDialog_directoryLabel); 83 84 if (!initialPath.equals(IDEResourceInfoUtils.EMPTY_STRING)) { 85 IFileInfo info = IDEResourceInfoUtils 86 .getFileInfo(initialPath); 87 if (info != null && info.exists()) { 88 dialog.setFilterPath(initialPath); 89 } 90 } 91 92 String selectedDirectory = dialog.open(); 93 if (selectedDirectory == null) { 94 return null; 95 } 96 return new File(selectedDirectory).toURI(); 97 98 } 99 }, null); 100 101 /** 102 * Create a new instance of the receiver. 103 */ FileSystemSupportRegistry()104 public FileSystemSupportRegistry() { 105 IExtensionTracker tracker = PlatformUI.getWorkbench().getExtensionTracker(); 106 IExtensionPoint point = Platform.getExtensionRegistry() 107 .getExtensionPoint(IDEWorkbenchPlugin.IDE_WORKBENCH, 108 FILESYSTEM_SUPPORT); 109 if (point == null) { 110 return; 111 } 112 // initial population 113 for (IExtension extension : point.getExtensions()) { 114 processExtension(tracker, extension); 115 } 116 tracker.registerHandler(this, ExtensionTracker.createExtensionPointFilter(point)); 117 } 118 119 @Override addExtension(IExtensionTracker tracker, IExtension extension)120 public void addExtension(IExtensionTracker tracker, IExtension extension) { 121 processExtension(tracker, extension); 122 } 123 124 @Override removeExtension(IExtension extension, Object[] objects)125 public void removeExtension(IExtension extension, Object[] objects) { 126 for (Object object : objects) { 127 registeredContributions.remove(object); 128 } 129 } 130 131 /** 132 * Process the extension and register the result with the tracker. 133 * 134 * @param tracker 135 * @param extension 136 */ processExtension(IExtensionTracker tracker, IExtension extension)137 private void processExtension(IExtensionTracker tracker, IExtension extension) { 138 for (IConfigurationElement configElement : extension.getConfigurationElements()) { 139 FileSystemConfiguration contribution = newConfiguration(configElement); 140 if (contribution != null) { 141 registeredContributions.add(contribution); 142 tracker.registerObject(extension, contribution, IExtensionTracker.REF_STRONG); 143 } 144 } 145 } 146 147 /** 148 * Return a new FileSystemContribution. 149 * 150 * @param element 151 * @return FileSystemContribution or <code>null</code> if there is an 152 * exception. 153 */ newConfiguration( final IConfigurationElement element)154 private FileSystemConfiguration newConfiguration( 155 final IConfigurationElement element) { 156 157 final FileSystemContributor[] contributors = new FileSystemContributor[1]; 158 final CoreException[] exceptions = new CoreException[1]; 159 160 SafeRunner.run(new ISafeRunnable() { 161 @Override 162 public void run() { 163 try { 164 contributors[0] = (FileSystemContributor) IDEWorkbenchPlugin 165 .createExtension(element, ATT_CLASS); 166 167 } catch (CoreException exception) { 168 exceptions[0] = exception; 169 IDEWorkbenchPlugin.getDefault().getLog().log(exception.getStatus()); 170 } 171 } 172 173 @Override 174 public void handleException(Throwable e) { 175 IDEWorkbenchPlugin.log(FileSystemMessages.FileSystemSupportRegistry_e_creating_extension, e); 176 } 177 }); 178 179 if (exceptions[0] != null) { 180 return null; 181 } 182 String name = element.getAttribute(LABEL); 183 String fileSystem = element.getAttribute(SCHEME); 184 return new FileSystemConfiguration(name, 185 contributors[0], fileSystem); 186 187 } 188 189 /** 190 * Return the FileSystemConfiguration defined in the receiver. 191 * 192 * @return FileSystemConfiguration[] 193 */ getConfigurations()194 public FileSystemConfiguration[] getConfigurations() { 195 return Stream.concat(Stream.of(defaultConfiguration), registeredContributions.stream()) 196 .toArray(FileSystemConfiguration[]::new); 197 } 198 199 /** 200 * Return the default file system configuration (the local file system 201 * extension in the ide plug-in). 202 * 203 * @return FileSystemConfiguration 204 */ getDefaultConfiguration()205 public FileSystemConfiguration getDefaultConfiguration() { 206 return defaultConfiguration; 207 } 208 209 /** 210 * Return whether or not there is only one file system registered. 211 * 212 * @return <code>true</code> if there is only one file system. 213 */ hasOneFileSystem()214 public boolean hasOneFileSystem() { 215 return registeredContributions.isEmpty(); 216 } 217 } 218