- documentation for the Media handling interface. See MirMedia.java and
authormh <mh>
Wed, 10 Oct 2001 02:01:11 +0000 (02:01 +0000)
committermh <mh>
Wed, 10 Oct 2001 02:01:11 +0000 (02:01 +0000)
MediaHandler*
- makes ProducerTopics media aware. (i.e convert to the media interface)
- make the right hand summary of the startpage *only* display newswire items
  not sure if this is a bug fix or a feature addition/removal.

source/mir/media/MediaHandlerAudio.java
source/mir/media/MediaHandlerGeneric.java
source/mir/media/MediaHandlerImages.java
source/mir/media/MediaHandlerImagesGif.java
source/mir/media/MediaHandlerImagesJpeg.java
source/mir/media/MirMedia.java
source/mircoders/producer/ProducerStartPage.java
source/mircoders/producer/ProducerTopics.java
source/mircoders/servlet/ServletModuleOpenIndy.java
templates-dist/producer/topiclist.template

index dc3e08b..4be2dd5 100755 (executable)
@@ -13,11 +13,12 @@ import mir.storage.*;
 
 
 /**
- * Interfacedefinition für Datenbank-Adpatoren. Die Adaptoren legen
- * jeweils das Verhalten und die Befehlsmächtigkeit der Datenbank
- * fest.
+ * Handles audio media, like mp3 and maybe it could also handle some other.
+ * It is MediaHandlerGeneric with different icons.
  *
- * @author <mh>
+ * @see mir.media.MediaHandlerGeneric
+ * @see mir.media.MirMedia
+ * @author mh <heckmann@hbe.ca>
  * @version 24.09.2001
  */
 
index 253d871..1710c95 100755 (executable)
@@ -13,11 +13,22 @@ import mir.storage.*;
 
 
 /**
- * Interfacedefinition für Datenbank-Adpatoren. Die Adaptoren legen
- * jeweils das Verhalten und die Befehlsmächtigkeit der Datenbank
- * fest.
+ * This is the Generic MediaHandler. It stores the media data on
+ * the filesystem and keeps basic metadata  (size, type...) in the
+ * DB. Usually only representation needs to be overridden.
+ * See the MediaHandlerAudio class to see an example of how one
+ * could override it.
+ * <p>
+ * Most media handlers should override this class.
+ * <p>
+ * In theory, it could be used to handle miscellaneous media that
+ * we don't have entered in the media_type table, (like RTF documents,
+ * PS, PDF, etc..)
+ * <p>
+ * Of course it implements the MirMedia interface.
  *
- * @author <mh>
+ * @see mir.media.MirMedia
+ * @author mh <heckmann@hbe.ca>
  * @version 24.09.2001
  */
 
index aa62a26..2e3ffb5 100755 (executable)
@@ -11,12 +11,18 @@ import mir.entity.*;
 
 /**
  * This class handles saving, fetching creating representations
- * for all images.
- *
+ * for all images. The image content is stored in the DB. The content is
+ * written out to a file at the ProducerImages level.
+ * Remember that Handlers for specific image types, Gif, Jpeg, etc..
+ * should override it.
+ * It implements the MirMedia interface.
+ * <p>
  * ok. this is a big hack, it's cause putting the image in the DB
  * and fetching it from the DB needs low level db connections for
- * some reason. -mh 25.09.2001
+ * some reason. Does anyone know how to get around this?
+ * -mh 25.09.2001
  *
+ * @see mir.media.MirMedia
  * @author mh
  * @version 24.09.2001
  */
index b25058d..0b22412 100755 (executable)
@@ -10,8 +10,10 @@ import mir.entity.*;
 
 /**
  * This class handles saving, fetching creating representations
- * for gif images.
+ * for gif images. it overrides MediaHandlerImages.
  *
+ * @see mir.media.MediaHandlerImages
+ * @see mir.media.MirMedia
  * @author mh
  * @version 24.09.2001
  */
