You are viewing a plain text version of this content. The canonical link for it is here.
Posted to adffaces-commits@incubator.apache.org by aw...@apache.org on 2006/10/11 07:01:54 UTC

svn commit: r462718 [1/2] - in /incubator/adffaces/trunk/trinidad: trinidad-build/src/main/resources/META-INF/maven-faces-plugin/renderers/trinidad/ trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/ trinidad-impl/src...

Author: awiner
Date: Wed Oct 11 00:01:52 2006
New Revision: 462718

URL: http://svn.apache.org/viewvc?view=rev&rev=462718
Log:
Create Faces-major renderers for tr:separator and tr:media.  Support using the renderers where Javascript attributes not only aren't supported, but aren't even present on the target components

Added:
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/MediaRenderer.java
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/SeparatorRenderer.java
Removed:
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/ui/laf/base/xhtml/MediaRenderer.java
Modified:
    incubator/adffaces/trunk/trinidad/trinidad-build/src/main/resources/META-INF/maven-faces-plugin/renderers/trinidad/Media.xml
    incubator/adffaces/trunk/trinidad/trinidad-build/src/main/resources/META-INF/maven-faces-plugin/renderers/trinidad/Separator.xml
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/BodyRenderer.java
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/ColumnGroupRenderer.java
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormElementRenderer.java
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormRenderer.java
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/GoLinkRenderer.java
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/SkinSelectors.java
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/XhtmlRenderer.java
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/ui/UIConstants.java
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/ui/laf/base/desktop/BaseDesktopConstants.java
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/ui/laf/base/xhtml/XhtmlLookAndFeel.java
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/resources/META-INF/faces-bean.properties
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/resources/META-INF/renderertype-localname.properties
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/media-minimalPPC-golden.xml
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/panelPage-facets-minimal-golden.xml
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/panelPage-facets-minimalIE-golden.xml
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/panelPage-facets-minimalIERtl-golden.xml
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/panelPage-facets-minimalInacc-golden.xml
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/panelPage-facets-minimalSaf-golden.xml
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/panelPage-facets-minimalScrRdr-golden.xml
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/separator-minimal-golden.xml
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/separator-minimalIE-golden.xml
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/separator-minimalIERtl-golden.xml
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/separator-minimalInacc-golden.xml
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/separator-minimalPPC-golden.xml
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/separator-minimalSaf-golden.xml
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/test/resources/org/apache/myfaces/trinidadinternal/renderkit/golden/separator-minimalScrRdr-golden.xml

Modified: incubator/adffaces/trunk/trinidad/trinidad-build/src/main/resources/META-INF/maven-faces-plugin/renderers/trinidad/Media.xml
URL: http://svn.apache.org/viewvc/incubator/adffaces/trunk/trinidad/trinidad-build/src/main/resources/META-INF/maven-faces-plugin/renderers/trinidad/Media.xml?view=diff&rev=462718&r1=462717&r2=462718
==============================================================================
--- incubator/adffaces/trunk/trinidad/trinidad-build/src/main/resources/META-INF/maven-faces-plugin/renderers/trinidad/Media.xml (original)
+++ incubator/adffaces/trunk/trinidad/trinidad-build/src/main/resources/META-INF/maven-faces-plugin/renderers/trinidad/Media.xml Wed Oct 11 00:01:52 2006
@@ -21,7 +21,7 @@
     <renderer>
       <component-family>org.apache.myfaces.trinidad.Object</component-family>
       <renderer-type>org.apache.myfaces.trinidad.Media</renderer-type>
-      <renderer-class>org.apache.myfaces.trinidadinternal.uinode.UINodeRendererBase</renderer-class>
+      <renderer-class>org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.MediaRenderer</renderer-class>
       <renderer-extension>
         <mfp:component-type>org.apache.myfaces.trinidad.CoreMedia</mfp:component-type>
       </renderer-extension>

Modified: incubator/adffaces/trunk/trinidad/trinidad-build/src/main/resources/META-INF/maven-faces-plugin/renderers/trinidad/Separator.xml
URL: http://svn.apache.org/viewvc/incubator/adffaces/trunk/trinidad/trinidad-build/src/main/resources/META-INF/maven-faces-plugin/renderers/trinidad/Separator.xml?view=diff&rev=462718&r1=462717&r2=462718
==============================================================================
--- incubator/adffaces/trunk/trinidad/trinidad-build/src/main/resources/META-INF/maven-faces-plugin/renderers/trinidad/Separator.xml (original)
+++ incubator/adffaces/trunk/trinidad/trinidad-build/src/main/resources/META-INF/maven-faces-plugin/renderers/trinidad/Separator.xml Wed Oct 11 00:01:52 2006
@@ -21,7 +21,7 @@
     <renderer>
       <component-family>org.apache.myfaces.trinidad.Object</component-family>
       <renderer-type>org.apache.myfaces.trinidad.Separator</renderer-type>
-      <renderer-class>org.apache.myfaces.trinidadinternal.uinode.UINodeRendererBase</renderer-class>
+      <renderer-class>org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.SeparatorRenderer</renderer-class>
       <renderer-extension>
         <mfp:component-type>org.apache.myfaces.trinidad.CoreSeparator</mfp:component-type>
       </renderer-extension>

