1 /******************************************************************************* 2 * Copyright (c) 2000, 2017 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 *******************************************************************************/ 14 package org.eclipse.team.internal.core; 15 16 import java.io.IOException; 17 import java.io.InputStream; 18 import java.io.OutputStream; 19 import java.util.ArrayList; 20 import java.util.Hashtable; 21 import java.util.List; 22 import java.util.StringTokenizer; 23 24 import org.eclipse.core.resources.IStorage; 25 import org.eclipse.core.runtime.CoreException; 26 import org.eclipse.core.runtime.IConfigurationElement; 27 import org.eclipse.core.runtime.IExtension; 28 import org.eclipse.core.runtime.IExtensionPoint; 29 import org.eclipse.core.runtime.IPath; 30 import org.eclipse.core.runtime.IProgressMonitor; 31 import org.eclipse.core.runtime.IStatus; 32 import org.eclipse.core.runtime.Path; 33 import org.eclipse.core.runtime.Platform; 34 import org.eclipse.core.runtime.Plugin; 35 import org.eclipse.core.runtime.QualifiedName; 36 import org.eclipse.core.runtime.Status; 37 import org.eclipse.core.runtime.content.IContentDescription; 38 import org.eclipse.core.runtime.content.IContentTypeManager; 39 import org.eclipse.osgi.service.debug.DebugOptions; 40 import org.eclipse.osgi.service.debug.DebugOptionsListener; 41 import org.eclipse.team.core.RepositoryProvider; 42 import org.eclipse.team.core.RepositoryProviderType; 43 import org.eclipse.team.core.Team; 44 import org.eclipse.team.core.TeamException; 45 import org.eclipse.team.core.mapping.DelegatingStorageMerger; 46 import org.eclipse.team.internal.core.mapping.IStreamMergerDelegate; 47 import org.osgi.framework.BundleContext; 48 import org.osgi.framework.ServiceRegistration; 49 50 /** 51 * <code>TeamPlugin</code> is the plug-in runtime class for the Team 52 * resource management plugin. 53 * <p> 54 * 55 * @see Team 56 * @see RepositoryProvider 57 * 58 * @since 2.0 59 */ 60 final public class TeamPlugin extends Plugin { 61 62 // The id of the core team plug-in 63 public static final String ID = "org.eclipse.team.core"; //$NON-NLS-1$ 64 65 // The id of the providers extension point 66 public static final String PROVIDER_EXTENSION = "repository-provider-type"; //$NON-NLS-1$ 67 68 // The id of the file types extension point 69 public static final String FILE_TYPES_EXTENSION = "fileTypes"; //$NON-NLS-1$ 70 71 // The id of the global ignore extension point 72 public static final String IGNORE_EXTENSION = "ignore"; //$NON-NLS-1$ 73 // The id of the project set extension point 74 public static final String PROJECT_SET_EXTENSION = "projectSets"; //$NON-NLS-1$ 75 // The id of the repository extension point 76 public static final String REPOSITORY_EXTENSION = "repository"; //$NON-NLS-1$ 77 // The id of the default file modification validator extension point 78 public static final String DEFAULT_FILE_MODIFICATION_VALIDATOR_EXTENSION = "defaultFileModificationValidator"; //$NON-NLS-1$ 79 80 // The id used to associate a provider with a project 81 public final static QualifiedName PROVIDER_PROP_KEY = 82 new QualifiedName("org.eclipse.team.core", "repository"); //$NON-NLS-1$ //$NON-NLS-2$ 83 84 // The id for the Bundle Import extension point 85 public static final String EXTENSION_POINT_BUNDLE_IMPORTERS = ID + ".bundleImporters"; //$NON-NLS-1$ 86 87 // The one and only plug-in instance 88 private static TeamPlugin plugin; 89 90 private ServiceRegistration debugRegistration; 91 private IStreamMergerDelegate mergerDelegate; 92 93 /** 94 * Constructs a plug-in runtime class. 95 */ TeamPlugin()96 public TeamPlugin() { 97 super(); 98 plugin = this; 99 } 100 101 @Override start(BundleContext context)102 public void start(BundleContext context) throws Exception { 103 super.start(context); 104 105 // register debug options listener 106 Hashtable<String, String> properties = new Hashtable<>(2); 107 properties.put(DebugOptions.LISTENER_SYMBOLICNAME, ID); 108 debugRegistration = context.registerService(DebugOptionsListener.class, Policy.DEBUG_OPTIONS_LISTENER, properties); 109 110 Team.startup(); 111 } 112 113 @Override stop(BundleContext context)114 public void stop(BundleContext context) throws Exception { 115 try { 116 // unregister debug options listener 117 debugRegistration.unregister(); 118 debugRegistration = null; 119 120 Team.shutdown(); 121 ResourceVariantCache.shutdown(); 122 } finally { 123 super.stop(context); 124 } 125 } 126 127 /** 128 * Returns the Team plug-in. 129 * 130 * @return the single instance of this plug-in runtime class 131 */ getPlugin()132 public static TeamPlugin getPlugin() { 133 return plugin; 134 } 135 136 /** 137 * Log the given exception allowing with the provided message and severity indicator 138 * @param severity the severity 139 * @param message the message 140 * @param e the exception 141 */ log(int severity, String message, Throwable e)142 public static void log(int severity, String message, Throwable e) { 143 plugin.getLog().log(new Status(severity, ID, 0, message, e)); 144 } 145 146 /** 147 * Log the given CoreException in a manner that will include the stacktrace of 148 * the exception in the log. 149 * @param e the exception 150 */ log(CoreException e)151 public static void log(CoreException e) { 152 log(e.getStatus().getSeverity(), e.getMessage(), e); 153 } 154 155 /* 156 * Static helper methods for creating exceptions 157 */ wrapException(CoreException e)158 public static TeamException wrapException(CoreException e) { 159 IStatus status = e.getStatus(); 160 return new TeamException(new Status(status.getSeverity(), ID, status.getCode(), status.getMessage(), e)); 161 } 162 getCharset(String name, InputStream stream)163 public static String getCharset(String name, InputStream stream) throws IOException { 164 IContentDescription description = getContentDescription(name, stream); 165 return description == null ? null : description.getCharset(); 166 167 } getContentDescription(String name, InputStream stream)168 public static IContentDescription getContentDescription(String name, InputStream stream) throws IOException { 169 // tries to obtain a description for this file contents 170 IContentTypeManager contentTypeManager = Platform.getContentTypeManager(); 171 try { 172 return contentTypeManager.getDescriptionFor(stream, name, IContentDescription.ALL); 173 } finally { 174 if (stream != null) 175 try { 176 stream.close(); 177 } catch (IOException e) { 178 // Ignore exceptions on close 179 } 180 } 181 } 182 getAliasType(String id)183 public static RepositoryProviderType getAliasType(String id) { 184 IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(TeamPlugin.ID, TeamPlugin.REPOSITORY_EXTENSION); 185 if (extension != null) { 186 IExtension[] extensions = extension.getExtensions(); 187 for (IExtension ext : extensions) { 188 IConfigurationElement[] configElements = ext.getConfigurationElements(); 189 for (IConfigurationElement configElement : configElements) { 190 String aliasId = configElement.getAttribute("canImportId"); //$NON-NLS-1$ 191 if (aliasId != null && aliasId.equals(id)) { 192 String extensionId = configElement.getAttribute("id"); //$NON-NLS-1$ 193 if (extensionId != null) { 194 return RepositoryProviderType.getProviderType(extensionId); 195 } 196 } 197 } 198 } 199 } 200 return null; 201 } 202 getMetaFilePaths(String id)203 public static IPath[] getMetaFilePaths(String id) { 204 IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(TeamPlugin.ID, TeamPlugin.REPOSITORY_EXTENSION); 205 if (extension != null) { 206 IExtension[] extensions = extension.getExtensions(); 207 for (IExtension ext : extensions) { 208 IConfigurationElement[] configElements = ext.getConfigurationElements(); 209 for (IConfigurationElement configElement : configElements) { 210 String extensionId = configElement.getAttribute("id"); //$NON-NLS-1$ 211 String metaFilePaths = configElement.getAttribute("metaFilePaths"); //$NON-NLS-1$ 212 if (extensionId != null && extensionId.equals(id) && metaFilePaths != null) { 213 return getPaths(metaFilePaths); 214 215 } 216 } 217 } 218 } 219 return null; 220 } 221 getPaths(String metaFilePaths)222 private static IPath[] getPaths(String metaFilePaths) { 223 List<IPath> result = new ArrayList<>(); 224 StringTokenizer t = new StringTokenizer(metaFilePaths, ","); //$NON-NLS-1$ 225 while (t.hasMoreTokens()) { 226 String next = t.nextToken(); 227 IPath path = new Path(null, next); 228 result.add(path); 229 } 230 return result.toArray(new IPath[result.size()]); 231 } 232 233 /** 234 * Set the file merger that is used by the {@link DelegatingStorageMerger#merge(OutputStream, String, IStorage, IStorage, IStorage, IProgressMonitor)} 235 * method. It is the responsibility of subclasses to provide a merger. 236 * If a merger is not provided, subclasses must override <code>performThreeWayMerge</code>. 237 * @param merger the merger used to merge files 238 */ setMergerDelegate(IStreamMergerDelegate merger)239 public void setMergerDelegate(IStreamMergerDelegate merger) { 240 mergerDelegate = merger; 241 } 242 getMergerDelegate()243 public IStreamMergerDelegate getMergerDelegate() { 244 return mergerDelegate; 245 } 246 247 } 248