KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > applications > media > builders > MediaSources


1  /*
2   
3  This software is OSI Certified Open Source Software.
4  OSI Certified is a certification mark of the Open Source Initiative.
5   
6  The license (Mozilla version 1.0) can be read at the MMBase site.
7  See http://www.MMBase.org/license
8   */

9
10 package org.mmbase.applications.media.builders;
11
12 import java.util.*;
13
14 import org.mmbase.module.core.MMObjectNode;
15 import org.mmbase.module.core.MMObjectBuilder;
16
17
18 import org.mmbase.util.functions.*;
19 import org.mmbase.util.logging.Logger;
20 import org.mmbase.util.logging.Logging;
21
22 import org.mmbase.applications.media.urlcomposers.URLComposer;
23 import org.mmbase.applications.media.filters.MainFilter;
24 import org.mmbase.applications.media.Format;
25 import org.mmbase.applications.media.Codec;
26
27
28
29 /**
30  * The MediaSource builder describes a specific type of media that can be retrieved (real/mp3/etc). Information about
31  * format, quality, and status will be maintained in this object. A MediaSource belongs
32  * to a MediaFragement that describes the piece of media, the MediaSource is the
33  * real audio/video itself. A MediaSource is connected to provider objects that indicate
34  * where the real audio/video files can be found.
35  *
36  * @author Rob Vermeulen
37  * @author Michiel Meeuwissen
38  * @version $Id: MediaSources.java,v 1.34 2005/10/06 11:46:31 michiel Exp $
39  * @since MMBase-1.7
40  */