Modified: incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/BodyRenderer.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/BodyRenderer.java?view=diff&rev=462718&r1=462717&r2=462718
==============================================================================
--- incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/BodyRenderer.java (original)
+++ incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/BodyRenderer.java Wed Oct 11 00:01:52 2006
@@ -191,7 +191,11 @@
 
   protected String getOnload(RenderingContext arc, FacesBean bean)
   {
-    String onload = toString(bean.getProperty(_onloadKey));
+    String onload;
+    if (_onloadKey == null)
+      onload = null;
+    else
+      onload = toString(bean.getProperty(_onloadKey));
     if (PartialPageUtils.supportsPartialRendering(arc))
 	{
 	  // Don't short circuit...
@@ -215,7 +219,11 @@
 
   protected String getOnunload(RenderingContext arc, FacesBean bean)
   {
-    String onunload = toString(bean.getProperty(_onunloadKey));
+    String onunload;
+    if (_onunloadKey == null)
+      onunload = null;
+    else
+      onunload = toString(bean.getProperty(_onunloadKey));
     if (PartialPageUtils.supportsPartialRendering(arc))
     {
       // Don't short circuit...

Modified: incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/ColumnGroupRenderer.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/ColumnGroupRenderer.java?view=diff&rev=462718&r1=462717&r2=462718
==============================================================================
--- incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/ColumnGroupRenderer.java (original)
+++ incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/ColumnGroupRenderer.java Wed Oct 11 00:01:52 2006
@@ -150,6 +150,9 @@
 
   protected String getDefaultSortOrder(FacesBean bean)
   {
+    if (_defaultSortOrderKey == null)
+      return null;
+
     return toString(bean.getProperty(_defaultSortOrderKey));
   }
 

Modified: incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormElementRenderer.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormElementRenderer.java?view=diff&rev=462718&r1=462717&r2=462718
==============================================================================
--- incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormElementRenderer.java (original)
+++ incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormElementRenderer.java Wed Oct 11 00:01:52 2006
@@ -214,16 +214,25 @@
 
   protected String getOnblur(FacesBean bean)
   {
+    if (_onblurKey == null)
+      return null;
+
     return toString(bean.getProperty(_onblurKey));
   }
 
   protected String getOnfocus(FacesBean bean)
   {
+    if (_onfocusKey == null)
+      return null;
+
     return toString(bean.getProperty(_onfocusKey));
   }
 
   protected String getOnchange(FacesBean bean)
   {
+    if (_onchangeKey == null)
+      return null;
+
     return toString(bean.getProperty(_onchangeKey));
   }
 

Modified: incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormRenderer.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormRenderer.java?view=diff&rev=462718&r1=462717&r2=462718
==============================================================================
--- incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormRenderer.java (original)
+++ incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/FormRenderer.java Wed Oct 11 00:01:52 2006
@@ -930,6 +930,9 @@
 
   protected String getOnsubmit(FacesBean bean)
   {
+    if (_onsubmitKey == null)
+      return null;
+
     return toString(bean.getProperty(_onsubmitKey));
   }
 

Modified: incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/GoLinkRenderer.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/GoLinkRenderer.java?view=diff&rev=462718&r1=462717&r2=462718
==============================================================================
--- incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/GoLinkRenderer.java (original)
+++ incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/GoLinkRenderer.java Wed Oct 11 00:01:52 2006
@@ -181,11 +181,17 @@
 
   protected String getOnblur(FacesBean bean)
   {
+    if (_onblurKey == null)
+      return null;
+
     return toString(bean.getProperty(_onblurKey));
   }
 
   protected String getOnfocus(FacesBean bean)
   {
+    if (_onfocusKey == null)
+      return null;
+
     return toString(bean.getProperty(_onfocusKey));
   }
 

Added: incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/MediaRenderer.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/MediaRenderer.java?view=auto&rev=462718
==============================================================================
--- incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/MediaRenderer.java (added)
+++ incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/MediaRenderer.java Wed Oct 11 00:01:52 2006
@@ -0,0 +1,2162 @@
+/*
+ * Copyright  2002-2006 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.myfaces.trinidadinternal.renderkit.core.xhtml;
+
+import java.io.IOException;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+
+import org.apache.myfaces.trinidad.bean.FacesBean;
+import org.apache.myfaces.trinidad.bean.PropertyKey;
+import org.apache.myfaces.trinidad.component.core.output.CoreMedia;
+
+import org.apache.myfaces.trinidad.context.RenderingContext;
+
+import org.apache.myfaces.trinidadinternal.util.IntegerUtils;
+import org.apache.myfaces.trinidadinternal.agent.TrinidadAgent;
+
+
+/**
+ * Base class for audio and video rendering.
+ *
+ * @version $Name:  $ ($Revision: adfrt/faces/adf-faces-impl/src/main/java/oracle/adfinternal/view/faces/ui/laf/base/xhtml/MediaRenderer.java#0 $) $Date: 15-nov-2005.19:26:37 $
+ * @author The Oracle ADF Faces Team
+ */
+public class MediaRenderer extends XhtmlRenderer
+{
+
+  public MediaRenderer()
+  {
+    super(CoreMedia.TYPE);
+  }
+  
+  @Override
+  protected void findTypeConstants(FacesBean.Type type)
+  {
+    super.findTypeConstants(type);
+    _sourceKey = type.findKey("source");
+    _playerKey = type.findKey("player");
+    _contentTypeKey = type.findKey("contentType");
+    _autostartKey = type.findKey("autostart");
+    _playCountKey = type.findKey("playCount");
+    _controlsKey = type.findKey("controls");
+    _standbyTextKey = type.findKey("standbyText");
+
+    _widthKey = type.findKey("width");
+    _heightKey = type.findKey("height");
+    _innerWidthKey = type.findKey("innerWidth");
+    _innerHeightKey = type.findKey("innerHeight");
+  }
+
+  protected String getSource(FacesBean bean)
+  {
+    return toUri(bean.getProperty(_sourceKey));
+  }
+
+  protected String getPlayer(FacesBean bean)
+  {
+    return toString(bean.getProperty(_playerKey));
+  }
+
+  protected String getContentType(FacesBean bean)
+  {
+    return toString(bean.getProperty(_contentTypeKey));
+  }
+
+  protected String getControls(FacesBean bean)
+  {
+    return toString(bean.getProperty(_controlsKey));
+  }
+
+  protected String getStandbyText(FacesBean bean)
+  {
+    return toString(bean.getProperty(_standbyTextKey));
+  }
+
+  protected boolean getAutostart(FacesBean bean)
+  {
+    Object o = bean.getProperty(_autostartKey);
+    if (o == null)
+      o = _autostartKey.getDefault();
+
+    return Boolean.TRUE.equals(o);
+  }
+
+
+  protected Number getPlayCount(FacesBean bean)
+  {
+    Object o = bean.getProperty(_playCountKey);
+    if (o == null)
+      o = _playCountKey.getDefault();
+
+    if (o instanceof Number)
+      return ((Number) o);
+
+    return null;
+  }
+
+  protected String getWidth(FacesBean bean)
+  {
+    return toString(bean.getProperty(_widthKey));
+  }
+
+  protected String getHeight(FacesBean bean)
+  {
+    return toString(bean.getProperty(_heightKey));
+  }
+
+
+  protected String getInnerWidth(FacesBean bean)
+  {
+    return toString(bean.getProperty(_innerWidthKey));
+  }
+
+  protected String getInnerHeight(FacesBean bean)
+  {
+    return toString(bean.getProperty(_innerHeightKey));
+  }
+
+
+  @Override
+  public boolean getRendersChildren()
+  {
+    return true;
+  }
+
+  @Override
+  protected void encodeAll(
+    FacesContext        context,
+    RenderingContext    arc,
+    UIComponent         component,
+    FacesBean           bean) throws IOException
+  {
+    // get the mime type
+    String mimeType = _getMimeType(bean);
+
+    // extract the primary cotnent type from the content mime type
+    String primaryContentType = _getPrimaryContentType(mimeType);
+
+    MediaRenderer.PlayerData playerData = _getPlayerData(arc,
+                                                         bean,
+                                                         mimeType,
+                                                         primaryContentType);
+
+    ResponseWriter writer = context.getResponseWriter();
+
+    String  source         = getSource(bean);
+    String  contentType    = getContentType(bean);
+    String  id             = getClientId(context, component);
+
+    if (_LINK_PLAYER_DATA == playerData)
+    {
+      _renderLink(context,
+                  arc,
+                  component,
+                  bean,
+                  id,
+                  source,
+                  null,
+                  contentType);
+    }
+    else
+    {
+     // determine which controls to display based on the primary
+      // mime type
+      MediaRenderer.ControlSet  controlSet = playerData.getControlSet(primaryContentType);
+
+
+
+      MediaRenderer.ControlData imageWindowControlData =
+               playerData.getImageWindowControlData(primaryContentType);
+
+      MediaRenderer.ControlData controlData = (controlSet != null)
+                                  ? controlSet.getControlData(
+                                                 getControls(bean))
+                                  : null;
+
+      //
+      // Determine which tags to use
+      //
+      boolean useEmbedTag = true;
+      boolean useObjectTag = true;
+
+      boolean isImage = _IMAGE_PLAYER_DATA == playerData;
+
+      if (isImage)
+      {
+        useEmbedTag  = false;
+        useObjectTag = false;
+      }
+      else
+      {
+        useEmbedTag  = useEmbed(arc);
+        useObjectTag = !useEmbedTag;
+      }
+
+      String width = getWidth(bean);
+
+      // since current players don't add to width, treat innerWidth
+      // identically to width for now
+      if (width == null)
+        width = getInnerWidth(bean);
+
+      // get whether this set of controls can be autosized.
+      // embed elements can not be autosized.
+      boolean canAutosize = playerData.canAlwaysAutosize ||
+                            (controlData.canAutosize && !useEmbedTag);
+
+      // compute default width for players that don't autosize
+      if ((width == null) && !canAutosize)
+      {
+        Number defaultInnerWidth = getDefaultInnerWidth(primaryContentType);
+
+        // use the greater of the default width of the content
+        // and the preferred width of the controls
+        width = ((defaultInnerWidth.intValue() >
+                 controlData.preferredWidth.intValue())
+                  ? defaultInnerWidth
+                 : controlData.preferredWidth).toString();
+      }
+
+
+
+      // default the autostarting value
+      String  autostartValue  = null;
+
+      // default the playcount param name and value
+      String playCountParamName = null;
+      Object playCountParamValue = null;
+
+      if (!isImage)
+      {
+        //
+        // Handle looping attributes
+        //
+        Number playCountValue = getPlayCount(bean);
+
+        if (playCountValue != null)
+        {
+          int playCount = playCountValue.intValue();
+
+          if ((playCount != 1) && (playCount >= 0))
+          {
+            if (playCount == 0)
+            {
+              // some players handle infinite looping specially
+              playCountParamName  = playerData.infiniteLoopParamName;
+              playCountParamValue = playerData.infiniteLoopParamValue;
+            }
+            else
+            {
+              playCountParamName  = playerData.playCountParamName;
+              playCountParamValue = playCountValue;
+            }
+          }
+        }
+
+        //
+        // determine whether we should autostart
+        //
+        boolean autostarts = getAutostart(bean);
+        if (autostarts != playerData.autostartByDefault)
+        {
+          // only write out an autostart value, if its different than
+          // the default
+          autostartValue = autostarts
+            ? playerData.autostartTrueValue
+            : playerData.autostartFalseValue;
+        }
+      }
+
+
+      String standbyText = getStandbyText(bean);
+
+      String height = null;
+      // if image window and controls rendered separately
+      if ( imageWindowControlData != null )
+      {
+
+        height = _getInnerHeight( bean,
+                                  canAutosize,
+                                  primaryContentType,
+                                  controlData,
+                                  playerData );
+
+        // since image and controls are rendered separately, a value
+        // is needed to associate them. The id will be used if it is not null,
+        // otherwise an id will be generated for the value.
+        String wireImageToControlsParamValue = id;
+
+        _render( context,
+                 arc,
+                 component,
+                 bean,
+                 contentType,
+                 id,
+                 wireImageToControlsParamValue,
+                 source,
+                 standbyText,
+                 width,
+                 height,
+                 autostartValue,
+                 playCountParamName,
+                 playCountParamValue,
+                 playerData,
+                 imageWindowControlData,
+                 useEmbedTag,
+                 useObjectTag,
+                 isImage,
+                 false);
+
+
+        if ( controlData != _NULL_CONTROL_DATA )
+        {
+          writer.startElement("div", component);
+          writer.endElement("div");
+
+
+          height = IntegerUtils.getInteger( controlData.height ).toString();
+          _render( context,
+                   arc,
+                   component,
+                   bean,
+                   contentType,
+                   id,
+                   wireImageToControlsParamValue,
+                   null,
+                   null,
+                   width,
+                   height,
+                   null,
+                   null,
+                   null,
+                   playerData,
+                   controlData,
+                   useEmbedTag,
+                   useObjectTag,
+                   isImage,
+                   true);
+        }
+      }
+      // if image window and controls rendered together
+      else
+      {
+        height = _getHeight( bean,
+                             canAutosize,
+                             primaryContentType,
+                             controlData,
+                             playerData );
+
+        _render( context,
+                 arc,
+                 component,
+                 bean,
+                 contentType,
+                 id,
+                 null,
+                 source,
+                 standbyText,
+                 width,
+                 height,
+                 autostartValue,
+                 playCountParamName,
+                 playCountParamValue,
+                 playerData,
+                 controlData,
+                 useEmbedTag,
+                 useObjectTag,
+                 isImage,
+                 false);
+      }
+
+
+      if (useEmbedTag)
+      {
+        //
+        // render the alternative link content
+        //
+        // =-=bts I feel that our backup rendering should be an icon that
+        //        we retrieve using a pretected method
+        //
+        writer.startElement("noembed", component);
+        _renderLink(context, arc, component, bean, null, source, null, contentType);
+        writer.endElement("noembed");
+      }
+    }
+  }
+
+  /**
+   * Returns the default inner width to use for players when no width is
+   * specified.
+   */
+  protected Number getDefaultInnerWidth(
+    String           primaryContentType
+    )
+  {
+    return _getDefaultSizeArray(primaryContentType)[_DEFAULT_INNER_WIDTH_INDEX];
+  }
+
+
+  /**
+   * Returns the default inner height to use for players when no height is
+   * specified.
+   */
+  protected Number getDefaultInnerHeight(
+    String           primaryContentType
+    )
+  {
+    return _getDefaultSizeArray(primaryContentType)[_DEFAULT_INNER_HEIGHT_INDEX];
+  }
+
+
+  /**
+   * Returns true if we should use the <embed> tag instead of the
+   * <object> tag to embed the viewer
+   */
+  protected boolean useEmbed(
+    RenderingContext arc
+    )
+  {
+    TrinidadAgent agent = (TrinidadAgent) arc.getAgent();
+
+    // =-= bts only desktop IE seems to support this
+    //         Move this to capability
+    return !((agent.getAgentType()       == TrinidadAgent.TYPE_DESKTOP) &&
+            (agent.getAgentApplication() == TrinidadAgent.APPLICATION_IEXPLORER) &&
+            (agent.getAgentOS()          == TrinidadAgent.OS_WINDOWS));
+  }
+
+  private Number[] _getDefaultSizeArray(
+    String primaryContentType
+    )
+  {
+    Object sizeArray = _sDefaultInnerSizes.get(primaryContentType);
+
+    if (sizeArray == null)
+    {
+      // try again with video if no entry found for this primary content type
+      sizeArray = _sDefaultInnerSizes.get("video");
+    }
+
+    return (Number[])sizeArray;
+  }
+
+
+  /**
+   * Renders a link
+   */
+  private void _renderLink(
+    FacesContext context,
+    RenderingContext arc,
+    UIComponent  component,
+    FacesBean    bean,
+    String       id,
+    String       source,
+    String       iconUrl,
+    String       contentType
+    ) throws IOException
+  {
+    ResponseWriter writer = context.getResponseWriter();
+
+    // Don't render a link without an "href".
+    // But, for PPR, always render a span if we have an ID.
+    if (source == null)
+    {
+      if (id != null)
+      {
+        writer.startElement("span", component);
+        writer.writeAttribute("id", id, null);
+        renderAllAttributes(context, arc, bean);
+        writer.endElement("span");
+      }
+    }
+    else
+    {
+      writer.startElement("a", component);
+
+      // write the ID
+      if (id != null)
+      {
+        writer.writeAttribute("id", id, null);
+        // And render all the attributes here if we have
+        // that ID, because that means this is the main
+        // content
+        renderAllAttributes(context, arc, bean);
+      }
+
+      // link to the content
+      writer.writeURIAttribute("href", source, null);
+
+      // mime-type of content
+      writer.writeAttribute("type", contentType, null);
+
+      if (iconUrl != null)
+      {
+        // =-=AEW Just noticed: this code fails to render "alt"; before
+        // using, check accessibility!!!
+        writer.startElement("img", component);
+        writer.writeURIAttribute("src", iconUrl, null);
+        writer.endElement("img");
+      }
+
+      writer.writeText(getShortDesc(bean), "shortDesc");
+
+      writer.endElement("a");
+    }
+  }
+
+
+  /**
+   * Renders a name value pair as a <param> element
+   */
+  private void _renderParamAttribute(
+    FacesContext     context,
+    String           paramName,
+    Object           paramValue,
+    boolean          isURL
+    ) throws IOException
+  {
+    if ( paramValue != null )
+    {
+      ResponseWriter writer = context.getResponseWriter();
+
+      writer.startElement("param", null);
+      writer.writeAttribute("name", paramName, null);
+
+      if (isURL)
+      {
+        writer.writeURIAttribute("value", paramValue, null);
+      }
+      else
+      {
+        writer.writeAttribute("value", paramValue, null);
+      }
+
+      writer.endElement("param");
+    }
+  }
+
+
+  /**
+   * Returns the constant identifying the player to use
+   *
+   * =-= bts Do we care about AccessibilityMode?
+   */
+  private MediaRenderer.PlayerData _getPlayerData(
+    RenderingContext arc,
+    FacesBean        bean,
+    String           mimeType,
+    String           primaryMimeType
+    )
+  {
+    PlayerData playerData = null;
+    // the default player is the link player
+    TrinidadAgent agent = (TrinidadAgent) arc.getAgent();
+    int agentOSInt = agent.getAgentOS();
+    
+    // get the set of supported players for this OS
+    HashSet<Object> supportedPlayers = _sSupportedOSPlayers.get(agentOSInt);
+    
+    // are we trying to display an image?
+    boolean isImage = "image".equals(primaryMimeType);
+    
+    // check if this OS supports any non-link style players
+    if (supportedPlayers != null)
+    {
+      // get the desired player, if any
+      String playerString = getPlayer(bean);
+      if (playerString != null)
+      {
+        if (CoreMedia.PLAYER_LINK.equals(playerString))
+        {
+          playerData = _LINK_PLAYER_DATA;
+        }
+        else
+        {
+          // check that the specified player is supported
+          if (!isImage && supportedPlayers.contains(playerString))
+          {
+            playerData = (PlayerData) _sPlayerData.get(playerString);
+            
+            if (playerData != null)
+            {
+              if (mimeType != null)
+              {
+                // check that the format is supported by this player
+                if (!((PlayerData)playerData).isSupportedMimeType(mimeType))
+                {
+                  playerData = null;
+                }
+              }
+            }
+          }
+        }
+      }
+      
+      // assume that all images can be played by the browser's built-in
+      // image player
+      if (isImage)
+        playerData = _IMAGE_PLAYER_DATA;
+      else
+      {
+        // if the primary content type isn't image, video, or audio,
+        // use the link player
+        if (!"video".equals(primaryMimeType) &&
+            !"audio".equals(primaryMimeType))
+          playerData = _LINK_PLAYER_DATA;
+      }
+      
+      //
+      // guess the player based on the mime type
+      //
+      if (playerData == null)
+      {
+        Object preferredPlayer = _sPreferredMimePlayers.get(mimeType);
+        
+        if ((preferredPlayer != null) &&
+            supportedPlayers.contains(preferredPlayer))
+        {
+          playerData = (PlayerData) _sPlayerData.get(preferredPlayer);
+        }
+      }
+      
+      //
+      // guess the player based on the operating system
+      //
+      if (playerData == null)
+      {
+        Object preferredPlayer = _sPreferredOSPlayers.get(agentOSInt);
+        
+        if (preferredPlayer != null)
+        {
+          playerData = (PlayerData) _sPlayerData.get(preferredPlayer);
+          
+          // check that the format is supported by this player
+          if (!playerData.isSupportedMimeType(mimeType))
+          {
+            playerData = null;
+          }
+        }
+      }
+    }
+    
+    // if all else fails, use the link player
+    if (playerData == null)
+      playerData = _LINK_PLAYER_DATA;
+    
+    return playerData;
+  }
+
+
+  /**
+   * Returns the primary content type of the result:
+   * i.e. "audio", "video"
+   */
+  private String _getPrimaryContentType(
+    String mimeType
+    )
+  {
+    if (mimeType != null)
+    {
+      int slashIndex = mimeType.indexOf('/');
+
+      if (slashIndex != -1)
+      {
+        return mimeType.substring(0, slashIndex);
+      }
+    }
+
+    return null;
+  }
+
+
+  /**
+   * Returns the secondary content type of the result:
+   * i.e. "quicktime", "au"
+   */
+  private String _getSecondaryContentType(
+    String mimeType
+    )
+  {
+    if (mimeType != null)
+    {
+      int slashIndex = mimeType.indexOf('/');
+
+      if (slashIndex != -1)
+      {
+        return mimeType.substring(slashIndex + 1);
+      }
+    }
+
+    return null;
+  }
+
+
+  /**
+   * Returns the most likely MIME type for the content
+   */
+  private String _getMimeType(FacesBean bean)
+  {
+    // try any provided content mime type first
+    String mimeType = getContentType(bean);
+
+    // primary mime type to force mime type to
+    String primaryForced = null;
+
+    if (mimeType != null)
+    {
+      // convert mime types to lower case
+      mimeType = mimeType.toLowerCase(Locale.US);
+
+      // Check that the user hasn't forced the primary mime-type
+      int mimeLength = mimeType.length();
+
+      if ((mimeType.charAt(mimeLength - 1) == '*') &&
+          (mimeType.charAt(mimeLength - 2) == '/'))
+      {
+        // force the primary mime type
+        primaryForced = mimeType.substring(0, mimeLength - 2);
+      }
+      else
+      {
+        Object remapped = _sMimeTypeRemapper.get(mimeType);
+
+        if (remapped != null)
+        {
+          // we remapped the in mime-type to the cannonical mime type
+          return remapped.toString();
+        }
+        else
+        {
+          // return the mime-type as is
+          return mimeType;
+        }
+      }
+    }
+
+    // try to determine the mime-type off of the source extension
+    String extension = _getSourceExtension(bean);
+
+    if (extension != null)
+    {
+      // try to map the extension to a mime type
+      Object mimeTypeObject = _sExtensionMap.get(extension);
+
+      if (mimeTypeObject != null)
+      {
+        mimeType = mimeTypeObject.toString();
+
+        if (primaryForced != null)
+        {
+          // merge the primary forced type with the extension mapped secondary
+          // type
+          mimeType = primaryForced + '/' + _getSecondaryContentType(mimeType);
+        }
+      }
+    }
+
+    return mimeType;
+  }
+
+
+  /**
+   * Returns the lowercase extension of any source URL
+   */
+  private String _getSourceExtension(FacesBean bean)
+  {
+    String sourceURLString = getSource(bean);
+
+    if (sourceURLString != null)
+    {
+      int extensionIndex = sourceURLString.lastIndexOf('.');
+
+      if ((extensionIndex != -1) &&
+          (extensionIndex != sourceURLString.length() -1))
+      {
+        return sourceURLString.substring(extensionIndex + 1).toLowerCase();
+      }
+    }
+
+    // no extension
+    return null;
+  }
+
+
+  /**
+   * Initializes a Hashset with the contents of an array
+   */
+  private static HashSet<Object> _createHashSet(
+    Object[] contents
+    )
+  {
+    if (contents != null)
+    {
+      int contentLength = contents.length;
+
+      HashSet<Object> set = 
+        new HashSet<Object>((int)(contentLength * 1.5));
+
+      for (int i = 0; i < contentLength; i++)
+      {
+        set.add(contents[i]);
+      }
+
+      return set;
+    }
+    else
+    {
+      return null;
+    }
+  }
+
+  /**
+   * Initializes a HashMap with the name/value contents of an array
+   */
+  private static HashMap<Object, Object> _createHashMap(
+    Object[] contents
+    )
+  {
+    if (contents != null)
+    {
+      int contentLength = contents.length;
+
+      HashMap<Object, Object> map = 
+        new HashMap<Object, Object>((int)(contentLength * 0.75));
+
+      for (int i = 0; i < contentLength; i += 2)
+      {
+        map.put(contents[i], contents[i + 1]);
+      }
+
+      return map;
+    }
+    else
+    {
+      return null;
+    }
+  }
+
+
+  // get the height of the image window
+  private String _getInnerHeight(
+    FacesBean        bean,
+    boolean          canAutosize,
+    String           primaryContentType,
+    ControlData      controlData,
+    PlayerData       playerData
+    )
+  {
+    // get the height without checking min
+    String height = _getHeightNoMin(bean,
+                                    canAutosize,
+                                    primaryContentType,
+                                    controlData);
+
+
+
+    boolean useMinHeight = (height == null);
+
+    if (!useMinHeight)
+    {
+      int intHeight = _getIntHeight(height);
+
+      // - if intHeight equals Integer.MAX_VALUE then height could not be
+      //   turned to an int, return height
+      // - if intHeight is less than playerData.minHeight.intValue()
+      //   then return player min - contorl data height if possible
+      // - if intHeight is between the player min and Integer.MAX_VALUE
+      //   then return inHeight - control data height
+
+      if (playerData.minHeight != null &&
+          intHeight < playerData.minHeight.intValue())
+      {
+        useMinHeight = true;
+      }
+      else if ( intHeight < Integer.MAX_VALUE )
+      {
+        return IntegerUtils.getInteger(intHeight - controlData.height).toString();
+      }
+    }
+
+    if (useMinHeight)
+    {
+      return IntegerUtils.getInteger(playerData.minHeight.intValue() -
+                                     controlData.height).toString();
+    }
+
+    return height;
+  }
+
+  //
+  // determine the height without checking the min height
+  //
+  private String _getHeightNoMin(
+    FacesBean        bean,
+    boolean          canAutosize,
+    String           primaryContentType,
+    ControlData      controlData
+    )
+  {
+    String height = getHeight(bean);
+    // compute default height for players that don't autosize
+    if (height == null)
+    {
+      // get the inner height from the attribute
+      String innerHeight = getInnerHeight(bean);
+      if (!canAutosize && (innerHeight == null))
+      {
+        // get the default inner height
+        innerHeight = getDefaultInnerHeight(primaryContentType).toString();
+      }
+
+      //
+      // convert from inner height to outer height
+      //
+      int extraHeight = (controlData != null)
+        ? controlData.height
+        : 0;
+
+      if ((innerHeight != null) && (extraHeight != 0))
+      {
+        try
+        {
+          int innerHeightInt = Integer.parseInt(innerHeight);
+          height = Integer.toString(innerHeightInt + extraHeight);
+        }
+        catch (NumberFormatException nfe)
+        {
+          height = innerHeight;
+        }
+      }
+      else
+      {
+        height = innerHeight;
+      }
+    }
+
+    return height;
+  }
+
+
+  //
+  // determine the height including the controls
+  //
+  private String _getHeight(
+    FacesBean        bean,
+    boolean          canAutosize,
+    String           primaryContentType,
+    ControlData      controlData,
+    PlayerData       playerData
+    )
+  {
+
+    // get the height
+    String height = _getHeightNoMin(bean,
+                                    canAutosize,
+                                    primaryContentType,
+                                    controlData);
+
+    //
+    // apply minimum player size to height
+    //
+    if (playerData.minHeight != null)
+    {
+      boolean useMinHeight = (height == null);
+
+      if (!useMinHeight)
+      {
+        int intHeight = _getIntHeight(height);
+
+        useMinHeight = (playerData.minHeight.intValue() > intHeight);
+      }
+
+      if (useMinHeight)
+      {
+        height = playerData.minHeight.toString();
+      }
+    }
+
+    return height;
+  }
+
+  // try to transform height to an int
+  // returns Integer.MAX_VALUE if unable to transform height to an int
+  private int _getIntHeight(
+    Object height
+  )
+  {
+    int intHeight;
+
+    if (height instanceof Number)
+    {
+      intHeight = ((Number)height).intValue();
+    }
+    else
+    {
+      String stringHeight = height.toString();
+
+      // don't parse  0.000000e+000ights
+      if (stringHeight.indexOf('%') == -1)
+      {
+        try
+        {
+          intHeight = new Integer(stringHeight).intValue();
+        }
+        catch (NumberFormatException e)
+        {
+          // not a number
+          intHeight = Integer.MAX_VALUE;
+        }
+      }
+      else
+      {
+        intHeight = Integer.MAX_VALUE;
+      }
+    }
+
+    return intHeight;
+  }
+
+  private void _render(
+    FacesContext     context,
+    RenderingContext  arc,
+    UIComponent      component,
+    FacesBean        bean,
+    String           contentType,
+    String           id,
+    String           wireImageToControls,
+    String           source,
+    String           standbyText,
+    String           width,
+    String           height,
+    String           autostartValue,
+    String           playCountParamName,
+    Object           playCountParamValue,
+    PlayerData       playerData,
+    ControlData      controlData,
+    boolean          useEmbedTag,
+    boolean          useObjectTag,
+    boolean          isImage,
+    boolean          isNotMainID
+    )throws IOException
+  {
+    String elementName = (isImage)
+                             ? "img"
+                             : (useEmbedTag)
+                                 ? "embed"
+                                 : "object";
+
+    // name of attribute to use to write out source URL
+    String sourceAttrName = "src";
+
+    ResponseWriter writer = context.getResponseWriter();
+
+    // start the element
+    writer.startElement(elementName, component);
+    renderAllAttributes(context, arc, bean);
+
+    writer.writeAttribute("width", width, null);
+    writer.writeAttribute("height", height, null);
+
+    if (!isImage)
+    {
+
+      //
+      // <embed> uses direct attributes
+      //
+      if (useEmbedTag)
+      {
+
+        // embed doesn't support id, use name instead
+        writer.writeAttribute("name", id, null );
+
+        // =-= bts, we might only want to do this if the client has specified
+        //     that they want this particular player
+        writer.writeAttribute("type", playerData.playerMimeType, null);
+
+        // location to download new plug-in from
+        writer.writeAttribute("pluginspage", playerData.pluginsPage, null);
+
+        // autostart
+        writer.writeAttribute(playerData.autostartParamName, autostartValue, null);
+
+        // looping
+        writer.writeAttribute(playCountParamName, playCountParamValue, null);
+
+        // wire image window to controls
+        writer.writeAttribute(playerData.wireImageToControlsParamName,
+                              wireImageToControls,
+                              null);
+
+        // add in control attributes
+        if (controlData != null)
+        {
+          String[] paramNameValues = controlData.paramNameValues;
+
+          if (paramNameValues != null)
+          {
+            for (int i = 0; i < paramNameValues.length; i += 2)
+            {
+              writer.writeAttribute(paramNameValues[i], paramNameValues[i+1], null);
+            }
+          }
+        }
+      }
+      else
+      {
+        if (!isNotMainID )
+          writer.writeAttribute("id", id, null);
+
+        // Object tag doesn't take a source attribute
+        sourceAttrName = null;
+
+        // override the content type with a player-specified type
+        // =-= bts What does this do?
+        if (playerData.overrideContentType != null)
+        {
+          contentType = playerData.overrideContentType;
+        }
+
+        // =-= bts maybe we should have a default message
+        writer.writeAttribute("standby", standbyText, null);
+
+        // mime-type of content
+        writer.writeAttribute("type", contentType, null);
+
+        // Class ID
+        writer.writeAttribute("classid", playerData.classID, null);
+
+        // Download location
+        writer.writeAttribute("codebase", playerData.codeBase, null);
+      }
+    }
+
+    // write out the source if any
+    if (sourceAttrName != null)
+    {
+      writer.writeURIAttribute(sourceAttrName, source, null);
+    }
+
+    //
+    // write out Object tag content
+    //
+    if (useObjectTag)
+    {
+      //
+      // render the parameters to the player
+      //
+
+      // source of content
+      _renderParamAttribute(context,
+                            playerData.sourceParamName,
+                            source,
+                            true);
+
+      // autostart
+      _renderParamAttribute(context,
+                            playerData.autostartParamName,
+                            autostartValue,
+                            false);
+
+      // looping
+      _renderParamAttribute(context,
+                            playCountParamName,
+                            playCountParamValue,
+                            false);
+
+      // wire image window to controls
+      if ( playerData.wireImageToControlsParamName != null )
+      {
+        _renderParamAttribute(context,
+                              playerData.wireImageToControlsParamName,
+                              wireImageToControls,
+                              false);
+      }
+
+      // add in control attributes
+      if (controlData != null )
+      {
+        String[] paramNameValues = controlData.paramNameValues;
+
+        if (paramNameValues != null)
+        {
+          for (int i = 0; i < paramNameValues.length; i += 2)
+          {
+            _renderParamAttribute(context,
+                                  paramNameValues[i],
+                                  paramNameValues[i + 1],
+                                  false);
+          }
+        }
+      }
+
+      //
+      // render the link as alternative content
+      //
+      // =-=bts I feel that our backup rendering should be an icon that
+      //        we retrieve using a pretected method
+      //
+      _renderLink(context, arc, component, bean, null, source, null, contentType);
+    }
+
+    // close the element
+    writer.endElement(elementName);
+  }
+
+
+
+  //
+  // known mime types
+  //
+  private static final String _AIFF_MIME_TYPE = "audio/aiff";
+  private static final String _ART_MIME_TYPE = "image/x-art";
+  private static final String _ASF_MIME_TYPE = "video/x-ms-asf";
+  private static final String _AVI_MIME_TYPE = "video/avi";
+  private static final String _BMP_MIME_TYPE = "image/bmp";
+  private static final String _GIF_MIME_TYPE = "image/gif";
+  private static final String _HTML_MIME_TYPE = "text/html";
+  private static final String _IEF_IMAGE_MIME_TYPE = "image/ief";
+  private static final String _JPEG_MIME_TYPE = "image/jpeg";
+  private static final String _MIDI_MIME_TYPE = "audio/mid";
+  private static final String _MPEG_AUDIO_MIME_TYPE = "audio/mpeg";
+  private static final String _MPEG_VIDEO_MIME_TYPE = "video/mpeg";
+  private static final String _MPEG2_VIDEO_MIME_TYPE = "video/x-mpeg2";
+  private static final String _PLAIN_TEXT_MIME_TYPE = "text/plain";
+  private static final String _PORTABLE_ANYMAP_MIME_TYPE = "image/x-portable-anymap";
+  private static final String _PORTABLE_BITMAP_MIME_TYPE = "image/x-portable-bitmap";
+  private static final String _PORTABLE_GRAYMAP_MIME_TYPE = "image/x-portable-graymap";
+  private static final String _PICT_MIME_TYPE = "image/pict";
+  private static final String _PNG_MIME_TYPE = "image/png";
+  private static final String _QUICKTIME_MIME_TYPE = "video/quicktime";
+  private static final String _CMU_RASTER_MIME_TYPE = "image/x-cmu-raster";
+  private static final String _REAL_AUDIO_MIME_TYPE = "audio/x-realaudio";
+  private static final String _REAL_AUDIO_PLUGIN_MIME_TYPE = "audio/x-pn-realaudio-plugin";
+  private static final String _REAL_AUDIO_PN_MIME_TYPE = "audio/x-pn-realaudio";
+  private static final String _REAL_VIDEO_MIME_TYPE = "video/x-realaudio";
+  private static final String _REAL_VIDEO_PLUGIN_MIME_TYPE = "video/x-pn-realaudio-plugin";
+  private static final String _REAL_VIDEO_PN_MIME_TYPE = "video/x-pn-realaudio";
+  private static final String _RGB_MIME_TYPE = "image/x-rgb";
+  private static final String _SGI_MOVIE_MIME_TYPE = "video/x-sgi-movie";
+  private static final String _SMIL_MIME_TYPE = "application/smil";
+  private static final String _TIFF_MIME_TYPE = "image/tiff";
+  private static final String _ULAW_MIME_TYPE = "audio/basic";
+  private static final String _WAV_MIME_TYPE = "audio/wav";
+  private static final String _WMA_MIME_TYPE = "audio/x-ms-wma";
+  private static final String _WMV_MIME_TYPE = "video/x-ms-wmv";
+  private static final String _WVX_MIME_TYPE = "video/x-ms-wvx";
+  private static final String _X_BITMAP_MIME_TYPE = "image/x-xbitmap";
+  private static final String _X_PIXMAP_MIME_TYPE = "image/x-xpixmap";
+  private static final String _X_WINDOW_DUMP_MIME_TYPE = "image/x-xwindowdump";
+
+  // Maps MIME type variants to the cannonical MIME type
+  private static final String[] _MIME_TYPE_REMAPPER = new String[]
+  {
+    "audio/vnd.rn-realaudio", _REAL_AUDIO_PN_MIME_TYPE,
+    "video/vnd.rn-realvideo", _REAL_VIDEO_PN_MIME_TYPE,
+    "audio/x-aiff",           _AIFF_MIME_TYPE,
+    "audio/x-mpeg",           _MPEG_AUDIO_MIME_TYPE,
+    "audio/x-wav",            _WAV_MIME_TYPE,
+    "video/msvideo",          _AVI_MIME_TYPE,
+    "video/x-mpeg",           _MPEG_VIDEO_MIME_TYPE,
+    "video/x-msvideo",        _AVI_MIME_TYPE,
+  };
+
+
+  /**
+   * Maintains attribute and size information for a particular control
+   * configuration.
+   */
+  private static class ControlData
+  {
+    public ControlData(
+      String[] paramNameValues,
+      boolean  canAutosize,
+      int      height,
+      Number   preferredWidth
+      )
+    {
+      if (height < 0)
+        throw new IllegalArgumentException();
+
+       if (preferredWidth.intValue() < 0)
+        throw new IllegalArgumentException();
+
+      this.paramNameValues = paramNameValues;
+      this.canAutosize     = canAutosize;
+      this.height          = height;
+      this.preferredWidth  = preferredWidth;
+    }
+
+    // name values necessary to get to this control state
+    public String[] paramNameValues;
+    public boolean  canAutosize;
+    public int      height;
+    public Number   preferredWidth;
+  }
+
+  /**
+   * Maintains default innersize information and ControlData information
+   * for a set of ControlData's for a primary content type
+   */
+  private static class ControlSet
+  {
+    public ControlSet(
+      Object[] controls
+      )
+    {
+      _controls = _createHashMap(controls);
+    }
+
+    /**
+     * Returns the ControlData Object to use to build up the set of controls
+     * for this player, based on the client-specified set of controls to render.
+     */
+    public MediaRenderer.ControlData getControlData(
+      Object controlValue
+      )
+    {
+      Object controlData = null;
+
+      // get the specified control data
+      if (controlValue != null)
+      {
+        controlData = _controls.get(controlValue.toString());
+      }
+
+      // if we failed for some reason, default to the typical controls
+      if (controlData == null)
+      {
+        controlData = _controls.get(CoreMedia.CONTROLS_TYPICAL);
+      }
+
+      return (ControlData)controlData;
+    }
+
+    private final HashMap<Object, Object> _controls;
+  }
+
+
+  /**
+   * Class containing information about the different players
+   */
+  private static class PlayerData
+  {
+    public PlayerData(
+      String   player,
+      boolean  autostartByDefault,
+      String   autostartTrueValue,
+      String   autostartFalseValue,
+      boolean  canAlwaysAutosize,
+      Number   minHeight,
+      String   autostartParamName,
+      String   sourceParamName,
+      String   infiniteLoopParamName,
+      Object   infiniteLoopParamValue,
+      String   playCountParamName,
+      String   pluginsPage,
+      String   codeBase,
+      String   playerMimeType,
+      String   classID,
+      String   overrideContentType,
+      String   wireImageToControlsParamName,
+      ControlData imageWindowControlData,
+      Object[] controlSets,
+      Object[] unsupportedMimeTypes
+      )
+    {
+      if ((minHeight != null) && (minHeight.intValue() < 0))
+        throw new IllegalArgumentException();
+
+      this.player                 = player;
+      this.autostartByDefault     = autostartByDefault;
+      this.autostartTrueValue     = autostartTrueValue;
+      this.autostartFalseValue    = autostartFalseValue;
+      this.canAlwaysAutosize      = canAlwaysAutosize;
+      this.minHeight              = minHeight;
+      this.autostartParamName     = autostartParamName;
+      this.sourceParamName        = sourceParamName;
+      this.infiniteLoopParamName  = infiniteLoopParamName;
+      this.infiniteLoopParamValue = infiniteLoopParamValue;
+      this.playCountParamName     = playCountParamName;
+      this.pluginsPage            = pluginsPage;
+      this.codeBase               = codeBase;
+      this.classID                = classID;
+      this.playerMimeType         = playerMimeType;
+      this.overrideContentType    = overrideContentType;
+      this.wireImageToControlsParamName = wireImageToControlsParamName;
+
+      _imageWindowControlData = imageWindowControlData;
+      _controlSets = _createHashMap(controlSets);
+      _unsupportedMimeTypes = _createHashSet(unsupportedMimeTypes);
+    }
+
+    public MediaRenderer.ControlData getImageWindowControlData(
+      String primaryContentType
+      )
+    {
+      if ( "video".equals(primaryContentType))
+        return _imageWindowControlData;
+
+      return null;
+    }
+
+    /**
+     * Returns the ControlSet Object to use to build up the set of controls
+     * for this player, based on the primary content MimeType
+     */
+    public MediaRenderer.ControlSet getControlSet(
+      String primaryContentType
+      )
+    {
+      if (_controlSets != null)
+      {
+        Object controls = null;
+
+        // get the primary hashmap
+        if (primaryContentType != null)
+          controls = _controlSets.get(primaryContentType);
+
+        // if we have an unknown primary typoe, try again with video,
+        // which shouldn't fail
+        if (controls == null)
+          controls = _controlSets.get("video");
+
+        return (ControlSet)controls;
+      }
+
+      return null;
+    }
+
+    /**
+     * Returns true if the player supports rendering this format
+     */
+    public boolean isSupportedMimeType(
+      String mimeType
+      )
+    {
+      if ((mimeType != null) && (mimeType.length() != 0))
+      {
+        if (_unsupportedMimeTypes != null)
+        {
+          // extension isn't listed as an unsupported extension
+          return !_unsupportedMimeTypes.contains(mimeType);
+        }
+      }
+
+      return true;
+    }
+
+    public  final String  player;
+    public  final boolean autostartByDefault;
+    public  final String  autostartTrueValue;
+    public  final String  autostartFalseValue;
+    public  final boolean canAlwaysAutosize;
+    public  final Number  minHeight;
+    public  final String  autostartParamName;
+    public  final String  sourceParamName;
+    public  final String  infiniteLoopParamName;
+    public  final Object  infiniteLoopParamValue;
+    public  final String  playCountParamName;
+    public  final String  pluginsPage;
+    public  final String  codeBase;
+    public  final String  playerMimeType;
+    public  final String  classID;
+    public  final String  overrideContentType;
+    public  final String  wireImageToControlsParamName;
+    private final ControlData _imageWindowControlData;
+    private final HashMap<Object, Object> _controlSets;
+    private final HashSet<Object> _unsupportedMimeTypes;
+  }
+
+
+  // Real Player Class ID
+  private static final String _RP_CLASS_ID =
+                                  "clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA";
+
+  // QuickTime class id
+  private static final String _QT_CLASS_ID =
+                                  "clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B";
+
+  private static final String _QT_CODE_BASE =
+                              "http://www.apple.com/qtactivex/qtplugin.cab";
+
+  private static final String _WMP_6_4_CLASS_ID =
+                               "clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95";
+
+  private static final String _WMP_CODE_BASE =
+    "http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,0,02,902";
+
+  private static final Integer _MIN_QT_HEIGHT = 2;
+  private static final int _QT_CONTROL_HEIGHT = 16;
+  private static final int _WMP_CONTROL_HEIGHT = 40;
+
+  //
+  // Meta Data for the Link Player
+  //
+  private static final MediaRenderer.PlayerData _LINK_PLAYER_DATA =
+    new MediaRenderer.PlayerData(CoreMedia.PLAYER_LINK, // player type
+                   false,       // no autostart by default
+                   "true",      // autostartTrueValue
+                   "false",     // autostartFalseValue
+                   true,        // can always autosize
+                   null,        // min player height
+                   null,        // autostartParamName
+                   null,        // sourceParamName
+                   null,        // infiniteLoopParamName,
+                   null,        // infiniteLoopParamValue
+                   null,        // playCountParamName
+                   null,        // pluginsPage URL
+                   null,        // <Object> CodeBase
+                   null,        // playerMimeType
+                   null,        // <Object> ClassID
+                   null,        // overrideContentType
+                   null,        // wireImageToControlsParamName
+                   null,        // imageWindowControlData
+                   null,        // ControlData[]
+                   null);       // Unsupported MimeTypes
+
+  //
+  //
+  private static final MediaRenderer.PlayerData _IMAGE_PLAYER_DATA =
+    new MediaRenderer.PlayerData("image",     // player type
+                   false,       // no autostart by default
+                   "true",      // autostartTrueValue
+                   "false",     // autostartFalseValue
+                   true,        // can always autosize
+                   null,        // min player height
+                   null,        // autostartParamName
+                   null,        // sourceParamName
+                   null,        // infiniteLoopParamName,
+                   null,        // infiniteLoopParamValue
+                   null,        // playCountParamName
+                   null,        // pluginsPage URL
+                   null,        // <Object> CodeBase
+                   null,        // playerMimeType
+                   null,        // <Object> ClassID
+                   null,        // overrideContentType
+                   null,        // wireImageToControlsParamName
+                   null,        // imageWindowControlData
+                   null,        // ControlData[]
+                   null);       // Unsupported MimeTypes
+
+  //
+  // Meta Data for the Quicktime Player
+  //
+
+  // ControlData for the QuickTime all controls case
+  private static final MediaRenderer.ControlData _QUICKTIME_ALL_CONTROL_DATA =
+     new MediaRenderer.ControlData(null,                  // all controls is the default
+                     false,                 // no autosize
+                     _QT_CONTROL_HEIGHT,    // extra height
+                     new Integer(275));     // preferred width
+
+  private static final MediaRenderer.PlayerData _QUICKTIME_PLAYER_DATA =
+    new MediaRenderer.PlayerData(
+    CoreMedia.PLAYER_QUICKTIME,                           // player type
+    true,                                       // autostart by default
+    "true",                                     // autostartTrueValue
+    "false",                                    // autostartFalseValue
+    false,                                      // can't always autosize
+    _MIN_QT_HEIGHT,                             // min player height
+    "autoplay",                                 // autostartParamName
+    "src",                                      // sourceParamName
+    "loop",                                     // infiniteLoopParamName,
+    "true",                                     // infiniteLoopParamValue
+    null,                                       // no loop count support
+    "http://www.apple.com/quicktime/download/", // pluginsPage
+    _QT_CODE_BASE,                              // <Object> CodeBase
+    null,                                       // playerMimeType
+    _QT_CLASS_ID,                               // <Object> ClassID
+    null,                                       // overrideContentType
+    null,                                       // wireImageToControlsParamName
+    null,                                       // imageWindowControlData
+    new Object[]
+    {
+      "audio", new MediaRenderer.ControlSet(new Object[]
+      {
+        CoreMedia.CONTROLS_NONE,         new MediaRenderer.ControlData(new String[]
+                                               {
+                                                 "kioskmode", "true",
+                                                 "controller","false",
+                                               },
+                                               false, // no autosize
+                                               0,
+                                               IntegerUtils.getInteger(0)),
+        CoreMedia.CONTROLS_NONE_VISIBLE, new MediaRenderer.ControlData(new String[]
+                                               {
+                                                 "controller", "false"
+                                               },
+                                               false, // no autosize
+                                               0,
+                                               IntegerUtils.getInteger(0)),
+        CoreMedia.CONTROLS_MINIMAL,      new MediaRenderer.ControlData(null, // all controls default
+                                               false, // no autosize
+                                               _QT_CONTROL_HEIGHT,
+                                               new Integer(18)),  // play button only
+        CoreMedia.CONTROLS_TYPICAL,      _QUICKTIME_ALL_CONTROL_DATA,
+        CoreMedia.CONTROLS_ALL,          _QUICKTIME_ALL_CONTROL_DATA,
+      }),
+      "video", new MediaRenderer.ControlSet(new Object[]
+      {
+        CoreMedia.CONTROLS_NONE,         new MediaRenderer.ControlData(new String[]
+                                               {
+                                                 "kioskmode", "true",
+                                                 "controller","false",
+                                               },
+                                               false, // no autosize
+                                               0,
+                                               IntegerUtils.getInteger(0)),
+        CoreMedia.CONTROLS_NONE_VISIBLE, new MediaRenderer.ControlData(new String[]
+                                               {
+                                                 "controller", "false"
+                                               },
+                                               false, // no autosize
+                                               0,
+                                               IntegerUtils.getInteger(0)),
+        CoreMedia.CONTROLS_MINIMAL,      _QUICKTIME_ALL_CONTROL_DATA,
+        CoreMedia.CONTROLS_TYPICAL,      _QUICKTIME_ALL_CONTROL_DATA,
+        CoreMedia.CONTROLS_ALL,          _QUICKTIME_ALL_CONTROL_DATA,
+      }),
+    },
+    new String[] // mime-types not supported by Quicktime 5
+    {
+      _WMA_MIME_TYPE,
+      _WMV_MIME_TYPE,
+      _REAL_AUDIO_MIME_TYPE,
+      _REAL_AUDIO_PN_MIME_TYPE,
+      _REAL_AUDIO_PLUGIN_MIME_TYPE,
+      _REAL_VIDEO_MIME_TYPE,
+      _REAL_VIDEO_PN_MIME_TYPE,
+      _REAL_VIDEO_PLUGIN_MIME_TYPE,
+    });
+
+
+  //
+  // Meta Data for the Windows Media Player 6.4
+  //
+
+  // preferred width of WMP showing all controls
+  private static final Number _WMP_ALL_CONTROLS_WIDTH = new Integer(275);
+
+  private static final Number _WMP_MINIMAL_CONTROLS_WIDTH =
+                                                IntegerUtils.getInteger(72);
+  private static final int _WMP_MINIMAL_CONTROLS_HEIGHT = 21;
+  private static final int _WMP_ALL_CONTROLS_HEIGHT = 170;
+
+  // control data for showing no visible controls on Windows Meida Player 6.4
+  private static final MediaRenderer.ControlData _WMP_6_4_NONE_VISIBLE_CONTROL_DATA =
+     new MediaRenderer.ControlData(new String[]
+                     {
+                       "showcontrols", "false"
+                     },
+                     true, // autosizes
+                     0,
+                     IntegerUtils.getInteger(0));
+
+  // =-= bts what about close captioning?
+  // =-= bts Is unsupported mime types the right way to go, how about supported
+  //         mimetypes instead?
+
+  //
+  // ControlSet shared by all primary content types on WMP 6.4
+  //
+  private static final MediaRenderer.ControlSet _WINDOWS_6_4_CONTROL_SET = new MediaRenderer.ControlSet(
+    new Object[]
+    {
+      CoreMedia.CONTROLS_NONE,         _WMP_6_4_NONE_VISIBLE_CONTROL_DATA,
+      CoreMedia.CONTROLS_NONE_VISIBLE, _WMP_6_4_NONE_VISIBLE_CONTROL_DATA,
+      CoreMedia.CONTROLS_MINIMAL,      new MediaRenderer.ControlData(new String[]
+                                             {
+                                               "showcontrols",         "true",
+                                               "showaudiocontrols",    "false",
+                                               "showpositioncontrols", "false",
+                                               "showtracker",          "false",
+                                             },
+                                             false, // no autosize
+                                             _WMP_MINIMAL_CONTROLS_HEIGHT,
+                                             _WMP_MINIMAL_CONTROLS_WIDTH),
+      CoreMedia.CONTROLS_TYPICAL,      new MediaRenderer.ControlData(null,// this is the default
+                                             true, // autosizes
+                                             _WMP_CONTROL_HEIGHT,
+                                             _WMP_ALL_CONTROLS_WIDTH),
+      CoreMedia.CONTROLS_ALL,          new MediaRenderer.ControlData(new String[]
+                                             {
+                                               "showdisplay",   "true",
+                                               "showgotobar",   "true",
+                                               "showstatusbar", "true",
+                                             },
+                                             true, // autosizes
+                                             _WMP_ALL_CONTROLS_HEIGHT,
+                                             _WMP_ALL_CONTROLS_WIDTH),
+    });
+
+  private static final MediaRenderer.PlayerData _WINDOWS_6_4_PLAYER_DATA =
+    new MediaRenderer.PlayerData(
+    CoreMedia.PLAYER_WINDOWS,                        // player type
+    true,                                            // autostart by default
+    "1",                                             // autostartTrueValue
+    "0",                                             // autostartFalseValue
+    false,                                           // can't always autosize
+    null,                                            // min player height
+    "autostart",                                     // autostartParamName
+    "filename",                                      // sourceParamName
+    "playcount",                                     // infiniteLoopParamName,
+    IntegerUtils.getInteger(0),                                            // infiniteLoopParamValue
+    "playcount",                                     // playCountParamName
+    "http://www.microsoft.com/Windows/MediaPlayer/", // pluginsPage
+    _WMP_CODE_BASE,                                  // <Object> CodeBase
+    "application/x-mplayer2",                        // playerMimeType
+    _WMP_6_4_CLASS_ID,                               // <Object> ClassID
+    "application/x-oleobject",                       // overrideContentType
+    null,                                            // wireImageToControlsParamName
+    null,                                            // imageWindowControlData
+    new Object[]
+    {
+      "audio", _WINDOWS_6_4_CONTROL_SET,
+      "video", _WINDOWS_6_4_CONTROL_SET,
+    },
+    new String[] // mime-types not supported by Windows Media Player 6.4
+    {
+      _QUICKTIME_MIME_TYPE,
+      _REAL_AUDIO_MIME_TYPE,
+      _REAL_AUDIO_PN_MIME_TYPE,
+      _REAL_AUDIO_PLUGIN_MIME_TYPE,
+      _REAL_VIDEO_MIME_TYPE,
+      _REAL_VIDEO_PN_MIME_TYPE,
+      _REAL_VIDEO_PLUGIN_MIME_TYPE,
+    });
+
+  //
+  // Meta Data for the Windows Media Player 7.1
+  //
+
+  /* WMP 7.1 is not currently activated in any way in this class.
+  private static final String _WMP_7_1_CLASS_ID =
+                               "clasid:6BF52A52-394A-11D3-B153-00C04F79FAA6";
+
+
+  // control data for showing no visible controls on Windows Media Player 7.1
+  private static final MediaRenderer.ControlData _WMP_7_1_NONE_VISIBLE_CONTROL_DATA =
+     new MediaRenderer.ControlData(new String[]{"uimode", "none"},
+                     true, // autosizes
+                     0,
+                     IntegerUtils.getInteger(0));
+
+  // control data for showing typical controls on Windows Media Player 7.1
+  private static final MediaRenderer.ControlData _WMP_7_1_TYPICAL_CONTROL_DATA =
+     new MediaRenderer.ControlData(null,// typical is the default
+                     true, // autosizes
+                     _WMP_CONTROL_HEIGHT,
+                     _WMP_ALL_CONTROLS_WIDTH);
+
+  //
+  // ControlSet shared by all primary content types on WMP 7.1
+  //
+  private static final MediaRenderer.ControlSet _WINDOWS_7_1_CONTROL_SET = new MediaRenderer.ControlSet(
+    new Object[]
+    {
+      CoreMedia.CONTROLS_NONE,         _WMP_7_1_NONE_VISIBLE_CONTROL_DATA,
+      CoreMedia.CONTROLS_NONE_VISIBLE, _WMP_7_1_NONE_VISIBLE_CONTROL_DATA,
+      CoreMedia.CONTROLS_MINIMAL,      new MediaRenderer.ControlData(new String[]{"uimode", "mini"},
+                                             true, // autosizes
+                                             _WMP_CONTROL_HEIGHT,
+                                             _WMP_ALL_CONTROLS_WIDTH),
+      CoreMedia.CONTROLS_TYPICAL,      _WMP_7_1_TYPICAL_CONTROL_DATA,
+      CoreMedia.CONTROLS_ALL,          _WMP_7_1_TYPICAL_CONTROL_DATA,
+    });
+
+  private static final MediaRenderer.PlayerData _WINDOWS_7_1_PLAYER_DATA =
+    new MediaRenderer.PlayerData(
+    CoreMedia.PLAYER_WINDOWS,                                  // player type
+    true,                                            // autostart by default
+    "1",                                             // autostartTrueValue
+    "0",                                             // autostartFalseValue
+    true,                                            // can always autosize
+    null,                                            // min player height
+    "autostart",                                     // autostartParamName
+    "filename",                                      // sourceParamName
+    "playcount",                                     // infiniteLoopParamName,
+    IntegerUtils.getInteger(0),                                            // infiniteLoopParamValue
+    "playcount",                                     // playCountParamName
+    "http://www.microsoft.com/Windows/MediaPlayer/", // pluginsPage
+    _WMP_CODE_BASE,                                  // <Object> CodeBase
+    "application/x-mplayer2",                        // playerMimeType
+    _WMP_7_1_CLASS_ID,                               // <Object> ClassID
+    "application/x-oleobject",                       // overrideContentType
+    null,                                            // wireImageToControlsParamName
+    null,                                            // imageWindowControlData
+    new Object[]
+    {
+      "audio", _WINDOWS_7_1_CONTROL_SET,
+      "video", _WINDOWS_7_1_CONTROL_SET,
+    },
+    new String[] // mime-types not supported by Windows Media Player 7.0.1
+    {
+      _QUICKTIME_MIME_TYPE,
+      _QUICKTIME_MIME_TYPE,
+      _REAL_AUDIO_MIME_TYPE,
+      _REAL_AUDIO_PN_MIME_TYPE,
+      _REAL_AUDIO_PLUGIN_MIME_TYPE,
+      _REAL_VIDEO_MIME_TYPE,
+      _REAL_VIDEO_PN_MIME_TYPE,
+      _REAL_VIDEO_PLUGIN_MIME_TYPE,
+   });
+  */
+
+  //
+  // Meta Data for the Real Player
+  //
+  private static final Number _REAL_MINIMAL_WIDTH  = new Integer(44);
+  private static final int    _REAL_MINIMAL_HEIGHT = 26;
+
+  private static final Number _REAL_TYPICAL_WIDTH  = new Integer(220);
+  private static final int    _REAL_TYPICAL_HEIGHT = 36;
+
+  private static final Number _REAL_ALL_WIDTH  = new Integer(375);
+  private static final int    _REAL_ALL_HEIGHT = 100;
+
+
+ // null control data
+  private static final MediaRenderer.ControlData _NULL_CONTROL_DATA =
+     new MediaRenderer.ControlData(null,
+                     false,           // no autosize
+                     0,
+                     IntegerUtils.getInteger(0));
+
+
+
+  // control data for showing image window on Real Player
+  private static final MediaRenderer.ControlData _REAL_VIDEO_IMAGE_WINDOW_CONTROL_DATA =
+     new MediaRenderer.ControlData(new String[]
+                     {
+                        "controls", "ImageWindow",
+                        "maintainAspect", "true"
+                     },
+                     false,           // no autosize
+                     0,
+                     IntegerUtils.getInteger(0));
+
+
+
+  private static final MediaRenderer.ControlData _REAL_MINIMAL_CONTROL_DATA =
+  new MediaRenderer.ControlData(new String[]
+                               {
+                                 "controls", "PlayButton"
+                               },
+                               false,           // no autosize
+                               _REAL_MINIMAL_HEIGHT,
+                               _REAL_MINIMAL_WIDTH);
+
+
+  // control data for showing typical controls on Real Player
+  private static final MediaRenderer.ControlData _REAL_TYPICAL_CONTROL_DATA =
+     new MediaRenderer.ControlData(new String[]{"controls", "ControlPanel"},
+                     false,           // no autosize
+                     _REAL_TYPICAL_HEIGHT,
+                     _REAL_TYPICAL_WIDTH);
+
+
+
+  // control data for showing all controls on Real Player
+  private static final MediaRenderer.ControlData _REAL_ALL_CONTROL_DATA =
+     new MediaRenderer.ControlData(new String[]{"controls", "All"},
+                     false,           // no autosize
+                     _REAL_ALL_HEIGHT,
+                     _REAL_ALL_WIDTH);
+
+  private static final MediaRenderer.ControlData _REAL_AUDIO_NONE_VISIBLE_CONTROL_DATA =
+     new MediaRenderer.ControlData(new String[]{"controls", ""},
+                     false,           // no autosize
+                     0,
+                     IntegerUtils.getInteger(0));
+
+
+  private static final MediaRenderer.PlayerData _REAL_PLAYER_DATA =
+    new MediaRenderer.PlayerData(
+    CoreMedia.PLAYER_REAL,                      // player type
+    false,                                      // no autostart by default
+    "true",                                     // autostartTrueValue
+    "false",                                    // autostartFalseValue
+    false,                                      // can't always autosize
+    null,                                       // min player height
+    "autostart",                                // autostartParamName
+    "src",                                      // sourceParamName
+    "loop",                                     // infiniteLoopParamName,
+    "true",                                     // infiniteLoopParamValue
+    "numloop",                                  // playCountParamName
+    "http://www.real.com/player/",              // pluginsPage
+    "http://www.real.com/player/",              // <Object> CodeBase
+    "audio/x-pn-realaudio-plugin",              // playerMimeType
+    _RP_CLASS_ID,                               // <Object> ClassID
+    null,                                       // overrideContentType
+    "console",                                  // wireImageToControlsParamName
+    _REAL_VIDEO_IMAGE_WINDOW_CONTROL_DATA,  // imageWindowControlData
+    new Object[]
+    {
+      "audio", new MediaRenderer.ControlSet(new Object[]
+      {
+        CoreMedia.CONTROLS_NONE,         _REAL_AUDIO_NONE_VISIBLE_CONTROL_DATA,
+        CoreMedia.CONTROLS_NONE_VISIBLE, _REAL_AUDIO_NONE_VISIBLE_CONTROL_DATA,
+        CoreMedia.CONTROLS_MINIMAL,      _REAL_MINIMAL_CONTROL_DATA,
+        CoreMedia.CONTROLS_TYPICAL,      _REAL_TYPICAL_CONTROL_DATA,
+        CoreMedia.CONTROLS_ALL,          _REAL_ALL_CONTROL_DATA,
+      }),
+      "video", new MediaRenderer.ControlSet(new Object[]
+      {
+        CoreMedia.CONTROLS_NONE,         _NULL_CONTROL_DATA,
+        CoreMedia.CONTROLS_NONE_VISIBLE, _NULL_CONTROL_DATA,
+        CoreMedia.CONTROLS_MINIMAL,      _REAL_MINIMAL_CONTROL_DATA,
+        CoreMedia.CONTROLS_TYPICAL,      _REAL_TYPICAL_CONTROL_DATA,
+        CoreMedia.CONTROLS_ALL,          _REAL_ALL_CONTROL_DATA,
+      }),
+    },
+    null); // mime types not supported by real
+
+  private static final Object[] _PLAYER_DATA = new Object[]
+  {
+    CoreMedia.PLAYER_LINK,      _LINK_PLAYER_DATA,
+    CoreMedia.PLAYER_QUICKTIME, _QUICKTIME_PLAYER_DATA,
+    CoreMedia.PLAYER_WINDOWS,   _WINDOWS_6_4_PLAYER_DATA,
+    CoreMedia.PLAYER_REAL,      _REAL_PLAYER_DATA,
+  };
+
+  // maps extensions to MIME types
+  private static final String[] _EXTENSION_TO_MIME_TYPE = new String[]
+  {
+    "aif",  _AIFF_MIME_TYPE,
+    "aifc", _AIFF_MIME_TYPE,
+    "aiff", _AIFF_MIME_TYPE,
+    "art",  _ART_MIME_TYPE,
+    "asf",  _ASF_MIME_TYPE,
+    "asx",  _ASF_MIME_TYPE,
+    "au",   _ULAW_MIME_TYPE,
+    "avi",  _AVI_MIME_TYPE,
+    "bmp",  _BMP_MIME_TYPE,
+    "gif",  _GIF_MIME_TYPE,
+    "htm",  _HTML_MIME_TYPE,
+    "html", _HTML_MIME_TYPE,
+    "ief",  _IEF_IMAGE_MIME_TYPE,
+    "jfif", _JPEG_MIME_TYPE,
+    "jpe",  _JPEG_MIME_TYPE,
+    "jpg",  _JPEG_MIME_TYPE,
+    "jpeg", _JPEG_MIME_TYPE,
+    "kar",  _MIDI_MIME_TYPE,
+    "m15",  _MPEG_VIDEO_MIME_TYPE,
+    "m75",  _MPEG_VIDEO_MIME_TYPE,
+    "m1a",  _MPEG_VIDEO_MIME_TYPE,
+    "m1s",  _MPEG_VIDEO_MIME_TYPE,
+    "m1v",  _MPEG_VIDEO_MIME_TYPE,
+    "mid",  _MIDI_MIME_TYPE,
+    "midi", _MIDI_MIME_TYPE,
+    "mov",  _QUICKTIME_MIME_TYPE,
+    "movie",_SGI_MOVIE_MIME_TYPE,
+    "mpe",  _MPEG_VIDEO_MIME_TYPE,
+    "mpg",  _MPEG_VIDEO_MIME_TYPE,
+    "mpga", _MPEG_AUDIO_MIME_TYPE,
+    "mpeg", _MPEG_VIDEO_MIME_TYPE,
+    "mp2",  _MPEG_AUDIO_MIME_TYPE,
+    "mp3",  _MPEG_AUDIO_MIME_TYPE,
+    "mpa",  _MPEG_AUDIO_MIME_TYPE,
+    "mpm",  _MPEG_AUDIO_MIME_TYPE,
+    "mp2v", _MPEG2_VIDEO_MIME_TYPE,
+    "mpv2", _MPEG2_VIDEO_MIME_TYPE,
+    "pbm",  _PORTABLE_BITMAP_MIME_TYPE,
+    "pgm",  _PORTABLE_GRAYMAP_MIME_TYPE,
+    "pnm",  _PORTABLE_ANYMAP_MIME_TYPE,
+    "pic",  _PICT_MIME_TYPE,
+    "pict", _PICT_MIME_TYPE,
+    "png",  _PNG_MIME_TYPE,
+    "qt",   _QUICKTIME_MIME_TYPE,
+    "ra",   _REAL_AUDIO_MIME_TYPE,
+    "ram",  _REAL_AUDIO_PN_MIME_TYPE,
+    "ras",  _CMU_RASTER_MIME_TYPE,
+    "rgb",  _RGB_MIME_TYPE,
+    "rm",   _REAL_AUDIO_PN_MIME_TYPE,
+    "rpg",  _REAL_AUDIO_PLUGIN_MIME_TYPE,
+    "rpm",  _REAL_AUDIO_PLUGIN_MIME_TYPE,
+    "rv",   _REAL_VIDEO_MIME_TYPE,
+    "smf",  _MIDI_MIME_TYPE,
+    "smi",  _SMIL_MIME_TYPE,
+    "smil", _SMIL_MIME_TYPE,
+    "snd",  _ULAW_MIME_TYPE,
+    "tif",  _TIFF_MIME_TYPE,
+    "tiff", _TIFF_MIME_TYPE,
+    "txt",  _PLAIN_TEXT_MIME_TYPE,
+    "ulw",  _ULAW_MIME_TYPE,
+    "wav",  _WAV_MIME_TYPE,
+    "wma",  _WMA_MIME_TYPE,
+    "wmv",  _WMV_MIME_TYPE,
+    "wvx",  _WVX_MIME_TYPE,
+    "xbm",  _X_BITMAP_MIME_TYPE,
+    "xpm",  _X_PIXMAP_MIME_TYPE,
+    "xwd",  _X_WINDOW_DUMP_MIME_TYPE,
+  };
+
+
+
+  // Preferred Players for MimeTypes
+  private static final Object[] _PREFERRED_MIME_PLAYERS = new Object[]
+  {
+    _AIFF_MIME_TYPE,              CoreMedia.PLAYER_QUICKTIME,
+    _ASF_MIME_TYPE,               CoreMedia.PLAYER_WINDOWS,
+    _AVI_MIME_TYPE,               CoreMedia.PLAYER_WINDOWS,
+    _QUICKTIME_MIME_TYPE,         CoreMedia.PLAYER_QUICKTIME,
+    _REAL_AUDIO_MIME_TYPE,        CoreMedia.PLAYER_REAL,
+    _REAL_AUDIO_PN_MIME_TYPE,     CoreMedia.PLAYER_REAL,
+    _REAL_AUDIO_PLUGIN_MIME_TYPE, CoreMedia.PLAYER_REAL,
+    _REAL_VIDEO_MIME_TYPE,        CoreMedia.PLAYER_REAL,
+    _REAL_VIDEO_PN_MIME_TYPE,     CoreMedia.PLAYER_REAL,
+    _REAL_VIDEO_PLUGIN_MIME_TYPE, CoreMedia.PLAYER_REAL,
+    _WMA_MIME_TYPE,               CoreMedia.PLAYER_WINDOWS,
+    _WMV_MIME_TYPE,               CoreMedia.PLAYER_WINDOWS,
+    _WVX_MIME_TYPE,               CoreMedia.PLAYER_WINDOWS,
+  };
+
+  //
+  // Object constants for OS's
+  //
+  private static final Integer _WINDOWS_OS =
+                                  IntegerUtils.getInteger(TrinidadAgent.OS_WINDOWS);
+
+  private static final Integer _MAC_OS =
+                                  IntegerUtils.getInteger(TrinidadAgent.OS_MACOS);
+
+  private static final Integer _SOLARIS_OS =
+                                  IntegerUtils.getInteger(TrinidadAgent.OS_SOLARIS);
+
+  // Preferred Players for Operating Systems
+  /* CURRENTLY UNUSED
+  private static final Object[] _PREFERRED_OS_PLAYERS = new Object[]
+  {
+    _WINDOWS_OS, PLAYER_WINDOWS,
+    _MAC_OS,     PLAYER_QUICKTIME,
+    _SOLARIS_OS, PLAYER_WINDOWS,
+  };
+  */
+
+  // Supported players on each OS, in prference order
+  private static final Object[] _SUPPORTED_OS_PLAYERS = new Object[]
+  {
+    _WINDOWS_OS, new Object[]{CoreMedia.PLAYER_WINDOWS,  
+                              CoreMedia.PLAYER_QUICKTIME,
+                              CoreMedia.PLAYER_REAL},
+    _MAC_OS,     new Object[]{CoreMedia.PLAYER_QUICKTIME,
+                              CoreMedia.PLAYER_WINDOWS,
+                              CoreMedia.PLAYER_REAL},
+    _SOLARIS_OS, new Object[]{CoreMedia.PLAYER_WINDOWS},
+  };
+
+  //
+  // default sizes for different primary mime types
+  //
+  private static Object[] _DEFAULT_INNER_SIZES = new Object[]
+  {
+    "audio", new Number[]{IntegerUtils.getInteger(0),
+                          IntegerUtils.getInteger(0)},
+    "video", new Number[]{IntegerUtils.getInteger(200),
+                          IntegerUtils.getInteger(150)},
+  };
+
+  private static final int _DEFAULT_INNER_WIDTH_INDEX  = 0;
+  private static final int _DEFAULT_INNER_HEIGHT_INDEX = 1;
+
+
+  // local property for the player identification information
+  private static final Object _PLAYER_DATA_KEY = new Object();
+
+  // map of mime types to preferred players
+  private static HashMap<Object, Object> _sPreferredMimePlayers;
+
+  // map of Operating Systems to preferred players
+  private static HashMap<Integer, String> _sPreferredOSPlayers;
+
+  // map of Operating Systems to HashSet of supported players
+  private static HashMap<Integer, HashSet<Object>> _sSupportedOSPlayers;
+
+  // map the in mime type to the cannonical mime type
+  private static HashMap<Object, Object>  _sMimeTypeRemapper;
+
+  // maps the extension to the mime type
+  private static HashMap<Object, Object> _sExtensionMap;
+
+  // maps a player name to its player data
+  private static HashMap<Object, Object> _sPlayerData;
+
+  // maps a primary content type to a default inner size
+  private static HashMap<Object, Object> _sDefaultInnerSizes;
+
+  static
+  {
+    // initialize data for supported players
+    _sPlayerData =  _createHashMap(_PLAYER_DATA);
+
+    // initialize the mapping of mime types to preferred players
+    _sPreferredMimePlayers = _createHashMap(_PREFERRED_MIME_PLAYERS);
+
+    //
+    // create the set of all OS's that have players.  The first player
+    // listed is the preferred player for that OS.
+    //
+    int supportedOSPlayersLength = _SUPPORTED_OS_PLAYERS.length;
+    int hashSize = (int)(supportedOSPlayersLength * 0.75);
+
+    _sSupportedOSPlayers = new HashMap<Integer, HashSet<Object>>(hashSize);
+    _sPreferredOSPlayers = new HashMap<Integer, String>(hashSize);
+
+    for (int i = 0; i < supportedOSPlayersLength; i += 2)
+    {
+      Integer  os      = (Integer)_SUPPORTED_OS_PLAYERS[i];
+      Object[] players = (Object[])_SUPPORTED_OS_PLAYERS[i + 1];
+
+      if ((players != null) && (players.length > 0))
+      {
+        // add the players for this OS to the mapping of OSs to
+        // player sets
+        _sSupportedOSPlayers.put(os, _createHashSet(players));
+
+        // record the preferred player for this OS
+        _sPreferredOSPlayers.put(os, (String)players[0]);
+      }
+    }
+
+    // initialize the mime type remapper
+    _sMimeTypeRemapper = _createHashMap(_MIME_TYPE_REMAPPER);
+
+    // initialize the extension map
+    _sExtensionMap = _createHashMap(_EXTENSION_TO_MIME_TYPE);
+
+    // initialize the map of default inner sizes
+    _sDefaultInnerSizes = _createHashMap(_DEFAULT_INNER_SIZES);
+  }
+
+  private PropertyKey _sourceKey;
+  private PropertyKey _playerKey;
+  private PropertyKey _contentTypeKey;
+  private PropertyKey _autostartKey;
+  private PropertyKey _playCountKey;
+  private PropertyKey _controlsKey;
+  private PropertyKey _standbyTextKey;
+  private PropertyKey _widthKey;
+  private PropertyKey _heightKey;
+  private PropertyKey _innerWidthKey;
+  private PropertyKey _innerHeightKey;
+}