1 /* 2 * Copyright (c) 1999, 2014, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.media.sound; 27 28 import java.security.AccessController; 29 import java.security.PrivilegedAction; 30 import java.util.ArrayList; 31 import java.util.Collections; 32 import java.util.List; 33 import java.util.Properties; 34 35 import javax.sound.midi.Receiver; 36 import javax.sound.midi.Sequencer; 37 import javax.sound.midi.Synthesizer; 38 import javax.sound.midi.Transmitter; 39 import javax.sound.midi.spi.MidiDeviceProvider; 40 import javax.sound.midi.spi.MidiFileReader; 41 import javax.sound.midi.spi.MidiFileWriter; 42 import javax.sound.midi.spi.SoundbankReader; 43 import javax.sound.sampled.Clip; 44 import javax.sound.sampled.Port; 45 import javax.sound.sampled.SourceDataLine; 46 import javax.sound.sampled.TargetDataLine; 47 import javax.sound.sampled.spi.AudioFileReader; 48 import javax.sound.sampled.spi.AudioFileWriter; 49 import javax.sound.sampled.spi.FormatConversionProvider; 50 import javax.sound.sampled.spi.MixerProvider; 51 52 53 /** 54 * JDK13Services uses the Service class in JDK 1.3 to discover a list of service 55 * providers installed in the system. 56 * <p> 57 * This class is public because it is called from javax.sound.midi.MidiSystem 58 * and javax.sound.sampled.AudioSystem. The alternative would be to make 59 * JSSecurityManager public, which is considered worse. 60 * 61 * @author Matthias Pfisterer 62 */ 63 public final class JDK13Services { 64 65 /** 66 * Filename of the properties file for default provider properties. This 67 * file is searched in the subdirectory "conf" of the JRE directory (this 68 * behaviour is hardcoded). 69 */ 70 private static final String PROPERTIES_FILENAME = "sound.properties"; 71 72 /** 73 * Properties loaded from the properties file for default provider 74 * properties. 75 */ 76 private static Properties properties; 77 78 /** 79 * Private, no-args constructor to ensure against instantiation. 80 */ 81 private JDK13Services() { 82 } 83 84 /** 85 * Obtains a List containing installed instances of the providers for the 86 * requested service. The returned List is immutable. 87 * 88 * @param serviceClass The type of providers requested. This should be one 89 * of AudioFileReader.class, AudioFileWriter.class, 90 * FormatConversionProvider.class, MixerProvider.class, 91 * MidiDeviceProvider.class, MidiFileReader.class, 92 * MidiFileWriter.class or SoundbankReader.class. 93 * 94 * @return A List of providers of the requested type. This List is 95 * immutable. 96 */ 97 public static List<?> getProviders(final Class<?> serviceClass) { 98 final List<?> providers; 99 if (!MixerProvider.class.equals(serviceClass) 100 && !FormatConversionProvider.class.equals(serviceClass) 101 && !AudioFileReader.class.equals(serviceClass) 102 && !AudioFileWriter.class.equals(serviceClass) 103 && !MidiDeviceProvider.class.equals(serviceClass) 104 && !SoundbankReader.class.equals(serviceClass) 105 && !MidiFileWriter.class.equals(serviceClass) 106 && !MidiFileReader.class.equals(serviceClass)) { 107 providers = new ArrayList<>(0); 108 } else { 109 providers = JSSecurityManager.getProviders(serviceClass); 110 } 111 return Collections.unmodifiableList(providers); 112 } 113 114 /** Obtain the provider class name part of a default provider property. 115 @param typeClass The type of the default provider property. This 116 should be one of Receiver.class, Transmitter.class, Sequencer.class, 117 Synthesizer.class, SourceDataLine.class, TargetDataLine.class, 118 Clip.class or Port.class. 119 @return The value of the provider class name part of the property 120 (the part before the hash sign), if available. If the property is 121 not set or the value has no provider class name part, null is returned. 122 */ 123 public static synchronized String getDefaultProviderClassName(Class<?> typeClass) { 124 String value = null; 125 String defaultProviderSpec = getDefaultProvider(typeClass); 126 if (defaultProviderSpec != null) { 127 int hashpos = defaultProviderSpec.indexOf('#'); 128 if (hashpos == 0) { 129 // instance name only; leave value as null 130 } else if (hashpos > 0) { 131 value = defaultProviderSpec.substring(0, hashpos); 132 } else { 133 value = defaultProviderSpec; 134 } 135 } 136 return value; 137 } 138 139 /** Obtain the instance name part of a default provider property. 140 @param typeClass The type of the default provider property. This 141 should be one of Receiver.class, Transmitter.class, Sequencer.class, 142 Synthesizer.class, SourceDataLine.class, TargetDataLine.class, 143 Clip.class or Port.class. 144 @return The value of the instance name part of the property (the 145 part after the hash sign), if available. If the property is not set 146 or the value has no instance name part, null is returned. 147 */ 148 public static synchronized String getDefaultInstanceName(Class<?> typeClass) { 149 String value = null; 150 String defaultProviderSpec = getDefaultProvider(typeClass); 151 if (defaultProviderSpec != null) { 152 int hashpos = defaultProviderSpec.indexOf('#'); 153 if (hashpos >= 0 && hashpos < defaultProviderSpec.length() - 1) { 154 value = defaultProviderSpec.substring(hashpos + 1); 155 } 156 } 157 return value; 158 } 159 160 /** Obtain the value of a default provider property. 161 @param typeClass The type of the default provider property. This 162 should be one of Receiver.class, Transmitter.class, Sequencer.class, 163 Synthesizer.class, SourceDataLine.class, TargetDataLine.class, 164 Clip.class or Port.class. 165 @return The complete value of the property, if available. 166 If the property is not set, null is returned. 167 */ 168 private static synchronized String getDefaultProvider(Class<?> typeClass) { 169 if (!SourceDataLine.class.equals(typeClass) 170 && !TargetDataLine.class.equals(typeClass) 171 && !Clip.class.equals(typeClass) 172 && !Port.class.equals(typeClass) 173 && !Receiver.class.equals(typeClass) 174 && !Transmitter.class.equals(typeClass) 175 && !Synthesizer.class.equals(typeClass) 176 && !Sequencer.class.equals(typeClass)) { 177 return null; 178 } 179 String name = typeClass.getName(); 180 String value = AccessController.doPrivileged( 181 (PrivilegedAction<String>) () -> System.getProperty(name)); 182 if (value == null) { 183 value = getProperties().getProperty(name); 184 } 185 if ("".equals(value)) { 186 value = null; 187 } 188 return value; 189 } 190 191 /** Obtain a properties bundle containing property values from the 192 properties file. If the properties file could not be loaded, 193 the properties bundle is empty. 194 */ 195 private static synchronized Properties getProperties() { 196 if (properties == null) { 197 properties = new Properties(); 198 JSSecurityManager.loadProperties(properties, PROPERTIES_FILENAME); 199 } 200 return properties; 201 } 202 }