index 283e827..ff01abc 100755 (executable)
@@ -10,8 +10,10 @@ import mir.entity.*;
 
 /**
  * This class handles saving, fetching creating representations
- * for jpeg images.
+ * for jpeg images. it overrides MediaHandlerImages.
  *
+ * @see mir.media.MediaHandlerImages
+ * @see mir.media.MirMedia
  * @author mh <heckmann@hbe.ca>
  * @version 24.09.2001
  */
index 34beee9..2a3a9b6 100755 (executable)
@@ -1,5 +1,6 @@
 /*
  * put your module comment here
+ *
  */
 
 
@@ -10,32 +11,201 @@ import java.util.*;
 import mir.entity.*;
 
 /**
- * Interfacedefinition für Datenbank-Adpatoren. Die Adaptoren legen
- * jeweils das Verhalten und die Befehlsmächtigkeit der Datenbank
- * fest.
- *
- * @author <mh>
+ * Interface for Media handling in Mir. All media handlers
+ * must implement this interface. Each specific media type,
+ * be it Gif, Jpeg, Mp3 audio, Real Audio or quicktime video
+ * has special needs when it comes to representation on the various
+ * pages (article, list, summary), must be stored differently and has a 
+ * different URL, etc... This interface allows Mir to support 
+ * an infinite (I hope) number of media types. Once this is done,
+ * no code at any other level in Mir needs to be changed other than
+ * adding the content-type <-> media handler name mapping in the
+ * media_type table. The following is an example of the media_type
+ * table:
+ * <p>
+ * id |  name   |        mime_type         | classname |   tablename   | dcname<br>
+ *---+---------+--------------------------+-----------+---------------+-------<br>
+ *  2 | unknown | application/octet-stream | --        | UploadedMedia | <br>
+ *  3 | jpg     | image/gif                | ImagesGif | Images        | <br>
+ *  4 | mp3     | audio/mp3                | Audio     | UploadedMedia | <br>
+ * <p>
+ * The "id" field is used as a mapping in the table that contains the media type
+ * to the media_type table. For example, the images table has a to_media_type
+ * field that contains the id in the media_type table.
+ * <p>
+ * The "name" field is used for various display/filenaming purposes. it should
+ * match a valid file extension name for a media_type (we could have used the
+ * content-type map for this....). 
+ * <p>
+ * The "mime_type" field is the most important as it does maps the type to Java
+ * classes (the storage and media_handler name). We call those classes using
+ * reflection. This way, once a Handler for a specific media type is implemented
+ * and entered into the media_type table, no other Mir code needs to be modified.
+ * <p>
+ * The "classname" field is the name of the media handler (e.g MediaHandlerAudio)
+ * we use it to call the MediaHandler methods via reflection.
+ * <p>
+ * The "tablename" is the name of the database storage classes (e.g DatabaseImages
+ * and EntityImages). We use this to fetch/storage the media (meta)data in the db.
+ * <p?
+ * The "dcname" field is as of yet unused. Do search for "Dublin Core" on google
+ * to learn more.
+ * <p>
+ * Most media handlers should just extend MediaHandlerGeneric (i.e inherit from
+ * ) and just override the things that need to be specific. see MediaHandlerAudio
+ * 
+ * @author mh <heckmann@hbe.ca>
  * @version 24.09.2001
  */
 
 public interface  MirMedia{
 
-        /* Liefert den Namen der Adaptorklasse
-        * @return Adaptorklasse als String
-        */
+  /**
+   * Takes the uploaded media data itself, along with the media Entity
+   * which contains the Media metadata plus the MediaType entity containing
+   * all the info for the specific media type itself. It's job is store the
+   * Media data (content) itself, this could be on the local filesystem, in the
+   * DB or even on a remote host. It then inserts the MetaData in the DB.
+   * @param uploadedData, a byte array containing the uploaded data.
+   * @param ent, an Entity holding the media MetaData
+   * @param mediaType, an Entity holding the media_table entry
+   * @return boolean, success/fail
+   * @see mir.entity.Entity
+   */
        public abstract boolean set (byte[] uploadedData, Entity ent, Entity mediaTypeEnt );
+
+  /**
+   * Get's the media data from storage and returns it as a byte array
+   * Not very useful for most media types as they are stored in a file,
+   * but very usefull for ones stored in the DB as it is necessary to get
+   * it first before making a file out of it (in Producer*).
+   * @param ent, an Entity holding the media MetaData
+   * @param mediaType, an Entity holding the media_table entry
+   * @return byte[]
+   * @see mir.entity.Entity
+   */
        public abstract byte[] get (Entity ent, Entity mediaTypeEnt);
+
+  /**
+   * Pretty much like get() above. But get's the specific Icon
+   * representation. useful for media stored in the DB.
+   * @param ent, an Entity holding the media MetaData
+   * @return byte[]
+   * @see mir.entity.Entity
+   */
        public abstract byte[] getIcon (Entity ent);
-       public abstract String getURL (Entity ent, Entity mediaTypeEnt);
-       public abstract String getListView (Entity ent, Entity mediaTypeEnt);
-       public abstract String getStoragePath ();
+
+       /**
+   * gets the final content representation for the media
+   * in the form of a URL (String) that allows someone to 
+   * download, look at or listen to the media. (HREF, img src
+   * streaming link, etc..)
+   * It should use the helper functions in the StringUtil class to
+   * build URL's safely, eliminating any *illegal* user input.
+   * @param ent, an Entity holding the media MetaData
+   * @param mediaTypeEnt, an Entity holding the media_table entry
+   * @return String, the url.
+   * @see mir.entity.Entity
+   * @see mir.misc.StringUtil
+   */
+  public abstract String getURL (Entity ent, Entity mediaTypeEnt);
+
+       /**
+   * gets the summary representation for the media
+   * in the form of a URL (String). Usually the URL points
+   * to some sort of an icon that previews what kind of
+   * media an article will contain.
+   * It should use the helper functions in the StringUtil class to
+   * build URL's safely, eliminating any *illegal* user input.
+   * @param ent, an Entity holding the media MetaData
+   * @param mediaTypeEnt, an Entity holding the media_table entry
+   * @return String, the url.
+   * @see mir.entity.Entity
+   * @see mir.misc.StringUtil
+   */
+  public abstract String getListView (Entity ent, Entity mediaTypeEnt);
+
+       /**
+   * Returns the absolute filesystem path to where the media
+   * content should be stored. This path is usually defined
+   * in the configuration wich is accessible through the MirConfig
+   * class.
+   * @return String, the path.
+   * @see mir.misc.MirConfig
+   */
+  public abstract String getStoragePath ();
+
+       /**
+   * Returns the *relative* filesystem path to where the media
+   * icon content should be stored. It is relative to the path
+   * returned by getStoragePath()
+   * This path is usually defined
+   * in the configuration wich is accessible through the MirConfig
+   * class.
+   * @return String, the path.
+   * @see mir.misc.MirConfig
+   */
        public abstract String getIconStoragePath ();
+
+       /**
+   * Returns the base URL to that the media is accessible from
+   * to the end user. This could be a URL to another host.
+   * This is used in the Metadata stored in the DB and later on
+   * ,the templates use it.
+   * It is usually defined
+   * in the configuration wich is accessible through the MirConfig
+   * class.
+   * @return String, the base URL to the host.
+   * @see mir.misc.MirConfig
+   */
        public abstract String getPublishHost ();
+
+       /**
+   * Returns the file name of the Icon representing the media type.
+   * It is used in the summary view.
+   * It is usually defined
+   * in the configuration wich is accessible through the MirConfig
+   * class.
+   * @return String, the icon filename.
+   * @see mir.misc.MirConfig
+   */
        public abstract String getBigIcon ();
+  
+       /**
+   * Returns the file name of the small Icon representing 
+   * the media type.
+   * It is used in the right hand newswire list of the startpage.
+   * It is usually defined
+   * in the configuration wich is accessible through the MirConfig
+   * class.
+   * @return String, the icon filename.
+   * @see mir.misc.MirConfig
+   */
        public abstract String getTinyIcon ();
+
+       /**
+   * Returns the IMG SRC "ALT" text to be used
+   * for the Icon representations
+   * @return String, the ALT text.
+   */
        public abstract String getIconAlt ();
-       public abstract boolean isVideo ();
+
+       /**
+   * your all smart enough to figure it out.
+   * @return boolean.
+   */
+  public abstract boolean isVideo ();
+
+       /**
+   * your all smart enough to figure it out.
+   * @return boolean.
+   */
        public abstract boolean isAudio ();
+
+       /**
+   * your all smart enough to figure it out.
+   * @return boolean.
+   */
        public abstract boolean isImage ();
 
 }
