1 /*******************************************************************************
2 * Copyright (c) 2000, 2007 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/13 moduleorg.eclipse.swt.internal.Compatibility;
14 15 importjava.lang.all;
16 importjava.io.BufferedInputStream;
17 importjava.io.File;
18 importjava.io.InputStream;
19 importjava.io.FileInputStream;
20 importjava.io.FileOutputStream;
21 importjava.text.MessageFormat;
22 importjava.util.MissingResourceException;
23 importjava.util.ResourceBundle;
24 importjava.util.zip.InflaterInputStream;
25 importjava.util.zip.DeflaterOutputStream;
26 27 importorg.eclipse.swt.SWT;
28 29 version(Tango){
30 importUnicode = tango.text.Unicode;
31 importtango.sys.Process;
32 } else { // Phobos33 }
34 35 /**
36 * This class is a placeholder for utility methods commonly
37 * used on J2SE platforms but not supported on some J2ME
38 * profiles.
39 * <p>
40 * It is part of our effort to provide support for both J2SE
41 * and J2ME platforms.
42 * </p>
43 * <p>
44 * IMPORTANT: some of the methods have been modified from their
45 * J2SE parents. Refer to the description of each method for
46 * specific changes.
47 * </p>
48 * <ul>
49 * <li>Exceptions thrown may differ since J2ME's set of
50 * exceptions is a subset of J2SE's one.
51 * </li>
52 * <li>The range of the mathematic functions is subject to
53 * change.
54 * </li>
55 * </ul>
56 */57 publicfinalclassCompatibility {
58 59 /**
60 * Returns the PI constant as a double.
61 */62 publicstaticconstrealPI = Math.PI;
63 64 staticconstrealtoRadians = PI / 180;
65 66 /**
67 * Answers the length of the side adjacent to the given angle
68 * of a right triangle. In other words, it returns the integer
69 * conversion of length * cos (angle).
70 * <p>
71 * IMPORTANT: the j2me version has an additional restriction on
72 * the argument. length must be between -32767 and 32767 (inclusive).
73 * </p>
74 *
75 * @param angle the angle in degrees
76 * @param length the length of the triangle's hypotenuse
77 * @return the integer conversion of length * cos (angle)
78 */79 publicstaticintcos(intangle, intlength) {
80 returncast(int)(Math.cos(angle * toRadians) * length);
81 }
82 83 /**
84 * Answers the length of the side opposite to the given angle
85 * of a right triangle. In other words, it returns the integer
86 * conversion of length * sin (angle).
87 * <p>
88 * IMPORTANT: the j2me version has an additional restriction on
89 * the argument. length must be between -32767 and 32767 (inclusive).
90 * </p>
91 *
92 * @param angle the angle in degrees
93 * @param length the length of the triangle's hypotenuse
94 * @return the integer conversion of length * sin (angle)
95 */96 publicstaticintsin(intangle, intlength) {
97 returncast(int)(Math.sin(angle * toRadians) * length);
98 }
99 100 /**
101 * Answers the most negative (i.e. closest to negative infinity)
102 * integer value which is greater than the number obtained by dividing
103 * the first argument p by the second argument q.
104 *
105 * @param p numerator
106 * @param q denominator (must be different from zero)
107 * @return the ceiling of the rational number p / q.
108 */109 publicstaticintceil(intp, intq) {
110 returncast(int)Math.ceil(cast(float)p / q);
111 }
112 113 /**
114 * Answers whether the indicated file exists or not.
115 *
116 * @param parent the file's parent directory
117 * @param child the file's name
118 * @return true if the file exists
119 */120 publicstaticboolfileExists(Stringparent, Stringchild) {
121 scopef = newFile(parent, child);
122 returnf.exists();
123 }
124 125 /**
126 * Answers the most positive (i.e. closest to positive infinity)
127 * integer value which is less than the number obtained by dividing
128 * the first argument p by the second argument q.
129 *
130 * @param p numerator
131 * @param q denominator (must be different from zero)
132 * @return the floor of the rational number p / q.
133 */134 publicstaticintfloor(intp, intq) {
135 returncast(int)Math.floor(cast(double)p / q);
136 }
137 138 /**
139 * Answers the result of rounding to the closest integer the number obtained
140 * by dividing the first argument p by the second argument q.
141 * <p>
142 * IMPORTANT: the j2me version has an additional restriction on
143 * the arguments. p must be within the range 0 - 32767 (inclusive).
144 * q must be within the range 1 - 32767 (inclusive).
145 * </p>
146 *
147 * @param p numerator
148 * @param q denominator (must be different from zero)
149 * @return the closest integer to the rational number p / q
150 */151 publicstaticintround(intp, intq) {
152 returncast(int)Math.round(cast(float)p / q);
153 }
154 155 /**
156 * Returns 2 raised to the power of the argument.
157 *
158 * @param n an int value between 0 and 30 (inclusive)
159 * @return 2 raised to the power of the argument
160 *
161 * @exception IllegalArgumentException <ul>
162 * <li>ERROR_INVALID_RANGE - if the argument is not between 0 and 30 (inclusive)</li>
163 * </ul>
164 */165 publicstaticintpow2(intn) {
166 if (n >= 1 && n <= 30)
167 return2 << (n - 1);
168 elseif (n != 0) {
169 SWT.error(SWT.ERROR_INVALID_RANGE);
170 }
171 return1;
172 }
173 174 /**
175 * Create an DeflaterOutputStream if such things are supported.
176 *
177 * @param stream the output stream
178 * @return a deflater stream or <code>null</code>
179 * @exception IOException
180 *
181 * @since 3.4
182 */183 publicstaticOutputStreamnewDeflaterOutputStream(OutputStreamstream) {
184 returnnewDeflaterOutputStream(stream);
185 }
186 187 /**
188 * Open a file if such things are supported.
189 *
190 * @param filename the name of the file to open
191 * @return a stream on the file if it could be opened.
192 * @exception IOException
193 */194 publicstaticInputStreamnewFileInputStream(Stringfilename) {
195 returnnewFileInputStream(filename);
196 }
197 198 /**
199 * Open a file if such things are supported.
200 *
201 * @param filename the name of the file to open
202 * @return a stream on the file if it could be opened.
203 * @exception IOException
204 */205 publicstaticOutputStreamnewFileOutputStream(Stringfilename) {
206 returnnewFileOutputStream(filename);
207 }
208 209 /**
210 * Create an InflaterInputStream if such things are supported.
211 *
212 * @param stream the input stream
213 * @return a inflater stream or <code>null</code>
214 * @exception IOException
215 *
216 * @since 3.3
217 */218 publicstaticInflaterInputStreamnewInflaterInputStream(InputStreamstream) {
219 returnnewInflaterInputStream(stream);
220 }
221 222 /**
223 * Answers whether the character is a letter.
224 *
225 * @param c the character
226 * @return true when the character is a letter
227 */228 publicstaticboolisLetter(dcharc) {
229 returnCharacter.isLetter(c);
230 }
231 232 /**
233 * Answers whether the character is a letter or a digit.
234 *
235 * @param c the character
236 * @return true when the character is a letter or a digit
237 */238 publicstaticboolisLetterOrDigit(dcharc) {
239 returnCharacter.isLetterOrDigit(c);
240 }
241 242 /**
243 * Answers whether the character is a Unicode space character.
244 *
245 * @param c the character
246 * @return true when the character is a Unicode space character
247 */248 publicstaticboolisSpaceChar(dcharc) {
249 returnCharacter.isSpace(c);
250 }
251 252 /**
253 * Answers whether the character is a whitespace character.
254 *
255 * @param c the character to test
256 * @return true if the character is whitespace
257 */258 publicstaticboolisWhitespace(dcharc) {
259 returnCharacter.isWhitespace(c);
260 }
261 262 /**
263 * Execute a program in a separate platform process if the
264 * underlying platform support this.
265 * <p>
266 * The new process inherits the environment of the caller.
267 * </p>
268 *
269 * @param prog the name of the program to execute
270 *
271 * @exception ProcessException
272 * if the program cannot be executed
273 */274 publicstaticvoidexec(Stringprog) {
275 version(Tango){
276 autoproc = newProcess( prog );
277 proc.execute;
278 } else { // Phobos279 implMissingInPhobos();
280 }
281 }
282 283 /**
284 * Execute progArray[0] in a separate platform process if the
285 * underlying platform support this.
286 * <p>
287 * The new process inherits the environment of the caller.
288 * <p>
289 *
290 * @param progArray array containing the program to execute and its arguments
291 *
292 * @exception ProcessException
293 * if the program cannot be executed
294 */295 publicstaticvoidexec(String[] progArray) {
296 version(Tango){
297 autoproc = newProcess( progArray );
298 proc.execute;
299 } else { // Phobos300 implMissingInPhobos();
301 }
302 }
303 304 staticconstImportData[] SWTMessagesBundleData = [
305 getImportData!( "org.eclipse.swt.internal.SWTMessages.properties" ),
306 getImportData!( "org.eclipse.swt.internal.SWTMessages_ar.properties" ),
307 getImportData!( "org.eclipse.swt.internal.SWTMessages_cs.properties" ),
308 getImportData!( "org.eclipse.swt.internal.SWTMessages_da.properties" ),
309 getImportData!( "org.eclipse.swt.internal.SWTMessages_de.properties" ),
310 getImportData!( "org.eclipse.swt.internal.SWTMessages_el.properties" ),
311 getImportData!( "org.eclipse.swt.internal.SWTMessages_es.properties" ),
312 getImportData!( "org.eclipse.swt.internal.SWTMessages_fi.properties" ),
313 getImportData!( "org.eclipse.swt.internal.SWTMessages_fr.properties" ),
314 getImportData!( "org.eclipse.swt.internal.SWTMessages_hu.properties" ),
315 getImportData!( "org.eclipse.swt.internal.SWTMessages_it.properties" ),
316 getImportData!( "org.eclipse.swt.internal.SWTMessages_iw.properties" ),
317 getImportData!( "org.eclipse.swt.internal.SWTMessages_ja.properties" ),
318 getImportData!( "org.eclipse.swt.internal.SWTMessages_ko.properties" ),
319 getImportData!( "org.eclipse.swt.internal.SWTMessages_nl.properties" ),
320 getImportData!( "org.eclipse.swt.internal.SWTMessages_no.properties" ),
321 getImportData!( "org.eclipse.swt.internal.SWTMessages_pl.properties" ),
322 getImportData!( "org.eclipse.swt.internal.SWTMessages_pt_BR.properties" ),
323 getImportData!( "org.eclipse.swt.internal.SWTMessages_pt.properties" ),
324 getImportData!( "org.eclipse.swt.internal.SWTMessages_ru.properties" ),
325 getImportData!( "org.eclipse.swt.internal.SWTMessages_sv.properties" ),
326 getImportData!( "org.eclipse.swt.internal.SWTMessages_tr.properties" ),
327 getImportData!( "org.eclipse.swt.internal.SWTMessages_zh_HK.properties" ),
328 getImportData!( "org.eclipse.swt.internal.SWTMessages_zh.properties" ),
329 getImportData!( "org.eclipse.swt.internal.SWTMessages_zh_TW.properties" )
330 ];
331 332 privatestaticResourceBundlemsgs = null;
333 334 /**
335 * Returns the NLS'ed message for the given argument. This is only being
336 * called from SWT.
337 *
338 * @param key the key to look up
339 * @return the message for the given key
340 *
341 * @see SWT#getMessage(String)
342 */343 publicstaticStringgetMessage(Stringkey) {
344 Stringanswer = key;
345 346 if (keyisnull) {
347 SWT.error (SWT.ERROR_NULL_ARGUMENT);
348 }
349 if (msgsisnull) {
350 try {
351 msgs = ResourceBundle.getBundle(SWTMessagesBundleData); //$NON-NLS-1$352 } catch (MissingResourceExceptionex) {
353 answer = key ~ " (no resource bundle)"; //$NON-NLS-1$354 }
355 }
356 if (msgs !isnull) {
357 try {
358 answer = msgs.getString(key);
359 } catch (MissingResourceExceptionex2) {}
360 }
361 returnanswer;
362 }
363 364 publicstaticStringgetMessage(Stringkey, Object[] args) {
365 Stringanswer = key;
366 367 if (keyisnull || argsisnull) {
368 SWT.error (SWT.ERROR_NULL_ARGUMENT);
369 }
370 if (msgsisnull) {
371 try {
372 msgs = ResourceBundle.getBundle(SWTMessagesBundleData); //$NON-NLS-1$373 } catch (MissingResourceExceptionex) {
374 answer = key ~ " (no resource bundle)"; //$NON-NLS-1$375 }
376 }
377 if (msgs !isnull) {
378 try {
379 Stringfrmt = msgs.getString(key);
380 switch( args.length ){
381 case0: answer = Format(frmt); break;
382 case1: answer = Format(frmt, args[0]); break;
383 case2: answer = Format(frmt, args[0], args[1]); break;
384 case3: answer = Format(frmt, args[0], args[1], args[2]); break;
385 case4: answer = Format(frmt, args[0], args[1], args[2], args[3]); break;
386 case5: answer = Format(frmt, args[0], args[1], args[2], args[3], args[4]); break;
387 default:
388 implMissing(__FILE__, __LINE__ );
389 }
390 } catch (MissingResourceExceptionex2) {}
391 }
392 returnanswer;
393 }
394 395 396 /**
397 * Interrupt the current thread.
398 * <p>
399 * Note that this is not available on CLDC.
400 * </p>
401 */402 publicstaticvoidinterrupt() {
403 //PORTING_FIXME: how to implement??404 //Thread.currentThread().interrupt();405 }
406 407 /**
408 * Compares two instances of class String ignoring the case of the
409 * characters and answers if they are equal.
410 *
411 * @param s1 string
412 * @param s2 string
413 * @return true if the two instances of class String are equal
414 */415 publicstaticboolequalsIgnoreCase(inchar[] s1, inchar[] s2) {
416 return .equalsIgnoreCase(s1, s2);
417 }
418 419 }