📄 configcontainer.java
字号:
/* * $RCSfile: ConfigContainer.java,v $ * * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistribution of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistribution in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or * intended for use in the design, construction, operation or * maintenance of any nuclear facility. * * $Revision: 1.6 $ * $Date: 2007/02/09 17:20:43 $ * $State: Exp $ */package com.sun.j3d.utils.universe ;import java.io.* ;import java.util.* ;import java.net.URL ;import java.net.MalformedURLException ;import javax.media.j3d.* ;import com.sun.j3d.utils.behaviors.vp.ViewPlatformBehavior ;/** * Loads a Java 3D configuration file and creates a container of named objects * that will effect the viewing configuration specified in the file. These * can include Viewers, ViewingPlatforms, ViewPlatformBehaviors, InputDevices, * Sensors, and other objects.<p> * * Clients can construct the view side of a scene graph by retrieving these * objects using the accessor methods provided by this class. This could * involve as little as just attaching ViewingPlatforms to a Locale, depending * upon how completely the viewing configuration is specified in the file. * The ConfiguredUniverse class is an example of a ConfigContainer client and * how it can be used.<p> * * ConfigContainer can be useful for clients other than ConfiguredUniverse. * InputDevice and ViewPlatformBehavior configuration is fully supported, so a * given Java 3D installation can provide configuration files to an * application that will allow it to fully utilize whatever site-specific * devices and behaviors are available. The configuration mechanism can be * extended for any target object through the use of the * <code>NewObject</code> and <code>ObjectProperty</code> configuration * commands. * * @see ConfiguredUniverse * @see <a href="doc-files/config-syntax.html"> * The Java 3D Configuration File</a> * @see <a href="doc-files/config-examples.html"> * Example Configuration Files</a> * * @since Java 3D 1.3.1 */public class ConfigContainer { // // The configuration object database is implemented with a HashMap which // maps their class names to ArrayList objects which contain the actual // instances. The latter are used since the instances of a given class // must be evaluated in the order in which they were created. // LinkedHashMap is available in JDK 1.4 but currently this code must run // under JDK 1.3.1 as well. // private Map baseNameMap = new HashMap() ; // Map containing named canvases for each view. private Map viewCanvasMap = new HashMap() ; // Read-only Maps for the public interface to the configuration database. private ReadOnlyMap bodyMap = null ; private ReadOnlyMap environmentMap = null ; private ReadOnlyMap viewerMap = null ; private ReadOnlyMap deviceMap = null ; private ReadOnlyMap sensorMap = null ; private ReadOnlyMap behaviorMap = null ; private ReadOnlyMap platformMap = null ; private ReadOnlyMap genericObjectMap = null ; // Read-only Sets for the public interface to the configuration database. private ReadOnlySet bodies = null ; private ReadOnlySet environments = null ; private ReadOnlySet viewers = null ; private ReadOnlySet devices = null ; private ReadOnlySet sensors = null ; private ReadOnlySet behaviors = null ; private ReadOnlySet platforms = null ; private ReadOnlySet genericObjects = null ; // The number of TransformGroups to include in ViewingPlatforms. private int transformCount = 1 ; // The visibility status of Viewer AWT components. private boolean setVisible = false ; private ClassLoader classLoader = ClassLoader.getSystemClassLoader(); /** * The name of the file this ConfigContainer is currently loading. */ String currentFileName = null ; /** * Creates a new ConfigContainer and loads the configuration file at the * specified URL. All ViewingPlatform instances are created with a single * TransformGroup and all Viewer components are initially invisible. * * @param userConfig URL of the configuration file to load */ public ConfigContainer(URL userConfig) { this(userConfig, false, 1, true) ; } /** * Creates a new ConfigContainer and loads the configuration file at the * specified URL. All ViewingPlatform instances are created with a single * TransformGroup and all Viewer components are initially invisible. * * @param userConfig URL of the configuration file to load * @param classLoader the class loader to use to load classes specified * in the config file. */ public ConfigContainer(URL userConfig, ClassLoader classLoader) { this(userConfig, false, 1, true, classLoader) ; } /** * Creates a new ConfigContainer and loads the configuration file at the * specified URL. Any ViewingPlatform instantiated by the configuration * file will be created with the specified number of transforms. Viewer * components may be set initially visible or invisible with the * <code>setVisible</code> flag. * * @param userConfig URL of the configuration file to load * @param setVisible if true, <code>setVisible(true)</code> is called on * all Viewers * @param transformCount number of transforms to be included in any * ViewingPlatform created; must be greater than 0 */ public ConfigContainer(URL userConfig, boolean setVisible, int transformCount) { this(userConfig, setVisible, transformCount, true) ; } /** * Creates a new ConfigContainer and loads the configuration file at the * specified URL. Any ViewingPlatform instantiated by the configuration * file will be created with the specified number of transforms. Viewer * components may be set initially visible or invisible with the * <code>setVisible</code> flag. * * @param userConfig URL of the configuration file to load * @param setVisible if true, <code>setVisible(true)</code> is called on * all Viewers * @param transformCount number of transforms to be included in any * ViewingPlatform created; must be greater than 0 * @param classLoader the class loader to use to load classes specified * in the config file. */ public ConfigContainer(URL userConfig, boolean setVisible, int transformCount, ClassLoader classLoader) { this(userConfig, setVisible, transformCount, true, classLoader) ; } /** * Package-scoped constructor for ConfigContainer. This provides an * additional flag, <code>attachBehaviors</code>, which indicates whether * or not ViewPlatformBehaviors should be attached to the ViewingPlatforms * specified for them.<p> * * Normally the flag should be true. However, when instantiated by * ConfiguredUniverse, this flag is set false so that ConfiguredUniverse * can set a reference to itself in the ViewingPlatform before attaching * the behavior. This provides backwards compatibility to behaviors that * access the ConfiguredUniverse instance from a call to * <code>setViewingPlatform</code> in order to look up the actual Sensor, * Viewer, Behavior, etc., instances associated with the names provided * them from the configuration file.<p> * * The preferred methods to retrieve instances of specific objects defined * in the configuration file are to either 1) get the ConfiguredUniverse * instance when the behavior's <code>initialize</code> method is called, * or to 2) define properties that accept object instances directly, and * then use the newer Device, Sensor, ViewPlatform, etc., built-in * commands in the configuration file. These built-ins will return an * object instance from a name. * * @param userConfig URL of the configuration file to load * @param setVisible if true, <code>setVisible(true)</code> is called on * all Viewers * @param transformCount number of transforms to be included in any * ViewingPlatform created; must be greater than 0 * @param attachBehaviors if true, attach ViewPlatformBehaviors to the * appropriate ViewingPlatforms */ ConfigContainer(URL userConfig, boolean setVisible, int transformCount, boolean attachBehaviors) { if (transformCount < 1) throw new IllegalArgumentException ("transformCount must be greater than 0") ; loadConfig(userConfig) ; processConfig(setVisible, transformCount, attachBehaviors) ; } /** * Package scoped constructor that adds the ability to set the ClassLoader * which will be used to load any app specific classes specified in the * configuration file. By default SystemClassLoader is used. */ ConfigContainer(URL userConfig, boolean setVisible, int transformCount, boolean attachBehaviors, ClassLoader classLoader) { this(userConfig, setVisible, transformCount, attachBehaviors); this.classLoader = classLoader; } /** * Open, parse, and load the contents of a configuration file. * * @param userConfig location of the configuration file */ private void loadConfig(URL userConfig) { InputStream inputStream = null ; StreamTokenizer streamTokenizer = null ; String lastFileName = currentFileName ; currentFileName = userConfig.toString() ; try { inputStream = userConfig.openStream() ; Reader r = new BufferedReader(new InputStreamReader(inputStream)) ; streamTokenizer = new StreamTokenizer(r) ; } catch (IOException e) { throw new IllegalArgumentException( e + "\nUnable to open " + currentFileName) ; } // // Set up syntax tables for the tokenizer. // // It would be nice to allow '/' as a word constituent for URL strings // and Unix paths, but then the scanner won't ignore "//" and "/* */" // comment style syntax. Treating '/' as an ordinary character will // allow comments to work, but then '/' becomes a single token which // has to be concatenated with subsequent tokens to reconstruct the // original word string. // // It is cleaner to just require quoting for forward slashes. '/' // should still be treated as an ordinary character however, so that a // non-quoted URL string or Unix path will be treated as a syntax // error instead of a comment. // streamTokenizer.ordinaryChar('/') ; streamTokenizer.wordChars('_', '_') ; streamTokenizer.wordChars('$', '$') ; // for ${...} Java property streamTokenizer.wordChars('{', '}') ; // substitution in word tokens streamTokenizer.slashSlashComments(true) ; streamTokenizer.slashStarComments(true) ; // Create an s-expression parser to use for all top-level (0) commands. ConfigSexpression sexp = new ConfigSexpression() ; // Loop through all top-level commands. Boolean.FALSE is returned // after the last one is evaluated. while (sexp.parseAndEval(this, streamTokenizer, 0) != Boolean.FALSE) ; // Close the input stream. try { inputStream.close() ; } catch (IOException e) { throw new IllegalArgumentException( e + "\nUnable to close " + currentFileName) ; } // Restore current file name. currentFileName = lastFileName ; } /** * This method gets called from the s-expression parser to process a * configuration command. * * @param elements tokenized list of sexp elements * @param lineNumber command line number */ void evaluateCommand(ArrayList elements, int lineNumber) { ConfigObject co ; ConfigCommand cmd ; // Create a command object. cmd = new ConfigCommand(elements, currentFileName, lineNumber) ; // Process the command according to its type. switch (cmd.type) { case ConfigCommand.CREATE: co = createConfigObject(cmd) ; addConfigObject(co) ; break ; case ConfigCommand.ALIAS: co = createConfigAlias(cmd) ; addConfigObject(co) ; break ; case ConfigCommand.PROPERTY: co = findConfigObject(cmd.baseName, cmd.instanceName) ; co.setProperty(cmd) ; break ; case ConfigCommand.INCLUDE: if (! (cmd.argv[1] instanceof String)) { throw new IllegalArgumentException ("Include file must be a URL string") ; } URL url = null ; String urlString = (String)cmd.argv[1] ; try { url = new URL(urlString) ; } catch (MalformedURLException e) { throw new IllegalArgumentException(e.toString()) ; } loadConfig(url) ; break ; case ConfigCommand.IGNORE: break ; default: throw new IllegalArgumentException ("Unknown command \"" + cmd.commandName + "\"") ; } } /** * Instantiates and initializes an object that extends the ConfigObject * base class. The class name of the object is derived from the * command, which is of the following form:<p> * * (New{baseName} {instanceName} ... [Alias {aliasName}])<p> * * The first two command elements and the optional trailing Alias syntax * are processed here, at which point the subclass implementation of * initialize() is called. Subclasses must override initialize() if they * need to process more than what is processed by default here. * * @param cmd configuration command that creates a new ConfigObject */ private ConfigObject createConfigObject(ConfigCommand cmd) { Class objectClass = null ; ConfigObject configObject = null ; // Instantatiate the ConfigObject if possible. This is not the target // object, but an object that will gather configuration properties,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -