001    /*
002    * @(#)Platform.java   1.0 06/08/25
003    */ // ************************************************************************ 
004    // * Copyright (c) 2006 by the Association for Computing Machinery        *
005    // *                                                                      *
006    // * The Java Task Force seeks to impose few restrictions on the use of   *
007    // * these packages so that users have as much freedom as possible to     *
008    // * use this software in constructive ways and can make the benefits of  *
009    // * that work available to others.  In view of the legal complexities    *
010    // * of software development, however, it is essential for the ACM to     *
011    // * maintain its copyright to guard against attempts by others to        *
012    // * claim ownership rights.  The full text of the JTF Software License   *
013    // * is available at the following URL:                                   *
014    // *                                                                      *
015    // *          http://www.acm.org/jtf/jtf-software-license.pdf             *
016    // *                                                                      *
017    // ************************************************************************
018    /**
019     * Class extracted from ACM JTF acm.util package (http://jtf.acm.org/). 
020     * Modified slightly to support FANG
021     */
022    package fang;
023    
024    import java.awt.*;
025    import java.io.*;
026    import java.lang.reflect.*;
027    import java.util.*;
028    
029    /* Class: Platform */
030    /**
031     * This class contains methods to support platform-specific code.
032     */
033    public class Platform
034    {
035    
036        /* Constant: UNKNOWN */
037        /** Indicates that the type of system cannot be determined. */
038        public static final int UNKNOWN = 0;
039    
040        /* Constant: MAC */
041        /** Indicates that the system is some variety of Apple Macintosh. */
042        public static final int MAC = 1;
043    
044        /* Constant: UNIX */
045        /** Indicates that the system is some variety of Unix or Linux. */
046        public static final int UNIX = 2;
047    
048        /* Constant: WINDOWS */
049        /** Indicates that the system is some variety of Microsoft Windows. */
050        public static final int WINDOWS = 3;
051    
052        /* Static method: getPlatform() */
053        /**
054         * Returns an enumeration constant specifying the type of platform
055         * on which this applet is running, which is one of the supported
056         * types defined at the beginning of this class.
057         *
058         * @usage int platform = Platform.getPlatform();
059         * @return A constant specifying the platform type
060         */
061        public static int getPlatform()
062        {
063            if (platform != -1)
064            {
065                return platform;
066            }
067            String name = System.getProperty("os.name", "").toLowerCase();
068            if (name.startsWith("mac"))
069            {
070                return platform = MAC;
071            }
072            if (name.startsWith("windows"))
073            {
074                return platform = WINDOWS;
075            }
076            if (name.startsWith("microsoft"))
077            {
078                return platform = WINDOWS;
079            }
080            if (name.startsWith("ms"))
081            {
082                return platform = WINDOWS;
083            }
084            if (name.startsWith("unix"))
085            {
086                return platform = UNIX;
087            }
088            if (name.startsWith("linux"))
089            {
090                return platform = UNIX;
091            }
092            return platform = UNKNOWN;
093        }
094    
095        /* Static method: isMac */
096        /**
097         * Checks whether the platform is a Macintosh.
098         *
099         * @usage if (Platform.isMac()) . . .
100         * @return <code>true</code> if the platform is a Macintosh, <code>false</code> otherwise
101         */
102        public static boolean isMac()
103        {
104            return getPlatform() == MAC;
105        }
106    
107        /* Static method: isWindows() */
108        /**
109         * Checks whether the platform is a Windows machine.
110         *
111         * @usage if (Platform.isWindows()) . . .
112         * @return <code>true</code> if the platform is a Windows machine, <code>false</code> otherwise
113         */
114        public static boolean isWindows()
115        {
116            return getPlatform() == WINDOWS;
117        }
118    
119        /* Static method: isUnix() */
120        /**
121         * Checks whether the platform is Unix.
122         *
123         * @usage if (Platform.isUnix()) . . .
124         * @return <code>true</code> if the platform is Unix, <code>false</code> otherwise
125         */
126        public static boolean isUnix()
127        {
128            return getPlatform() == UNIX;
129        }
130    
131        /* Static method: setFileTypeAndCreator(filename, type, creator) */
132        /**
133         * Sets the Macintosh file type and creator.  This method is ignored on non-Mac
134         * platforms.
135         *
136         * @usage setFileTypeAndCreator(filename, type, creator);
137         * @param filename The name of the file
138         * @param type A four-character string indicating the file type
139         * @param creator A four-character string indicating the file type
140         */
141        public static void setFileTypeAndCreator(String filename, String type, String creator)
142        {
143            if (!isMac())
144            {
145                return ;
146            }
147            try
148            {
149                setFileTypeAndCreator(new File(filename), type, creator);
150            }
151            catch (Exception ex)
152            {
153                /* Empty */
154            }
155        }
156    
157        /* Static method: setFileTypeAndCreator(file, type, creator) */
158        /**
159         * Sets the Macintosh file type and creator.  This method is ignored on non-Mac
160         * platforms.
161         *
162         * @usage setFileTypeAndCreator(file, type, creator);
163         * @param file The <code>File</code> object corresponding to the file
164         * @param type A four-character string indicating the file type
165         * @param creator A four-character string indicating the file type
166         */
167        @SuppressWarnings("unchecked")
168        public static void setFileTypeAndCreator(File file, String type, String creator)
169        {
170            if (!isMac())
171            {
172                return ;
173            }
174            try
175            {
176                Class mrjOSTypeClass = Class.forName("com.apple.mrj.MRJOSType");
177                Class mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils");
178                Class[] sig1 = {Class.forName("java.lang.String")};
179                Constructor constructor = mrjOSTypeClass.getConstructor(sig1);
180                Class[] sig2 = {Class.forName("java.io.File"), mrjOSTypeClass, mrjOSTypeClass};
181                Method fn = mrjFileUtilsClass.getMethod("setFileTypeAndCreator", sig2);
182                Object[] args1 = {(type + "    ").substring(0, 4)};
183                Object osType = constructor.newInstance(args1);
184                Object[] args2 = {(creator + "    ").substring(0, 4)};
185                Object creatorType = constructor.newInstance(args2);
186                Object[] args3 = {file, osType, creatorType};
187                fn.invoke(null, args3);
188            }
189            catch (Exception ex)
190            {
191                /* Empty */
192            }
193            finally
194            {}
195        }
196    
197        /* Static method: compareVersion(version) */
198        /**
199         * This method compares the Java version given in the system properties
200         * with the specified version and returns -1, 0, or +1 depending on whether
201         * the system version is earlier than, equal to, or later than the specified
202         * one.  Thus, to test whether the current version of the JDK was at least
203         * 1.2.1, for example, you could write
204         *
205         * <p><table cellspacing=0 cellpadding=0><tr><td width=36>&nbsp;</td>
206         * <td><table cellspacing=0 cellpadding=0><tr><td><pre><font face=courier size=-1><b>
207         *     if (Platform.compareVersion("1.2.1") &gt;= 0) . . .
208         * </b></font></pre></td></tr></table></td></tr></table>
209         *
210         * @usage int cmp = Platform.compareVersion(version);
211         * @param version A string consisting of integers separated by periods
212         * @return -1, 0, or +1 depending on whether the system version is earlier than,
213         *         equal to, or later than the specified one
214         */
215        public static int compareVersion(String version)
216        {
217            return compareVersion(System.getProperty("java.version"), version);
218        }
219    
220        /* Static method: compareVersion(v1, v2) */
221        /**
222         * This method compares the version strings <code>v1</code> and <code>v2</code>
223         * and returns -1, 0, or +1 depending on whether <code>v1</code> is earlier
224         * than, equal to, or later than <code>v2</code>.
225         *
226         * @usage int cmp = Platform.compareVersion(v1, v2);
227         * @param v1 A string consisting of integers separated by periods
228         * @param v2 A second version string in the same format
229         * @return -1, 0, or +1 depending on whether <code>v1</code> is earlier than,
230         *         equal to, or later than <code>v2</code>
231         */
232        public static int compareVersion(String v1, String v2)
233        {
234            StringTokenizer t1 = new StringTokenizer(v1, ".");
235            StringTokenizer t2 = new StringTokenizer(v2, ".");
236            while (t1.hasMoreTokens() && t2.hasMoreTokens())
237            {
238                int n1 = Integer.parseInt(t1.nextToken());
239                int n2 = Integer.parseInt(t2.nextToken());
240                if (n1 != n2)
241                {
242                    return (n1 < n2) ? -1 : + 1;
243                }
244            }
245            if (t1.hasMoreTokens())
246            {
247                return + 1;
248            }
249            if (t2.hasMoreTokens())
250            {
251                return -1;
252            }
253            return 0;
254        }
255    
256        /* Static method: isSwingAvailable() */
257        /**
258         * Checks whether Swing is available.  Unfortunately, some browsers seem to lie
259         * about the JDK version and return a 1.2 number without actually having Swing.
260         * This implementation tests the version first, but then confirms the result
261         * by looking for the <code>JComponent</code> class.  Checking the version first
262         * means that no <nobr><code>SecurityException</code>s</nobr> will be logged in
263         * Windows machines, which always log <nobr><code>SecurityException</code>s</nobr>,
264         * even if the exception is caught.
265         *
266         * @usage if (Platform.isSwingAvailable()) . . .
267         * @return <code>true</code> if Swing is available, <code>false</code> otherwise
268         */
269        public static boolean isSwingAvailable()
270        {
271            if (!swingChecked)
272            {
273                swingChecked = true;
274                isSwingAvailable = false;
275                if (compareVersion("1.2") >= 0)
276                {
277                    try
278                    {
279                        isSwingAvailable = Class.forName("javax.swing.JComponent") != null;
280                    }
281                    catch (Exception ex)
282                    {
283                        /* Empty */
284                    }
285                }
286            }
287            return isSwingAvailable;
288        }
289    
290        /* Static method: isSunAudioAvailable() */
291        /**
292         * Checks whether the <code>sun.audio</code> package is available.
293         *
294         * @usage if (Platform.isSunAudioAvailable()) . . .
295         * @return <code>true</code> if the <code>sun.audio</code> package is available,
296         *         <code>false</code> otherwise
297         */
298        public static boolean isSunAudioAvailable()
299        {
300            if (!sunAudioChecked)
301            {
302                sunAudioChecked = true;
303                try
304                {
305                    isSunAudioAvailable = Class.forName("sun.audio.AudioPlayer") != null;
306                }
307                catch (Exception ex)
308                {
309                    isSunAudioAvailable = false;
310                }
311            }
312            return isSunAudioAvailable;
313        }
314    
315        /* Static method: isJMFAvailable() */
316        /**
317         * Checks whether the Java Media Framework is available.
318         *
319         * @usage if (Platform.isJMFAvailable()) . . .
320         * @return <code>true</code> if the JMF package is available, <code>false</code> otherwise
321         */
322        public static boolean isJMFAvailable()
323        {
324            if (!jmfChecked)
325            {
326                jmfChecked = true;
327                try
328                {
329                    isJMFAvailable = Class.forName("javax.media.Player") != null;
330                }
331                catch (Exception ex)
332                {
333                    isJMFAvailable = false;
334                }
335            }
336            return isJMFAvailable;
337        }
338    
339        /* Static method: areCollectionsAvailable() */
340        /**
341         * Checks whether the JDK 1.2 collection classes are available.  Some browsers
342         * return a version of the JDK that does not actually match what is supported.
343         * This method actually checks whether the collection classes are there by
344         * looking for the <code>ArrayList</code> class.
345         *
346         * @usage if (Platform.areCollectionsAvailable()) . . .
347         * @return <code>true</code> if collections are available, <code>false</code> otherwise
348         */
349        public static boolean areCollectionsAvailable()
350        {
351            if (!collectionsChecked)
352            {
353                collectionsChecked = true;
354                try
355                {
356                    areCollectionsAvailable = Class.forName("java.util.ArrayList") != null;
357                }
358                catch (Exception ex)
359                {
360                    areCollectionsAvailable = false;
361                }
362            }
363            return areCollectionsAvailable;
364        }
365    
366        /* Static method: areStandardFontFamiliesAvailable() */
367        /**
368         * Checks whether the JDK 1.2 standard font families (<code>Serif</code>,
369         * <code>SansSerif</code>, and <code>Monospaced</code>) are available.
370         *
371         * @usage if (Platform.areStandardFontFamiliesAvailable()) . . .
372         * @return <code>true</code> if the standard fonts are available, <code>false</code> otherwise
373         */
374        public static boolean areStandardFontFamiliesAvailable()
375        {
376            if (!fontsChecked)
377            {
378                fontsChecked = true;
379                try
380                {
381                    Class < ? > toolkitClass = Class.forName("java.awt.Toolkit");
382                    Method getFontList = toolkitClass.getMethod("getFontList", new Class[0]);
383                    String[] fonts = (String[]) getFontList.invoke(Toolkit.getDefaultToolkit(), new Object[0]);
384                    int standardFontCount = 0;
385                    for (int i = 0; i < fonts.length; i++)
386                    {
387                        if (fonts[i].equals("Serif") || fonts[i].equals("SansSerif") || fonts[i].equals("Monospaced"))
388                        {
389                            standardFontCount++;
390                        }
391                    }
392                    areStandardFontFamiliesAvailable = (standardFontCount == 3);
393                }
394                catch (Exception ex)
395                {
396                    areStandardFontFamiliesAvailable = false;
397                }
398            }
399            return areStandardFontFamiliesAvailable;
400        }
401    
402        /* Private static variables */
403        private static int platform = -1;
404        private static boolean areStandardFontFamiliesAvailable;
405        private static boolean fontsChecked;
406        private static boolean isSwingAvailable;
407        private static boolean swingChecked;
408        private static boolean areCollectionsAvailable;
409        private static boolean collectionsChecked;
410        private static boolean isSunAudioAvailable;
411        private static boolean sunAudioChecked;
412        private static boolean isJMFAvailable;
413        private static boolean jmfChecked;
414    }