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 140 /** Obtain the instance name part of a default provider property. 141 @param typeClass The type of the default provider property. This 142 should be one of Receiver.class, Transmitter.class, Sequencer.class, 143 Synthesizer.class, SourceDataLine.class, TargetDataLine.class, 144 Clip.class or Port.class. 145 @return The value of the instance name part of the property (the 146 part after the hash sign), if available. If the property is not set 147 or the value has no instance name part, null is returned. 148 */ 149 public static synchronized String getDefaultInstanceName(Class<?> typeClass) { 150 String value = null; 151 String defaultProviderSpec = getDefaultProvider(typeClass); 152 if (defaultProviderSpec != null) { 153 int hashpos = defaultProviderSpec.indexOf('#'); 154 if (hashpos >= 0 && hashpos < defaultProviderSpec.length() - 1) { 155 value = defaultProviderSpec.substring(hashpos + 1); 156 } 157 } 158 return value; 159 } 160 161 162 /** Obtain the value of a default provider property. 163 @param typeClass The type of the default provider property. This 164 should be one of Receiver.class, Transmitter.class, Sequencer.class, 165 Synthesizer.class, SourceDataLine.class, TargetDataLine.class, 166 Clip.class or Port.class. 167 @return The complete value of the property, if available. 168 If the property is not set, null is returned. 169 */ 170 private static synchronized String getDefaultProvider(Class<?> typeClass) { 171 if (!SourceDataLine.class.equals(typeClass) 172 && !TargetDataLine.class.equals(typeClass) 173 && !Clip.class.equals(typeClass) 174 && !Port.class.equals(typeClass) 175 && !Receiver.class.equals(typeClass) 176 && !Transmitter.class.equals(typeClass) 177 && !Synthesizer.class.equals(typeClass) 178 && !Sequencer.class.equals(typeClass)) { 179 return null; 180 } 181 String name = typeClass.getName(); 182 String value = AccessController.doPrivileged( 183 (PrivilegedAction<String>) () -> System.getProperty(name)); 184 if (value == null) { 185 value = getProperties().getProperty(name); 186 } 187 if ("".equals(value)) { 188 value = null; 189 } 190 return value; 191 } 192 193 194 /** Obtain a properties bundle containing property values from the 195 properties file. If the properties file could not be loaded, 196 the properties bundle is empty. 197 */ 198 private static synchronized Properties getProperties() { 199 if (properties == null) { 200 properties = new Properties(); 201 JSSecurityManager.loadProperties(properties, PROPERTIES_FILENAME); 202 } 203 return properties; 204 } 205 }