001 /**
002 * <copyright>
003 *
004 * Copyright (c) 2002-2007 IBM Corporation and others.
005 * All rights reserved. This program and the accompanying materials
006 * are made available under the terms of the Eclipse Public License v1.0
007 * which accompanies this distribution, and is available at
008 * http://www.eclipse.org/legal/epl-v10.html
009 *
010 * Contributors:
011 * IBM - Initial API and implementation
012 *
013 * </copyright>
014 *
015 * $Id: CommonPlugin.java,v 1.14 2009/10/20 09:50:21 emerks Exp $
016 */
017 package org.eclipse.emf.common;
018
019
020 import java.io.IOException;
021 import java.lang.reflect.Method;
022 import java.net.URL;
023 import java.text.Collator;
024 import java.util.Comparator;
025 import java.util.Locale;
026
027 import org.eclipse.core.runtime.FileLocator;
028 import org.eclipse.core.runtime.Platform;
029 import org.eclipse.emf.common.util.ResourceLocator;
030 import org.eclipse.emf.common.util.URI;
031 import org.osgi.framework.Bundle;
032
033
034 /**
035 * The <b>Plugin</b> for the model EMF.Common library.
036 * EMF must run
037 * within an Eclipse workbench,
038 * within a headless Eclipse workspace,
039 * or just stand-alone as part of some other application.
040 * To support this, all resource access should be directed to the resource locator,
041 * which can redirect the service as appropriate to the runtime.
042 * During stand-alone invocation no plugin initialization takes place.
043 * In this case, common.resources.jar must be on the CLASSPATH.
044 * @see #INSTANCE
045 */
046 public final class CommonPlugin extends EMFPlugin
047 {
048 /**
049 * The singleton instance of the plugin.
050 */
051 public static final CommonPlugin INSTANCE = new CommonPlugin();
052
053 /**
054 * The one instance of this class.
055 */
056 private static Implementation plugin;
057
058 /**
059 * Creates the singleton instance.
060 */
061 private CommonPlugin()
062 {
063 super(new ResourceLocator[] {});
064 }
065
066 @Override
067 public ResourceLocator getPluginResourceLocator()
068 {
069 return plugin;
070 }
071
072 /**
073 * Returns the singleton instance of the Eclipse plugin.
074 * @return the singleton instance.
075 */
076 public static Implementation getPlugin()
077 {
078 return plugin;
079 }
080
081 /**
082 * Use the platform, if available, to convert to a local URI.
083 */
084 public static URI asLocalURI(URI uri)
085 {
086 return plugin == null ? uri : Implementation.asLocalURI(uri);
087 }
088
089 /**
090 * Use the platform, if available, to resolve the URI.
091 */
092 public static URI resolve(URI uri)
093 {
094 return plugin == null ? uri : Implementation.resolve(uri);
095 }
096
097 /**
098 * Use the platform, if available, to load the named class using the right class loader.
099 */
100 public static Class<?> loadClass(String pluginID, String className) throws ClassNotFoundException
101 {
102 return plugin == null ? Class.forName(className) : Implementation.loadClass(pluginID, className);
103 }
104
105 private static final Method COLLATOR_GET_INSTANCE_METHOD;
106 static
107 {
108 Method collatorGetInstanceMethod = null;
109 try
110 {
111 Class<?> collatorClass = loadClass("com.ibm.icu", "com.ibm.icu.text.Collator");
112 collatorGetInstanceMethod = collatorClass.getMethod("getInstance", Locale.class);
113 }
114 catch (Throwable throwable)
115 {
116 // Assume the class is not available.
117 }
118 COLLATOR_GET_INSTANCE_METHOD = collatorGetInstanceMethod;
119 }
120
121 /**
122 * Returns a string comparator appropriate for collating strings for the {@link Locale#getDefault() current locale}.
123 * @return a string comparator appropriate for collating strings for the {@link Locale#getDefault() current locale}.
124 */
125 public Comparator<String> getComparator()
126 {
127 return getComparator(Locale.getDefault());
128 }
129
130 /**
131 * Returns a string comparator appropriate for collating strings for the give locale.
132 * This will use ICU, when available that plugins is available, or {@link Collator} otherwise.
133 * @param locale the locale for which a comparator is needed.
134 * @return a string comparator appropriate for collating strings for the give locale.
135 */
136 @SuppressWarnings("unchecked")
137 public Comparator<String> getComparator(Locale locale)
138 {
139 if (COLLATOR_GET_INSTANCE_METHOD != null)
140 {
141 try
142 {
143 return (Comparator<String>)COLLATOR_GET_INSTANCE_METHOD.invoke(null, locale);
144 }
145 catch (Throwable eception)
146 {
147 // Just return the default.
148 }
149 }
150 return (Comparator<String>)(Comparator<?>)Collator.getInstance(locale);
151 }
152
153 /**
154 * The actual implementation of the Eclipse <b>Plugin</b>.
155 */
156 public static class Implementation extends EclipsePlugin
157 {
158 /**
159 * Creates an instance.
160 */
161 public Implementation()
162 {
163 super();
164
165 // Remember the static instance.
166 //
167 plugin = this;
168 }
169
170 /**
171 * Use the platform to convert to a local URI.
172 */
173 protected static URI asLocalURI(URI uri)
174 {
175 try
176 {
177 String fragment = uri.fragment();
178 URL url = FileLocator.toFileURL(new URL(uri.trimFragment().toString()));
179 return fix(url, fragment);
180 }
181 catch (IOException exception)
182 {
183 // Ignore the exception and return the original URI.
184 }
185 return uri;
186 }
187
188 /**
189 * Use the platform to convert to a local URI.
190 */
191 protected static URI resolve(URI uri)
192 {
193 String fragment = uri.fragment();
194 URI uriWithoutFragment = uri.trimFragment();
195 String uriWithoutFragmentToString = uriWithoutFragment.toString();
196
197 URL url = null;
198 try
199 {
200 url = FileLocator.resolve(new URL(uriWithoutFragmentToString));
201 }
202 catch (IOException exception1)
203 {
204 // Platform.resolve() doesn't work if the project is encoded.
205 //
206 try
207 {
208 uriWithoutFragmentToString = URI.decode(uriWithoutFragmentToString);
209 url = FileLocator.resolve(new URL(uriWithoutFragmentToString));
210 }
211 catch (IOException exception2)
212 {
213 // Continue with the unresolved URI.
214 }
215 }
216 if (url != null)
217 {
218 try
219 {
220 return fix(url, fragment);
221 }
222 catch (IOException exception)
223 {
224 // Return the original URI.
225 }
226 }
227
228 return uri;
229 }
230
231 protected static URI fix(URL url, String fragment) throws IOException
232 {
233 // Only file-scheme URIs will be re-encoded. If a URI was decoded in the workaround
234 // above, and Platform.resolve() didn't return a file-scheme URI, then this will return
235 // an decoded URI.
236 //
237 URI result =
238 "file".equalsIgnoreCase(url.getProtocol()) ?
239 URI.createFileURI(URI.decode(url.getFile())) :
240 URI.createURI(url.toString());
241 if (fragment != null)
242 {
243 result = result.appendFragment(fragment);
244 }
245 return result;
246 }
247
248 /**
249 * Use the platform to load the named class using the right class loader.
250 */
251 public static Class<?> loadClass(String pluginID, String className) throws ClassNotFoundException
252 {
253 Bundle bundle = Platform.getBundle(pluginID);
254 if (bundle == null)
255 {
256 throw new ClassNotFoundException(className + " cannot be loaded because because bundle " + pluginID + " cannot be resolved");
257 }
258 else
259 {
260 return bundle.loadClass(className);
261 }
262 }
263 }
264 }