blob: 2b588ceef8d70e79c710b68ac190c202084f51f1 [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.util.Collections;
29import java.util.HashMap;
30import java.util.List;
31import java.util.Map;
32import java.util.Properties;
33
34import javax.sound.sampled.spi.AudioFileReader;
35import javax.sound.sampled.spi.AudioFileWriter;
36import javax.sound.sampled.spi.FormatConversionProvider;
37import javax.sound.sampled.spi.MixerProvider;
38
39import javax.sound.midi.spi.MidiFileReader;
40import javax.sound.midi.spi.MidiFileWriter;
41import javax.sound.midi.spi.SoundbankReader;
42import javax.sound.midi.spi.MidiDeviceProvider;
43
44
45/**
46 * JDK13Services uses the Service class in JDK 1.3
47 * to discover a list of service providers installed
48 * in the system.
49 *
50 * This class is public because it is called from javax.sound.midi.MidiSystem
51 * and javax.sound.sampled.AudioSystem. The alternative would be to make
52 * JSSecurityManager public, which is considered worse.
53 *
54 * @author Matthias Pfisterer
55 */
56public class JDK13Services {
57
58 /** The default for the length of the period to hold the cache.
59 This value is given in milliseconds. It is equivalent to
60 1 minute.
61 */
62 private static final long DEFAULT_CACHING_PERIOD = 60000;
63
64 /** Filename of the properties file for default provider properties.
65 This file is searched in the subdirectory "lib" of the JRE directory
66 (this behaviour is hardcoded).
67 */
68 private static final String PROPERTIES_FILENAME = "sound.properties";
69
70 /** Cache for the providers.
71 Class objects of the provider type (MixerProvider, MidiDeviceProvider
72 ...) are used as keys. The values are instances of ProviderCache.
73 */
74 private static Map providersCacheMap = new HashMap();
75
76
77 /** The length of the period to hold the cache.
78 This value is given in milliseconds.
79 */
80 private static long cachingPeriod = DEFAULT_CACHING_PERIOD;
81
82 /** Properties loaded from the properties file for default provider
83 properties.
84 */
85 private static Properties properties;
86
87
88 /** Private, no-args constructor to ensure against instantiation.
89 */
90 private JDK13Services() {
91 }
92
93
94 /** Set the period provider lists are cached.
95 This method is only intended for testing.
96 */
97 public static void setCachingPeriod(int seconds) {
98 cachingPeriod = seconds * 1000L;
99 }
100
101
102 /** Obtains a List containing installed instances of the
103 providers for the requested service.
104 The List of providers is cached for the period of time given by
105 {@link #cachingPeriod cachingPeriod}. During this period, the same
106 List instance is returned for the same type of provider. After this
107 period, a new instance is constructed and returned. The returned
108 List is immutable.
109 @param serviceClass The type of providers requested. This should be one
110 of AudioFileReader.class, AudioFileWriter.class,
111 FormatConversionProvider.class, MixerProvider.class,
112 MidiDeviceProvider.class, MidiFileReader.class, MidiFileWriter.class or
113 SoundbankReader.class.
114 @return A List of providers of the requested type. This List is
115 immutable.
116 */
117 public static synchronized List getProviders(Class serviceClass) {
118 ProviderCache cache = (ProviderCache) providersCacheMap.get(serviceClass);
119 if (cache == null) {
120 cache = new ProviderCache();
121 providersCacheMap.put(serviceClass, cache);
122 }
123 if (cache.providers == null ||
124 System.currentTimeMillis() > cache.lastUpdate + cachingPeriod) {
125 cache.providers = Collections.unmodifiableList(JSSecurityManager.getProviders(serviceClass));
126 cache.lastUpdate = System.currentTimeMillis();
127 }
128 return cache.providers;
129 }
130
131
132 /** Obtain the provider class name part of a default provider property.
133 @param typeClass The type of the default provider property. This
134 should be one of Receiver.class, Transmitter.class, Sequencer.class,
135 Synthesizer.class, SourceDataLine.class, TargetDataLine.class,
136 Clip.class or Port.class.
137 @return The value of the provider class name part of the property
138 (the part before the hash sign), if available. If the property is
139 not set or the value has no provider class name part, null is returned.
140 */
141 public static synchronized String getDefaultProviderClassName(Class typeClass) {
142 String value = null;
143 String defaultProviderSpec = getDefaultProvider(typeClass);
144 if (defaultProviderSpec != null) {
145 int hashpos = defaultProviderSpec.indexOf('#');
146 if (hashpos == 0) {
147 // instance name only; leave value as null
148 } else if (hashpos > 0) {
149 value = defaultProviderSpec.substring(0, hashpos);
150 } else {
151 value = defaultProviderSpec;
152 }
153 }
154 return value;
155 }
156
157
158 /** Obtain the instance name part of a default provider property.
159 @param typeClass The type of the default provider property. This
160 should be one of Receiver.class, Transmitter.class, Sequencer.class,
161 Synthesizer.class, SourceDataLine.class, TargetDataLine.class,
162 Clip.class or Port.class.
163 @return The value of the instance name part of the property (the
164 part after the hash sign), if available. If the property is not set
165 or the value has no instance name part, null is returned.
166 */
167 public static synchronized String getDefaultInstanceName(Class typeClass) {
168 String value = null;
169 String defaultProviderSpec = getDefaultProvider(typeClass);
170 if (defaultProviderSpec != null) {
171 int hashpos = defaultProviderSpec.indexOf('#');
172 if (hashpos >= 0 && hashpos < defaultProviderSpec.length() - 1) {
173 value = defaultProviderSpec.substring(hashpos + 1);
174 }
175 }
176 return value;
177 }
178
179
180 /** Obtain the value of a default provider property.
181 @param typeClass The type of the default provider property. This
182 should be one of Receiver.class, Transmitter.class, Sequencer.class,
183 Synthesizer.class, SourceDataLine.class, TargetDataLine.class,
184 Clip.class or Port.class.
185 @return The complete value of the property, if available.
186 If the property is not set, null is returned.
187 */
188 private static synchronized String getDefaultProvider(Class typeClass) {
189 String value;
190 String propertyName = typeClass.getName();
191 value = JSSecurityManager.getProperty(propertyName);
192 if (value == null) {
193 value = getProperties().getProperty(propertyName);
194 }
195 if ("".equals(value)) {
196 value = null;
197 }
198 return value;
199 }
200
201
202 /** Obtain a properties bundle containing property values from the
203 properties file. If the properties file could not be loaded,
204 the properties bundle is empty.
205 */
206 private static synchronized Properties getProperties() {
207 if (properties == null) {
208 properties = new Properties();
209 JSSecurityManager.loadProperties(properties, PROPERTIES_FILENAME);
210 }
211 return properties;
212 }
213
214 // INNER CLASSES
215
216 private static class ProviderCache {
217 // System time of the last update in milliseconds.
218 public long lastUpdate;
219
220 // The providers.
221 public List providers;
222 }
223}