index 8fe05c6..133b698 100755 (executable)
@@ -94,7 +94,7 @@ public class ProducerStartPage extends Producer {
     SimpleList parentList = HTMLTemplateProcessor.makeSimpleList(theParentList);
 
     // get the newswire
-    whereClause="is_published=true AND to_article_type >= 1";
+    whereClause="is_published=true AND to_article_type = 1";
     entityList = contentModule.getContent(whereClause,"date desc, webdb_create desc",0,newsPerPage);
     SimpleList newsWireList = HTMLTemplateProcessor.makeSimpleList(entityList);
     for (int i=0; i < entityList.size();i++) {
@@ -176,14 +176,13 @@ public class ProducerStartPage extends Producer {
     SimpleList startItemList = HTMLTemplateProcessor.makeSimpleList(entityList);
     for (int k=0; k < entityList.size();k++) {
       currentContent = (EntityContent)entityList.elementAt(k);
-      //images to content
+      //media to content
       currentMediaList = DatabaseContentToMedia.getInstance().getUploadedMedia(currentContent);
       if (currentMediaList!=null && currentMediaList.getCount()>=1) {
         SimpleList mediaListAudio = new SimpleList();
         SimpleList mediaListImages = new SimpleList();
         SimpleList mediaListVideo = new SimpleList();
         SimpleList mediaListOther = new SimpleList();
-        //SimpleHash allMediaSimpleHash = new SimpleHash();
         for (int n=0; n < currentMediaList.size();n++) {
           upMedia = currentMediaList.elementAt(n);
           upMediaSimpleHash = HTMLTemplateProcessor.makeSimpleHash(upMedia);
@@ -218,7 +217,6 @@ public class ProducerStartPage extends Producer {
           } //end if media_type != null
         } //end for
         try{
-          //SimpleList contentList = (SimpleList)mergeData.get("contentlist");
           contentHash = (SimpleHash)startItemList.get(k);
           contentHash.put("to_media_audio", mediaListAudio);
           contentHash.put("to_media_images", mediaListImages);
@@ -228,21 +226,6 @@ public class ProducerStartPage extends Producer {
       } //end if currentMediaList != null
     } //enf for featurueList.size..
 
-
-
-    /*for (int i=0; i < entityList.size();i++) {
-      currentContent = (EntityContent)entityList.elementAt(i);
-      //fetching/setting the images
-      imageEntityList = DatabaseContentToMedia.getInstance().getImages(currentContent);
-      if (imageEntityList!=null && imageEntityList.getCount()>=1) {
-        try{
-          mediaList = HTMLTemplateProcessor.makeSimpleList(imageEntityList);
-          contentHash = (SimpleHash)startItemList.get(i);
-          contentHash.put("to_media", mediaList);
-        } catch (Exception e){}
-      }
-    }*/
-
     // get the breaking news
     // only the first 5
     // todo: the number of breaking_news items have to be configurable
@@ -257,14 +240,13 @@ public class ProducerStartPage extends Producer {
     SimpleList featureList = HTMLTemplateProcessor.makeSimpleList(entityList);
     for (int k=0; k < entityList.size();k++) {
       currentContent = (EntityContent)entityList.elementAt(k);
-      //images to content
+      //media to content
       currentMediaList = DatabaseContentToMedia.getInstance().getUploadedMedia(currentContent);
       if (currentMediaList!=null && currentMediaList.getCount()>=1) {
         SimpleList mediaListAudio = new SimpleList();
         SimpleList mediaListImages = new SimpleList();
         SimpleList mediaListVideo = new SimpleList();
         SimpleList mediaListOther = new SimpleList();
-        //SimpleHash allMediaSimpleHash = new SimpleHash();
         for (int n=0; n < currentMediaList.size();n++) {
           upMedia = currentMediaList.elementAt(n);
           upMediaSimpleHash = HTMLTemplateProcessor.makeSimpleHash(upMedia);
@@ -299,7 +281,6 @@ public class ProducerStartPage extends Producer {
           } //end if media_type != null
         } //end for
         try{
-          //SimpleList contentList = (SimpleList)mergeData.get("contentlist");
           contentHash = (SimpleHash)featureList.get(k);
           contentHash.put("to_media_audio", mediaListAudio);
           contentHash.put("to_media_images", mediaListImages);
@@ -309,21 +290,6 @@ public class ProducerStartPage extends Producer {
       } //end if currentMediaList != null
     } //enf for featurueList.size..
 
-
-
-    /*for (int i=0; i < entityList.size();i++) {
-      currentContent = (EntityContent)entityList.elementAt(i);
-      //fetching/setting the images
-      imageEntityList = DatabaseContentToMedia.getInstance().getImages(currentContent);
-      if (imageEntityList!=null && imageEntityList.getCount()>=1) {
-        try{
-          mediaList = HTMLTemplateProcessor.makeSimpleList(imageEntityList);
-          contentHash = (SimpleHash)featureList.get(i);
-          contentHash.put("to_media", mediaList);
-        } catch (Exception e){}
-      }
-    }*/
-
     // Zusaetzlich Informationen
     startPageModel = new SimpleHash();
     startPageModel.put("breakingnews", breakingList);
index 7b8ac84..6b3d418 100755 (executable)
@@ -2,12 +2,14 @@ package mircoders.producer;
 
 import java.io.*;
 import java.lang.*;
+import java.lang.reflect.*;
 import java.util.*;
 import java.sql.*;
 
 import freemarker.template.*;
 
 import mir.misc.*;
+import mir.media.*;
 import mir.storage.*;
 import mir.module.*;
 import mir.entity.*;
@@ -20,6 +22,18 @@ import mircoders.storage.*;
 public class ProducerTopics extends ProducerList {
 
   public String where;
+  String              currentMediaId;
+  EntityList          upMediaEntityList;
+  EntityList          imageEntityList;
+  EntityList          currentMediaList;
+  Entity              mediaType;
+  EntityMedia         uploadedMedia;
+  Class               mediaHandlerClass=null;
+  MirMedia            mediaHandler=null;
+  String              mediaHandlerName=null;
+  Database            mediaStorage=null;
+  String              tinyIcon;
+  String              iconAlt;
 
   public void setAdditional(String key, TemplateModel value) {
     additional.put(key,value);
@@ -88,12 +102,53 @@ public class ProducerTopics extends ProducerList {
         if(entityList != null && entityList.size()==1){
           currentContent = (EntityContent)entityList.elementAt(0);
           SimpleHash specialHash = HTMLTemplateProcessor.makeSimpleHash(currentContent);
-          // get the images
-          EntityList currentMedia = DatabaseContentToMedia.getInstance().getImages(currentContent);
-          if (currentMedia!=null && currentMedia.getCount()>=1) {
-            SimpleList mediaList = HTMLTemplateProcessor.makeSimpleList(currentMedia);
-            specialHash.put("to_media",mediaList);
-          }
+
+          currentMediaList = DatabaseContentToMedia.getInstance().getUploadedMedia(currentContent);
+          if (currentMediaList!=null && currentMediaList.getCount()>=1) {
+            SimpleList mediaListAudio = new SimpleList();
+            SimpleList mediaListImages = new SimpleList();
+            SimpleList mediaListVideo = new SimpleList();
+            SimpleList mediaListOther = new SimpleList();
+            for (int n=0; n < currentMediaList.size();n++) {
+              upMedia = currentMediaList.elementAt(n);
+              upMediaSimpleHash = HTMLTemplateProcessor.makeSimpleHash(upMedia);
+              mediaType = ((EntityMedia)upMedia).getMediaType();
+              //must be a non-existant to_media_type entry..
+              if (mediaType != null) {
+                try {
+                  mediaHandlerName = mediaType.getValue("classname");
+                  mediaStorageName = mediaType.getValue("tablename");
+                  mediaStorageClass = Class.forName("mircoders.storage.Database"+mediaStorageName);
+                  mediaHandlerClass = Class.forName("mir.media.MediaHandler"+mediaHandlerName);
+                  mediaHandler = (MirMedia)mediaHandlerClass.newInstance();
+                  Method m = mediaStorageClass.getMethod("getInstance", null);
+                  mediaStorage = (Database)m.invoke(null, null);
+                  //we most likely need further info
+                  upMedia = mediaStorage.selectById(upMedia.getId());
+                } catch (Exception e) {
+                  theLog.printError("ProducerList: problem in reflection: "+mediaHandlerName);
+                } //end catch
+                upMediaSimpleHash.put("url", mediaHandler.getListView(upMedia, mediaType));
+                if (upMedia.getValue("is_published") == "1") {
+                  if (mediaHandler.isImage()) {
+                    mediaListImages.add(upMediaSimpleHash);
+                  } else if (mediaHandler.isAudio()) {
+                    mediaListAudio.add(upMediaSimpleHash);
+                  } else if (mediaHandler.isVideo()) {
+                    mediaListVideo.add(upMediaSimpleHash);
+                  } else {
+                    mediaListOther.add(upMediaSimpleHash);
+                  }
+                } //end if is_published
+              } //end if media_type != null
+            } //end for
+            try{
+              specialHash.put("to_media_audio", mediaListAudio);
+              specialHash.put("to_media_images", mediaListImages);
+              specialHash.put("to_media_video", mediaListVideo);
+              specialHash.put("to_media_other", mediaListOther);
+            } catch (Exception e){}
+          } //end if currentMediaList != null
           setAdditional("special",specialHash);
         }
         
index d1a8980..6bd741d 100755 (executable)
@@ -239,16 +239,25 @@ public class ServletModuleOpenIndy extends ServletModule
       for(Iterator it = mp.requestList.iterator(); it.hasNext();){
         MpRequest mpReq = (MpRequest)it.next();
         String fileName = mpReq.getFilename();
+        //This is just a temporary way to get the content-type via
+        //the .extension , we need to use a magic method, by looking
+        //at the header (first few bytes) of the file. -mh
+        //the Oreilly method sucks cause it rely's on the what
+        //content-type the client browser sends and that's
+        //too often application-octet stream.
         String contentType = FileUtil.guessContentTypeFromName(fileName);
         HashMap mediaValues = new HashMap();
 
         theLog.printError("CONTENT TYPE IS: "+contentType);
-
+        
+        //The map file should be Mir/content-types.properties, it's the 
+        //default Sun Java file+ some entries that it did not have.
+        //so if you support a new media type you have to make sure that
+        //it is in this file
         if ((contentType==null) || (contentType=="application/octet-stream")) {
           throw new ServletModuleException("ModuleException: One or more files of unrecognized types");
         }
 
-
         String mediaTitle=(String)withValues.get("media_title"+i);
         i++;
 
@@ -262,6 +271,10 @@ public class ServletModuleOpenIndy extends ServletModule
         mediaValues.put("is_produced", "0");
         mediaValues.put("is_published","1");
 
+        //the where clause to find the media_type entry
+        //from the content-type.
+        //we use the media type entry to lookup the 
+        //media Handler/Storage classes
         String wc = " mime_type='"+contentType+"'";
 
         EntityList mediaTypesList = DatabaseMediaType.getInstance().selectByWhereClause(wc);
@@ -269,13 +282,17 @@ public class ServletModuleOpenIndy extends ServletModule
         String mediaTypeId = null;
         String mediaStorageName = null;
         String mediaHandlerName = null;
-  
+        //if we found an entry matching the
+        //content-type int the table.
         if (mediaTypesList.size() > 0) {
+          //get the class names from the media_type table.
           mediaTypeId = mediaTypesList.elementAt(0).getId();
           mediaStorageName = mediaTypesList.elementAt(0).getValue("tablename");
           mediaHandlerName = mediaTypesList.elementAt(0).getValue("classname");
           mediaValues.put("to_media_type",mediaTypeId);
-          
+         
+          //load the classes via reflection
           String MediaId;
           try {
                 Class mediaStorageClass = Class.forName("mircoders.storage.Database"+mediaStorageName);
@@ -288,12 +305,13 @@ public class ServletModuleOpenIndy extends ServletModule
 
                 Class mediaHandlerClass = Class.forName("mir.media.MediaHandler"+mediaHandlerName);
                 MirMedia mediaHandler = (MirMedia)mediaHandlerClass.newInstance();
+                //save and store the media data/metadata
                 mediaHandler.set(mpReq.getMedia(), mediaEnt,mediaTypesList.elementAt(0));
 
                 //were done with mpReq at this point, dereference it. as it contains
                 //mucho mem. -mh 01.10.2001
                 mpReq=null;
-
+              
               if(mediaId!=null){
                 new ProducerMedia().handle(null, null, false, false, mediaId);
               }
@@ -301,7 +319,7 @@ public class ServletModuleOpenIndy extends ServletModule
                 theLog.printError("setting uploaded_media failed: "+e.toString());
           } //end try-catch
               
-
+          //we got this far, associate the media to the article
           try{
               DatabaseContentToMedia.getInstance().addMedia(cid,mediaId);
               theLog.printError("setting content_x_media success");
index a869476..04ab03c 100755 (executable)
                       <td> 
                         <h3>${special.title}</h3>
                         <h4><i>${special.creator}, ${special.webdb_create_formatted}</i></h4>
-                        <p> <if special.to_media && special.to_media[0]["is_published"]=="1"> 
-                          <img src="${special.to_media[0]["icon_path"]}" width="${special.to_media[0]["icon_width"]}" height="${special.to_media[0]["icon_height"]}" alt="" align="left" vspace="8" hspace="8"> 
-                          </if> ${special.description} </p>
+                        <p> 
+                <if special.to_media_audio && special.to_media_audio[0]["is_published"]=="1"> 
+                  ${special.to_media_audio[0]["url"]}
+                </if> 
+                                 <if special.to_media_video && special.to_media_video[0]["is_published"]=="1"> 
+                  ${special.to_media_video[0]["url"]}
+                </if> 
+                                 <if special.to_media_other && special.to_media_other[0]["is_published"]=="1"> 
+                  ${special.to_media_other[0]["url"]}
+                </if> 
+                <p>
+                                 <if special.to_media_images && special.to_media_images[0]["is_published"]=="1"> 
+                  ${special.to_media_images[0]["url"]}
+                </if> 
+                          ${special.description} </p>
                         <p align="right">[<a href="${config.docroot}${special.publish_path}${special.id}.shtml">read</a>]</p>
                       </td>
                     </tr>
                         <h3>${i.title}</h3>
                         <h4><i>${i.creator}, ${i.webdb_create_formatted}</i></h4>
                         <p>                     
-                         <if i.to_media && i.to_media[0]["is_published"]=="1"> 
-                          <img src="${i.to_media[0]["icon_path"]}" width="${i.to_media[0]["icon_width"]}" height="${i.to_media[0]["icon_height"]}" alt="" align="left" vspace="8" hspace="8"> 
-                          </if> 
+                <if i.to_media_audio && i.to_media_audio[0]["is_published"]=="1"> 
+                  ${i.to_media_audio[0]["url"]}
+                </if> 
+                                 <if i.to_media_video && i.to_media_video[0]["is_published"]=="1"> 
+                  ${i.to_media_video[0]["url"]}
+                </if> 
+                                 <if i.to_media_other && i.to_media_other[0]["is_published"]=="1"> 
+                  ${i.to_media_other[0]["url"]}
+                </if> 
+                <p>
+                                 <if i.to_media_images && i.to_media_images[0]["is_published"]=="1"> 
+                  ${i.to_media_images[0]["url"]}
+                </if> 
                          ${i.description}</p>
                         <p align="right">[<a href="${config.docroot}${i.publish_path}${i.id}.shtml">read</a>]</p>
                       </td>