41 public class MediaSources extends MMObjectBuilder {
42     private static final Logger log = Logging.getLoggerInstance(MediaSources.class);
43        
44     // typo checks
45
public static final String JavaDoc FUNCTION_URLS = "urls";
46     public static final String JavaDoc FUNCTION_FILTEREDURLS = "filteredurls";
47     public static final String JavaDoc FUNCTION_URL = "url";
48     public static final String JavaDoc FUNCTION_AVAILABLE = "available";
49     public static final String JavaDoc FUNCTION_FORMAT = "format";
50     public static final String JavaDoc FUNCTION_CODEC = "codec";
51     public static final String JavaDoc FUNCTION_MIMETYPE = "mimetype";
52
53     
54     // parameter definitions (making use of reflection utitility for functions)
55
public final static Parameter[] URLS_PARAMETERS = { new Parameter("node", org.mmbase.bridge.Node.class),
56                                                                 new Parameter.Wrapper(MediaFragments.URLS_PARAMETERS) };
57     public final static Parameter[] FILTEREDURLS_PARAMETERS = URLS_PARAMETERS;
58     public final static Parameter[] URL_PARAMETERS = URLS_PARAMETERS;
59     public final static Parameter[] AVAILABLE_PARAMETERS = {};
60     public final static Parameter[] FORMAT_PARAMETERS = URLS_PARAMETERS;
61     public final static Parameter[] CODEC_PARAMETERS = {};
62     public final static Parameter[] MIMETYPE_PARAMETERS = {};
63
64
65
66
67     
68     // Status (this should be helped by field-type project (resourcebundle/java-constants))
69
public final static int STATE_DONE = 3; // jikes
70
public final static int STATE_SOURCE = 4; // what does this mean?
71
public final static int STATE_REMOVED = 10; // jikes
72
public final static String JavaDoc STATES_RESOURCE = "org.mmbase.applications.media.builders.resources.states";
73     
74     public final static int MONO = 1;
75     public final static int STEREO = 2;
76
77     
78
79
80     private String JavaDoc defaultProvider = null;
81     
82     /**
83      * {@inheritDoc}
84      */

85     public boolean init() {
86         boolean result = super.init();
87
88         defaultProvider = getInitParameter("default.provider.alias");
89         
90         return result;
91     }
92     
93     
94     public MediaSources() {
95     }
96     
97     /**
98      * create a new mediasource, and relate it with specified mediafragment.
99      *
100      * @param mediafragment the media fragment to which this source belongs
101      * @param status of the media source
102      * @param format the format of the source (Real, Mp3)
103      * @param channels stereo/mono
104      * @param url the file name of the media source
105      * @param owner creator of the new object
106      * @return the new <code>MediaSource</code>
107      */

108     public MMObjectNode createSource(MMObjectNode mediafragment, int status, int format, int speed, int channels, String JavaDoc url, String JavaDoc owner) {
109         // creating media source
110
MMObjectNode source = getNewNode(owner);
111         source.setValue("state", status);
112         source.setValue("format", format);
113         source.setValue("codec", Codec.UNKNOWN.toInt());
114         source.setValue("bitrate", speed);
115         source.setValue("channels",channels);
116         source.setValue("url",url);
117         source.insert(owner);
118         
119         // creating relation between media source and media fragment
120
MMObjectNode insrel = mmb.getInsRel().getNewNode(owner);
121         insrel.setValue("snumber", mediafragment.getIntValue("number"));
122         insrel.setValue("dnumber", source.getIntValue("number"));
123         insrel.setValue("rnumber", mmb.getRelDef().getNumberByName("related"));
124         int ret = insrel.insert(owner);
125         if(ret<0) {
126             log.error("Cannot create relation between mediafragment and mediasource "+insrel);
127         } else {
128             log.debug("created "+insrel);
129         }
130         
131         return source;
132     }
133     
134     
135     /**
136      * resolve the url of the mediasource. (e.g. pnm://www.mmbase.org/test/test.ra)
137      *
138      * @param source the media source
139      * @param info extra info (i.e. HttpRequestIno, bitrate, etc.)
140      * @return the url of the media source
141      */

142     protected String JavaDoc getURL(MMObjectNode source, Map info) {
143         List urls = getFilteredURLs(source, null, info);
144         if (urls.size() == 0) return "[could not compose URL]";
145         URLComposer ri = (URLComposer) urls.get(0);
146         return ri.getURL();
147     }
148
149     
150     /**
151      * Resolve the mimetype for a certain media source
152      *
153      * @param source the media source
154      * @return the content type
155      */

156     String JavaDoc getMimeType(MMObjectNode source) { // package because it is used in URLResolver
157
return getFormat(source).getMimeType();
158
159     }
160     
161     
162
163     /**
164      * used in the editors
165      */

166     public String JavaDoc getGUIIndicator(MMObjectNode source) {
167     return "" + Format.get(source.getIntValue("format")) + "/" + source.getStringValue("bitrate") + "/" + source.getStringValue("channels");
168     /*
169         List urls = getFilteredURLs(source, null, null);
170         if (urls.size() == 0) return "[could not compose URL]";
171         URLComposer ri = (URLComposer) urls.get(0);
172         String url = ri.getURL();
173         if (url.startsWith("/")) {
174             url = MMBaseContext.getHtmlRootUrlPath() + url.substring(1);
175         }
176         if (ri.isAvailable()) {
177             return "<a HREF='" + url + "'>" + Format.get(source.getIntValue("format")) + "</a>";
178         } else {
179             return "[<a HREF='" + url + "'>" + Format.get(source.getIntValue("format")) + "</a>]";
180         }
181     */

182     }
183     
184     public int getSpeed(MMObjectNode node) {
185         return node.getIntValue("bitrate");
186     }
187     
188     public int getChannels(MMObjectNode node) {
189         return node.getIntValue("channels");
190     }
191     
192     /**
193      * The format field is an integer, this function returns a string-presentation
194      */

195     protected Format getFormat(MMObjectNode source) {
196         return Format.get(source.getIntValue("format"));
197     }
198
199
200     protected String JavaDoc getFormat(MMObjectNode source, Map info) {
201         log.debug("Getting format of a source.");
202         List urls = getFilteredURLs(source, null, info);
203         if (urls.size() > 0) {
204             return ((URLComposer) urls.get(0)).getFormat().toString();
205         } else {
206             return ""; //no sources
207
}
208     }
209     
210     /**
211      * The codec field is an integer, this function returns a string-presentation
212      */

213     protected Codec getCodec(MMObjectNode source) {
214         return Codec.get(source.getIntValue("codec"));
215     }
216
217     /**
218      * {@inheritDoc}
219      */

220     protected Object JavaDoc executeFunction(MMObjectNode node, String JavaDoc function, List args) {
221         if (log.isDebugEnabled()) {
222             log.debug("executeFunction " + function + "(" + args + ") on mediasources " + node);
223         }
224         if (function.equals("info")) {
225             List empty = new ArrayList();
226             java.util.Map JavaDoc info = (java.util.Map JavaDoc) super.executeFunction(node, function, empty);
227             info.put("absoluteurl", "(<??>)");
228             info.put("urlresult", "(<??>) ");
229             info.put(FUNCTION_URLS, "(fragment) A list of all possible URLs to this source/fragment (Really URLComposer.URLComposer's)");
230             info.put(FUNCTION_FORMAT, "() Shorthand for gui(format)");
231             info.put(FUNCTION_CODEC, "() Shorthand for gui(codec)");
232             info.put(FUNCTION_MIMETYPE, "() Returns the mime-type for this source");
233             info.put("gui", "(state|channels|codec|format|..) Gui representation of this object.");
234             
235             if (args == null || args.size() == 0) {
236                 return info;
237             } else {
238                 return info.get(args.get(0));
239             }
240         } else if (FUNCTION_URLS.equals(function) || FUNCTION_FILTEREDURLS.equals(function)) {
241
242             Parameters parameters = Functions.buildParameters(URLS_PARAMETERS, args);
243
244             MMObjectNode fragment;
245                                                    
246             Object JavaDoc f = parameters.get("node");
247             if (f == null) {
248                 fragment = null;
249             } else {
250                 if (f instanceof MMObjectNode) {
251                     fragment = (MMObjectNode) f;
252                 } else if (f instanceof org.mmbase.bridge.Node) {
253                     fragment = getNode(((org.mmbase.bridge.Node) f).getNumber());
254                 } else if (f instanceof String JavaDoc) {
255                     fragment = getNode((String JavaDoc) f);
256                 } else {
257                     throw new IllegalArgumentException JavaDoc("Argument of function " + FUNCTION_URLS + " must be a Node");
258                 }
259             }
260
261             if (FUNCTION_FILTEREDURLS.equals(function)) {
262                 return getFilteredURLs(node, fragment, MediaFragments.translateURLArguments(args, null));
263             } else {
264                 return getURLs(node, fragment, MediaFragments.translateURLArguments(args, null), null,null);
265             }
266         } else if (FUNCTION_URL.equals(function)) {
267             return getURL(node, MediaFragments.translateURLArguments(args, null));
268         } else if (FUNCTION_AVAILABLE.equals(function)) {
269             Iterator providers = getProviders(node).iterator();
270             while (providers.hasNext()) {
271                 // if one of the providers is online, then this source is availabe.
272
MMObjectNode provider = (MMObjectNode) providers.next();
273                 if (provider.getIntValue("state") == MediaProviders.STATE_ON) return Boolean.TRUE;
274             }
275             return Boolean.FALSE;
276         } else if (FUNCTION_FORMAT.equals(function)) {
277             return getFormat(node, MediaFragments.translateURLArguments(args, null));
278         } else if (FUNCTION_CODEC.equals(function)) {
279             return getCodec(node);
280         } else if (FUNCTION_MIMETYPE.equals(function)) {
281             return getMimeType(node);
282         } else if (args != null && args.size() > 0) {
283             if (function.equals("gui")) {
284                 if ("state".equals(args.get(0))) {
285                     String JavaDoc val = node.getStringValue("state");
286                     ResourceBundle bundle;
287                     if (args.size() > 1) {
288                         bundle = ResourceBundle.getBundle(STATES_RESOURCE, new Locale((String JavaDoc) args.get(1), ""), getClass().getClassLoader());
289                     } else {
290                         bundle = ResourceBundle.getBundle(STATES_RESOURCE, new Locale(mmb.getLanguage(), ""), getClass().getClassLoader());
291                     }
292                     try {
293                         return bundle.getString(val);
294                     } catch (java.util.MissingResourceException JavaDoc e) {
295                         return val;
296                     }
297                 } else if ("channels".equals(args.get(0))) {
298                     int val = node.getIntValue("channels");
299                     switch(val) {
300                         case MONO: return "Mono";
301                         case STEREO: return "Stereo";
302                         default: return "Undefined";
303                     }
304                 } else if ("codec".equals(args.get(0))) {
305                     return getCodec(node);
306                 } else if ("format".equals(args.get(0))) {
307                     Locale locale = new Locale(mmb.getLanguage(), "");
308                     if(args.size() > 1) {
309                         locale = new Locale((String JavaDoc) args.get(1), "");
310                     }
311                     return getFormat(node).getGUIIndicator(locale);
312                 } else if ("".equals(args.get(0)) || args.get(0) == null) {
313                     return super.executeFunction(node, function, args); // call getGUIIndicator
314
} else {
315                     return node.getStringValue((String JavaDoc) args.get(0));
316                 }
317             }
318         } else {
319             String JavaDoc arg = null;
320             if (args != null && args.size() > 0) {
321                 arg = (String JavaDoc) args.get(0);
322             } else {
323                 arg = "";
324             }
325             if (function.equals("absoluteurl")) {
326                 Map info = new HashMap();
327                 info.put("server", arg);
328                 return getURL(node, info);
329             } else if (function.equals("urlresult")) {
330                 //return getURLResult(node, arg);
331
}
332         }
333         log.debug("Function not matched in mediasources");
334         return super.executeFunction(node, function, args);
335     }
336     
337     /**
338      * remove this MediaSource, check configuration and check all places where this
339      * file is reproduced.
340      */

341     /*
342     public void remove() {
343     }
344      */

345     
346     
347     /**
348      * Returns all possible URLs for this source. (A source can be on different providers)
349      */

350     
351     protected List getURLs(MMObjectNode source, MMObjectNode fragment, Map info, List urls, Set cacheExpireObjects) {
352         if (urls == null) urls = new ArrayList();
353         log.debug("Getting urls for source " + source.getNumber());
354         List providers = getProviders(source);
355         if (providers.size() == 0) {
356             if (defaultProvider != null) {
357                 MMObjectNode provider = getNode(defaultProvider);
358                 if (provider == null) {
359                     log.warn("Specified default provider '" + defaultProvider + "' is not an existing node");
360                 } else {
361                     MediaProviders bul = (MediaProviders) provider.getBuilder(); // cast everytime, because it can be extended
362
bul.getURLs(provider, source, fragment, info, urls, cacheExpireObjects);
363                 }
364             }
365             
366         } else {
367             Iterator i = providers.iterator();
368             while (i.hasNext()) {
369                 MMObjectNode provider = (MMObjectNode) i.next();
370                 if (log.isDebugEnabled()) {
371                     log.debug("Found provider " + provider.getNumber() + " source: " + source.getNumber());
372                 }
373                 MediaProviders bul = (MediaProviders) provider.getBuilder(); // cast everytime, because it can be extended
374
bul.getURLs(provider, source, fragment, info, urls, cacheExpireObjects);
375             }
376         }
377         return urls;
378     }
379     /**
380      * Returns all URLs for this source, but filtered, with the best ones on top.
381      */

382     protected List getFilteredURLs(MMObjectNode source, MMObjectNode fragment, Map info) {
383         List urls = getURLs(source, fragment, info, null, null);
384         return MainFilter.getInstance().filter(urls);
385     }
386     
387     /**
388      * relates a source with given provider. Only if there is one provider matching.
389      *
390      * @param source the media source.
391      * @param providername the name of the provider that is going to be related.
392      * @param owner the owner name that is creating the relation.
393      */

394
395     public void addProvider(MMObjectNode source, String JavaDoc providername, String JavaDoc owner) {
396         MMObjectBuilder providers = mmb.getMMObject("mediaproviders");
397        
398     /** should be used in 1.7
399         NodeSearchQuery query = new NodeSearchQuery(providers);
400         StepField namefield = query.getField(providers.getField("name"));
401         BasicFieldValueConstraint constraint = new BasicFieldValueConstraint(namefield,providername);
402         query.setConstraint(constraint);
403         
404         List providerlist=null;
405         try{
406             providerlist = providers.getNodes(query);
407         } catch (SearchQueryException sqe) {
408             log.error("Exception while querying "+sqe);
409     }
410     */

411
412     int providernumber = 0;
413     Enumeration e = providers.search("WHERE name='"+providername+"'");
414         if (!e.hasMoreElements()) {
415             log.error("No media provider found with name "+providername);
416             return;
417     } else {
418         MMObjectNode provider = (MMObjectNode)e.nextElement();
419         providernumber = provider.getIntValue("number");
420         log.debug("found provider with number = "+providernumber);
421     }
422     if (e.hasMoreElements()) {
423             log.error("Multiple media providers with name "+providername+" found");
424             return;
425     }
426         
427         MMObjectNode insrel = mmb.getInsRel().getNewNode(owner);
428         insrel.setValue("snumber", source.getValue("number"));
429         insrel.setValue("dnumber", providernumber);
430         insrel.setValue("rnumber", mmb.getRelDef().getNumberByName("related"));
431         
432         int ret = insrel.insert(owner);
433         if(ret<0) {
434             log.error("cannot create relation "+insrel);
435         } else {
436             log.debug("relation created "+insrel);
437         }
438     }
439
440
441     /**
442      * get all mediaproviders belonging to this mediasource
443      * @param source the mediasource
444      * @return All mediaproviders related to the given mediasource
445      */

446     protected List getProviders(MMObjectNode source) {
447         if (log.isDebugEnabled()) {
448             log.debug("mediasource " + source.getStringValue("number"));
449         }
450         return source.getRelatedNodes("mediaproviders");
451     }
452     
453     
454     private void checkFields(MMObjectNode node) {
455         if (log.isDebugEnabled()) {
456             log.debug("format: " + node.getValue("format"));
457         }
458         if (node.getValue("format") == null || node.getIntValue("format") == -1) {
459             String JavaDoc url = node.getStringValue("url");
460             int dot = url.lastIndexOf('.');
461             if (dot > 0) {
462                 String JavaDoc extension = url.substring(dot + 1).toLowerCase();
463                 if (log.isDebugEnabled()) {
464                     log.debug("Format of was unset, trying to autodetect by using 'url' field '" + url + "' with extension '" + extension + "'");
465                 }
466                 node.setValue("format", Format.get(extension).toInt());
467             }
468         }
469     }
470     
471     public boolean setValue(MMObjectNode node,String JavaDoc fieldName, Object JavaDoc value) {
472         if ("format".equals(fieldName)) {
473         }
474         return super.setValue(node, fieldName, value);
475     }
476     
477     /**
478      * The commit can be used to automaticly fill unfilled fields. For
479      * example the format can well be guessed by the URL.
480      * (todo: which of commit,insert must be overriden?)
481      */

482     
483     public boolean commit(MMObjectNode node) {
484         checkFields(node);
485         return super.commit(node);
486     }
487     public int insert(String JavaDoc owner, MMObjectNode node) {
488         checkFields(node);
489         return super.insert(owner, node);
490     }
491
492
493
494 }
495
Popular Tags