jdk/src/share/classes/com/sun/media/sound/JSSecurityManager.java
changeset 2 90ce3da70b43
child 3453 55b3a9c935cd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/media/sound/JSSecurityManager.java	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,310 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.media.sound;
+
+import java.io.BufferedInputStream;
+import java.io.InputStream;
+import java.io.File;
+import java.io.FileInputStream;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import javax.sound.sampled.AudioPermission;
+
+import sun.misc.Service;
+
+
+/** Managing security in the Java Sound implementation.
+ * This class contains all code that uses and is used by
+ * SecurityManager.doPrivileged().
+ *
+ * @author Matthias Pfisterer
+ */
+class JSSecurityManager {
+
+    /** Prevent instantiation.
+     */
+    private JSSecurityManager() {
+    }
+
+    /** Checks if the VM currently has a SecurityManager installed.
+     * Note that this may change over time. So the result of this method
+     * should not be cached.
+     *
+     * @return true if a SecurityManger is installed, false otherwise.
+     */
+    private static boolean hasSecurityManager() {
+        return (System.getSecurityManager() != null);
+    }
+
+
+    static void checkRecordPermission() throws SecurityException {
+        if(Printer.trace) Printer.trace("JSSecurityManager.checkRecordPermission()");
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new AudioPermission("record"));
+        }
+    }
+
+
+    static void loadLibrary(final String libName) {
+        try {
+            if (hasSecurityManager()) {
+                if(Printer.debug) Printer.debug("using security manager to load library");
+                PrivilegedAction action = new PrivilegedAction() {
+                        public Object run() {
+                            System.loadLibrary(libName);
+                            return null;
+                        }
+                    };
+                AccessController.doPrivileged(action);
+            } else {
+                if(Printer.debug) Printer.debug("not using security manager to load library");
+                System.loadLibrary(libName);
+            }
+            if (Printer.debug) Printer.debug("loaded library " + libName);
+        } catch (UnsatisfiedLinkError e2) {
+            if (Printer.err)Printer.err("UnsatisfiedLinkError loading native library " + libName);
+            throw(e2);
+        }
+    }
+
+
+    static String getProperty(final String propertyName) {
+        String propertyValue;
+        if (hasSecurityManager()) {
+            if(Printer.debug) Printer.debug("using JDK 1.2 security to get property");
+            try{
+                PrivilegedAction action = new PrivilegedAction() {
+                        public Object run() {
+                            try {
+                                return System.getProperty(propertyName);
+                            } catch (Throwable t) {
+                                return null;
+                            }
+                        }
+                    };
+                propertyValue = (String) AccessController.doPrivileged(action);
+            } catch( Exception e ) {
+                if(Printer.debug) Printer.debug("not using JDK 1.2 security to get properties");
+                propertyValue = System.getProperty(propertyName);
+            }
+        } else {
+            if(Printer.debug) Printer.debug("not using JDK 1.2 security to get properties");
+            propertyValue = System.getProperty(propertyName);
+        }
+        return propertyValue;
+    }
+
+
+    /** Load properties from a file.
+        This method tries to load properties from the filename give into
+        the passed properties object.
+        If the file cannot be found or something else goes wrong,
+        the method silently fails.
+        @param properties The properties bundle to store the values of the
+        properties file.
+        @param filename The filename of the properties file to load. This
+        filename is interpreted as relative to the subdirectory "lib" in
+        the JRE directory.
+     */
+    static void loadProperties(final Properties properties,
+                               final String filename) {
+        if(hasSecurityManager()) {
+            try {
+                // invoke the privileged action using 1.2 security
+                PrivilegedAction action = new PrivilegedAction() {
+                        public Object run() {
+                            loadPropertiesImpl(properties, filename);
+                            return null;
+                        }
+                    };
+                AccessController.doPrivileged(action);
+                if(Printer.debug)Printer.debug("Loaded properties with JDK 1.2 security");
+            } catch (Exception e) {
+                if(Printer.debug)Printer.debug("Exception loading properties with JDK 1.2 security");
+                // try without using JDK 1.2 security
+                loadPropertiesImpl(properties, filename);
+            }
+        } else {
+            // not JDK 1.2 security, assume we already have permission
+            loadPropertiesImpl(properties, filename);
+        }
+    }
+
+
+    private static void loadPropertiesImpl(Properties properties,
+                                           String filename) {
+        if(Printer.trace)Printer.trace(">> JSSecurityManager: loadPropertiesImpl()");
+        String fname = System.getProperty("java.home");
+        try {
+            if (fname == null) {
+                throw new Error("Can't find java.home ??");
+            }
+            File f = new File(fname, "lib");
+            f = new File(f, filename);
+            fname = f.getCanonicalPath();
+            InputStream in = new FileInputStream(fname);
+            BufferedInputStream bin = new BufferedInputStream(in);
+            try {
+                properties.load(bin);
+            } finally {
+                if (in != null) {
+                    in.close();
+                }
+            }
+        } catch (Throwable t) {
+            if (Printer.trace) {
+                System.err.println("Could not load properties file \"" + fname + "\"");
+                t.printStackTrace();
+            }
+        }
+        if(Printer.trace)Printer.trace("<< JSSecurityManager: loadPropertiesImpl() completed");
+    }
+
+
+    private static ThreadGroup getTopmostThreadGroup() {
+        ThreadGroup topmostThreadGroup;
+        if(hasSecurityManager()) {
+            try {
+                // invoke the privileged action using 1.2 security
+                PrivilegedAction action = new PrivilegedAction() {
+                        public Object run() {
+                            try {
+                                return getTopmostThreadGroupImpl();
+                            } catch (Throwable t) {
+                                return null;
+                            }
+                        }
+                    };
+                topmostThreadGroup = (ThreadGroup) AccessController.doPrivileged(action);
+                if(Printer.debug)Printer.debug("Got topmost thread group with JDK 1.2 security");
+            } catch (Exception e) {
+                if(Printer.debug)Printer.debug("Exception getting topmost thread group with JDK 1.2 security");
+                // try without using JDK 1.2 security
+                topmostThreadGroup = getTopmostThreadGroupImpl();
+            }
+        } else {
+            // not JDK 1.2 security, assume we already have permission
+            topmostThreadGroup = getTopmostThreadGroupImpl();
+        }
+        return topmostThreadGroup;
+    }
+
+
+    private static ThreadGroup getTopmostThreadGroupImpl() {
+        if(Printer.trace)Printer.trace(">> JSSecurityManager: getTopmostThreadGroupImpl()");
+        ThreadGroup g = Thread.currentThread().getThreadGroup();
+        while ((g.getParent() != null) && (g.getParent().getParent() != null)) {
+            g = g.getParent();
+        }
+        if(Printer.trace)Printer.trace("<< JSSecurityManager: getTopmostThreadGroupImpl() completed");
+        return g;
+    }
+
+
+    /** Create a Thread in the topmost ThreadGroup.
+     */
+    static Thread createThread(final Runnable runnable,
+                               final String threadName,
+                               final boolean isDaemon, final int priority,
+                               final boolean doStart) {
+        Thread thread = null;
+        if(hasSecurityManager()) {
+            PrivilegedAction action = new PrivilegedAction() {
+                    public Object run() {
+                        try {
+                            return createThreadImpl(runnable, threadName,
+                                                    isDaemon, priority,
+                                                    doStart);
+                        } catch (Throwable t) {
+                            return null;
+                        }
+                    }
+                };
+            thread = (Thread) AccessController.doPrivileged(action);
+            if(Printer.debug) Printer.debug("created thread with JDK 1.2 security");
+        } else {
+            if(Printer.debug)Printer.debug("not using JDK 1.2 security");
+            thread = createThreadImpl(runnable, threadName, isDaemon, priority,
+                                      doStart);
+        }
+        return thread;
+    }
+
+
+    private static Thread createThreadImpl(Runnable runnable,
+                                           String threadName,
+                                           boolean isDaemon, int priority,
+                                           boolean doStart) {
+        ThreadGroup threadGroup = getTopmostThreadGroupImpl();
+        Thread thread = new Thread(threadGroup, runnable);
+        if (threadName != null) {
+            thread.setName(threadName);
+        }
+        thread.setDaemon(isDaemon);
+        if (priority >= 0) {
+            thread.setPriority(priority);
+        }
+        if (doStart) {
+            thread.start();
+        }
+        return thread;
+    }
+
+
+    static List getProviders(final Class providerClass) {
+        PrivilegedAction action = new PrivilegedAction() {
+                public Object run() {
+                    List p = new ArrayList();
+                    Iterator ps = Service.providers(providerClass);
+                    while (ps.hasNext()) {
+                        try {
+                            Object provider = ps.next();
+                            if (providerClass.isInstance(provider)) {
+                                // $$mp 2003-08-22
+                                // Always adding at the beginning reverses the
+                                // order of the providers. So we no longer have
+                                // to do this in AudioSystem and MidiSystem.
+                                p.add(0, provider);
+                            }
+                        } catch (Throwable t) {
+                            //$$fb 2002-11-07: do not fail on SPI not found
+                            if (Printer.err) t.printStackTrace();
+                        }                                                                  }
+                    return p;
+                }
+            };
+        List providers = (List) AccessController.doPrivileged(action);
+        return providers;
+    }
+}