diff -r fd16c54261b3 -r 90ce3da70b43 jdk/src/share/classes/com/sun/media/sound/JDK13Services.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/media/sound/JDK13Services.java Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,223 @@ +/* + * 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.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.sound.sampled.spi.AudioFileReader; +import javax.sound.sampled.spi.AudioFileWriter; +import javax.sound.sampled.spi.FormatConversionProvider; +import javax.sound.sampled.spi.MixerProvider; + +import javax.sound.midi.spi.MidiFileReader; +import javax.sound.midi.spi.MidiFileWriter; +import javax.sound.midi.spi.SoundbankReader; +import javax.sound.midi.spi.MidiDeviceProvider; + + +/** + * JDK13Services uses the Service class in JDK 1.3 + * to discover a list of service providers installed + * in the system. + * + * This class is public because it is called from javax.sound.midi.MidiSystem + * and javax.sound.sampled.AudioSystem. The alternative would be to make + * JSSecurityManager public, which is considered worse. + * + * @author Matthias Pfisterer + */ +public class JDK13Services { + + /** The default for the length of the period to hold the cache. + This value is given in milliseconds. It is equivalent to + 1 minute. + */ + private static final long DEFAULT_CACHING_PERIOD = 60000; + + /** Filename of the properties file for default provider properties. + This file is searched in the subdirectory "lib" of the JRE directory + (this behaviour is hardcoded). + */ + private static final String PROPERTIES_FILENAME = "sound.properties"; + + /** Cache for the providers. + Class objects of the provider type (MixerProvider, MidiDeviceProvider + ...) are used as keys. The values are instances of ProviderCache. + */ + private static Map providersCacheMap = new HashMap(); + + + /** The length of the period to hold the cache. + This value is given in milliseconds. + */ + private static long cachingPeriod = DEFAULT_CACHING_PERIOD; + + /** Properties loaded from the properties file for default provider + properties. + */ + private static Properties properties; + + + /** Private, no-args constructor to ensure against instantiation. + */ + private JDK13Services() { + } + + + /** Set the period provider lists are cached. + This method is only intended for testing. + */ + public static void setCachingPeriod(int seconds) { + cachingPeriod = seconds * 1000L; + } + + + /** Obtains a List containing installed instances of the + providers for the requested service. + The List of providers is cached for the period of time given by + {@link #cachingPeriod cachingPeriod}. During this period, the same + List instance is returned for the same type of provider. After this + period, a new instance is constructed and returned. The returned + List is immutable. + @param serviceClass The type of providers requested. This should be one + of AudioFileReader.class, AudioFileWriter.class, + FormatConversionProvider.class, MixerProvider.class, + MidiDeviceProvider.class, MidiFileReader.class, MidiFileWriter.class or + SoundbankReader.class. + @return A List of providers of the requested type. This List is + immutable. + */ + public static synchronized List getProviders(Class serviceClass) { + ProviderCache cache = (ProviderCache) providersCacheMap.get(serviceClass); + if (cache == null) { + cache = new ProviderCache(); + providersCacheMap.put(serviceClass, cache); + } + if (cache.providers == null || + System.currentTimeMillis() > cache.lastUpdate + cachingPeriod) { + cache.providers = Collections.unmodifiableList(JSSecurityManager.getProviders(serviceClass)); + cache.lastUpdate = System.currentTimeMillis(); + } + return cache.providers; + } + + + /** Obtain the provider class name part of a default provider property. + @param typeClass The type of the default provider property. This + should be one of Receiver.class, Transmitter.class, Sequencer.class, + Synthesizer.class, SourceDataLine.class, TargetDataLine.class, + Clip.class or Port.class. + @return The value of the provider class name part of the property + (the part before the hash sign), if available. If the property is + not set or the value has no provider class name part, null is returned. + */ + public static synchronized String getDefaultProviderClassName(Class typeClass) { + String value = null; + String defaultProviderSpec = getDefaultProvider(typeClass); + if (defaultProviderSpec != null) { + int hashpos = defaultProviderSpec.indexOf('#'); + if (hashpos == 0) { + // instance name only; leave value as null + } else if (hashpos > 0) { + value = defaultProviderSpec.substring(0, hashpos); + } else { + value = defaultProviderSpec; + } + } + return value; + } + + + /** Obtain the instance name part of a default provider property. + @param typeClass The type of the default provider property. This + should be one of Receiver.class, Transmitter.class, Sequencer.class, + Synthesizer.class, SourceDataLine.class, TargetDataLine.class, + Clip.class or Port.class. + @return The value of the instance name part of the property (the + part after the hash sign), if available. If the property is not set + or the value has no instance name part, null is returned. + */ + public static synchronized String getDefaultInstanceName(Class typeClass) { + String value = null; + String defaultProviderSpec = getDefaultProvider(typeClass); + if (defaultProviderSpec != null) { + int hashpos = defaultProviderSpec.indexOf('#'); + if (hashpos >= 0 && hashpos < defaultProviderSpec.length() - 1) { + value = defaultProviderSpec.substring(hashpos + 1); + } + } + return value; + } + + + /** Obtain the value of a default provider property. + @param typeClass The type of the default provider property. This + should be one of Receiver.class, Transmitter.class, Sequencer.class, + Synthesizer.class, SourceDataLine.class, TargetDataLine.class, + Clip.class or Port.class. + @return The complete value of the property, if available. + If the property is not set, null is returned. + */ + private static synchronized String getDefaultProvider(Class typeClass) { + String value; + String propertyName = typeClass.getName(); + value = JSSecurityManager.getProperty(propertyName); + if (value == null) { + value = getProperties().getProperty(propertyName); + } + if ("".equals(value)) { + value = null; + } + return value; + } + + + /** Obtain a properties bundle containing property values from the + properties file. If the properties file could not be loaded, + the properties bundle is empty. + */ + private static synchronized Properties getProperties() { + if (properties == null) { + properties = new Properties(); + JSSecurityManager.loadProperties(properties, PROPERTIES_FILENAME); + } + return properties; + } + + // INNER CLASSES + + private static class ProviderCache { + // System time of the last update in milliseconds. + public long lastUpdate; + + // The providers. + public List providers; + } +}