blob: 253d22c1e933f07bff75506e25b692ca34af7960 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.media.sound;
27
28import java.io.BufferedInputStream;
29import java.io.InputStream;
30import java.io.File;
31import java.io.FileInputStream;
32
33import java.util.ArrayList;
34import java.util.Iterator;
35import java.util.List;
36import java.util.Properties;
37
38import java.security.AccessController;
39import java.security.PrivilegedAction;
40
41import javax.sound.sampled.AudioPermission;
42
43import sun.misc.Service;
44
45
46/** Managing security in the Java Sound implementation.
47 * This class contains all code that uses and is used by
48 * SecurityManager.doPrivileged().
49 *
50 * @author Matthias Pfisterer
51 */
52class JSSecurityManager {
53
54 /** Prevent instantiation.
55 */
56 private JSSecurityManager() {
57 }
58
59 /** Checks if the VM currently has a SecurityManager installed.
60 * Note that this may change over time. So the result of this method
61 * should not be cached.
62 *
63 * @return true if a SecurityManger is installed, false otherwise.
64 */
65 private static boolean hasSecurityManager() {
66 return (System.getSecurityManager() != null);
67 }
68
69
70 static void checkRecordPermission() throws SecurityException {
71 if(Printer.trace) Printer.trace("JSSecurityManager.checkRecordPermission()");
72 SecurityManager sm = System.getSecurityManager();
73 if (sm != null) {
74 sm.checkPermission(new AudioPermission("record"));
75 }
76 }
77
78
79 static void loadLibrary(final String libName) {
80 try {
81 if (hasSecurityManager()) {
82 if(Printer.debug) Printer.debug("using security manager to load library");
83 PrivilegedAction action = new PrivilegedAction() {
84 public Object run() {
85 System.loadLibrary(libName);
86 return null;
87 }
88 };
89 AccessController.doPrivileged(action);
90 } else {
91 if(Printer.debug) Printer.debug("not using security manager to load library");
92 System.loadLibrary(libName);
93 }
94 if (Printer.debug) Printer.debug("loaded library " + libName);
95 } catch (UnsatisfiedLinkError e2) {
96 if (Printer.err)Printer.err("UnsatisfiedLinkError loading native library " + libName);
97 throw(e2);
98 }
99 }
100
101
102 static String getProperty(final String propertyName) {
103 String propertyValue;
104 if (hasSecurityManager()) {
105 if(Printer.debug) Printer.debug("using JDK 1.2 security to get property");
106 try{
107 PrivilegedAction action = new PrivilegedAction() {
108 public Object run() {
109 try {
110 return System.getProperty(propertyName);
111 } catch (Throwable t) {
112 return null;
113 }
114 }
115 };
116 propertyValue = (String) AccessController.doPrivileged(action);
117 } catch( Exception e ) {
118 if(Printer.debug) Printer.debug("not using JDK 1.2 security to get properties");
119 propertyValue = System.getProperty(propertyName);
120 }
121 } else {
122 if(Printer.debug) Printer.debug("not using JDK 1.2 security to get properties");
123 propertyValue = System.getProperty(propertyName);
124 }
125 return propertyValue;
126 }
127
128
129 /** Load properties from a file.
130 This method tries to load properties from the filename give into
131 the passed properties object.
132 If the file cannot be found or something else goes wrong,
133 the method silently fails.
134 @param properties The properties bundle to store the values of the
135 properties file.
136 @param filename The filename of the properties file to load. This
137 filename is interpreted as relative to the subdirectory "lib" in
138 the JRE directory.
139 */
140 static void loadProperties(final Properties properties,
141 final String filename) {
142 if(hasSecurityManager()) {
143 try {
144 // invoke the privileged action using 1.2 security
145 PrivilegedAction action = new PrivilegedAction() {
146 public Object run() {
147 loadPropertiesImpl(properties, filename);
148 return null;
149 }
150 };
151 AccessController.doPrivileged(action);
152 if(Printer.debug)Printer.debug("Loaded properties with JDK 1.2 security");
153 } catch (Exception e) {
154 if(Printer.debug)Printer.debug("Exception loading properties with JDK 1.2 security");
155 // try without using JDK 1.2 security
156 loadPropertiesImpl(properties, filename);
157 }
158 } else {
159 // not JDK 1.2 security, assume we already have permission
160 loadPropertiesImpl(properties, filename);
161 }
162 }
163
164
165 private static void loadPropertiesImpl(Properties properties,
166 String filename) {
167 if(Printer.trace)Printer.trace(">> JSSecurityManager: loadPropertiesImpl()");
168 String fname = System.getProperty("java.home");
169 try {
170 if (fname == null) {
171 throw new Error("Can't find java.home ??");
172 }
173 File f = new File(fname, "lib");
174 f = new File(f, filename);
175 fname = f.getCanonicalPath();
176 InputStream in = new FileInputStream(fname);
177 BufferedInputStream bin = new BufferedInputStream(in);
178 try {
179 properties.load(bin);
180 } finally {
181 if (in != null) {
182 in.close();
183 }
184 }
185 } catch (Throwable t) {
186 if (Printer.trace) {
187 System.err.println("Could not load properties file \"" + fname + "\"");
188 t.printStackTrace();
189 }
190 }
191 if(Printer.trace)Printer.trace("<< JSSecurityManager: loadPropertiesImpl() completed");
192 }
193
194
195 private static ThreadGroup getTopmostThreadGroup() {
196 ThreadGroup topmostThreadGroup;
197 if(hasSecurityManager()) {
198 try {
199 // invoke the privileged action using 1.2 security
200 PrivilegedAction action = new PrivilegedAction() {
201 public Object run() {
202 try {
203 return getTopmostThreadGroupImpl();
204 } catch (Throwable t) {
205 return null;
206 }
207 }
208 };
209 topmostThreadGroup = (ThreadGroup) AccessController.doPrivileged(action);
210 if(Printer.debug)Printer.debug("Got topmost thread group with JDK 1.2 security");
211 } catch (Exception e) {
212 if(Printer.debug)Printer.debug("Exception getting topmost thread group with JDK 1.2 security");
213 // try without using JDK 1.2 security
214 topmostThreadGroup = getTopmostThreadGroupImpl();
215 }
216 } else {
217 // not JDK 1.2 security, assume we already have permission
218 topmostThreadGroup = getTopmostThreadGroupImpl();
219 }
220 return topmostThreadGroup;
221 }
222
223
224 private static ThreadGroup getTopmostThreadGroupImpl() {
225 if(Printer.trace)Printer.trace(">> JSSecurityManager: getTopmostThreadGroupImpl()");
226 ThreadGroup g = Thread.currentThread().getThreadGroup();
227 while ((g.getParent() != null) && (g.getParent().getParent() != null)) {
228 g = g.getParent();
229 }
230 if(Printer.trace)Printer.trace("<< JSSecurityManager: getTopmostThreadGroupImpl() completed");
231 return g;
232 }
233
234
235 /** Create a Thread in the topmost ThreadGroup.
236 */
237 static Thread createThread(final Runnable runnable,
238 final String threadName,
239 final boolean isDaemon, final int priority,
240 final boolean doStart) {
241 Thread thread = null;
242 if(hasSecurityManager()) {
243 PrivilegedAction action = new PrivilegedAction() {
244 public Object run() {
245 try {
246 return createThreadImpl(runnable, threadName,
247 isDaemon, priority,
248 doStart);
249 } catch (Throwable t) {
250 return null;
251 }
252 }
253 };
254 thread = (Thread) AccessController.doPrivileged(action);
255 if(Printer.debug) Printer.debug("created thread with JDK 1.2 security");
256 } else {
257 if(Printer.debug)Printer.debug("not using JDK 1.2 security");
258 thread = createThreadImpl(runnable, threadName, isDaemon, priority,
259 doStart);
260 }
261 return thread;
262 }
263
264
265 private static Thread createThreadImpl(Runnable runnable,
266 String threadName,
267 boolean isDaemon, int priority,
268 boolean doStart) {
269 ThreadGroup threadGroup = getTopmostThreadGroupImpl();
270 Thread thread = new Thread(threadGroup, runnable);
271 if (threadName != null) {
272 thread.setName(threadName);
273 }
274 thread.setDaemon(isDaemon);
275 if (priority >= 0) {
276 thread.setPriority(priority);
277 }
278 if (doStart) {
279 thread.start();
280 }
281 return thread;
282 }
283
284
285 static List getProviders(final Class providerClass) {
286 PrivilegedAction action = new PrivilegedAction() {
287 public Object run() {
288 List p = new ArrayList();
289 Iterator ps = Service.providers(providerClass);
290 while (ps.hasNext()) {
291 try {
292 Object provider = ps.next();
293 if (providerClass.isInstance(provider)) {
294 // $$mp 2003-08-22
295 // Always adding at the beginning reverses the
296 // order of the providers. So we no longer have
297 // to do this in AudioSystem and MidiSystem.
298 p.add(0, provider);
299 }
300 } catch (Throwable t) {
301 //$$fb 2002-11-07: do not fail on SPI not found
302 if (Printer.err) t.printStackTrace();
303 } }
304 return p;
305 }
306 };
307 List providers = (List) AccessController.doPrivileged(action);
308 return providers;
309 }
310}