KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > applications > media > urlcomposers > URLComposerFactory


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
11 package org.mmbase.applications.media.urlcomposers;
12
13 import org.mmbase.applications.media.Format;
14 import org.mmbase.applications.media.builders.MediaFragments;
15 import org.mmbase.module.core.MMObjectNode;
16 import org.mmbase.util.logging.Logger;
17 import org.mmbase.util.logging.Logging;
18 import org.mmbase.util.xml.DocumentReader;
19 import org.mmbase.util.*;
20 import org.w3c.dom.Element JavaDoc;
21 import java.util.*;
22 import java.io.File JavaDoc;
23
24 /**
25  * The URLComposerFactory contains the code to decide which kind of
26  * URLComposer is instatiated. This is a default implementation,
27  * which can be extended for your situation (The class can be configured in
28  * the mediaproviders builder xml)
29  *
30  * This particular implementation provides the possibility to relate
31  * formats to URLComposer classes. It can also relate a
32  * format/protocol combination to a URLComposer class.
33  *
34  * @author Michiel Meeuwissen
35  * @author Rob Vermeulen (VPRO)
36  */

37
38 public class URLComposerFactory {
39
40     private static final Logger log = Logging.getLoggerInstance(URLComposerFactory.class);
41
42     // XML tags:
43
private static final String JavaDoc MAIN_TAG = "urlcomposers";
44     private static final String JavaDoc DEFAULT_TAG = "default";
45     private static final String JavaDoc COMPOSER_TAG = "urlcomposer";
46     private static final String JavaDoc FORMAT_ATT = "format";
47     private static final String JavaDoc PROTOCOL_ATT = "protocol";
48
49     public static final String JavaDoc CONFIG_FILE = "media/urlcomposers.xml";
50
51     private static final Class JavaDoc defaultComposerClass = URLComposer.class;
52
53     private static URLComposerFactory instance = new URLComposerFactory();
54
55     /**
56      * Container class te represent one configuration item, which is a
57      * format/protocol/URLComposer-class combination. The factory
58      * maintains a List of these.
59      */

60     private static class ComposerConfig {
61         /*
62         private static Class[] constructorArgs = new Class[] {
63             MMObjectNode.class, MMObjectNode.class, MMObjectNode.class, Map.class, List.class
64         };*/

65         private Format format;
66         private String JavaDoc protocol;
67         private Class JavaDoc klass;
68
69         ComposerConfig(Format f, Class JavaDoc k, String JavaDoc p) {
70             this.format = f;
71             this.klass = k;
72             this.protocol = p;
73             if (protocol == null) protocol = "";
74
75         }
76         boolean checkFormat(Format f) { return format.equals(f); }
77         boolean checkProtocol(String JavaDoc p) { return "".equals(protocol) || protocol.equals(p); }
78
79         Class JavaDoc getComposerClass() { return klass; };
80
81         URLComposer getInstance(MMObjectNode provider, MMObjectNode source, MMObjectNode fragment, Map info, Set cacheExpireObjects) {
82             try {
83                 log.debug("Instatiating " + klass);
84                 URLComposer newComposer = (URLComposer) klass.newInstance();
85                 newComposer.init(provider, source, fragment, info, cacheExpireObjects);
86                 return newComposer;
87             } catch (Exception JavaDoc g) {
88                 log.error("URLComposer could not be instantiated " + g.toString());
89             }
90             return null; // could not get instance, this is an error, but go on anyway (implemtnation checks for null)
91
}
92         public String JavaDoc toString() {
93             return "" + format + ":" + klass.getName();
94         }
95     }
96     // this is the beforementioned list.
97
private List urlComposerClasses = new ArrayList();
98
99     private ComposerConfig defaultUrlComposer = new ComposerConfig(null, defaultComposerClass, null);
100
101     private ResourceWatcher configWatcher = new ResourceWatcher() {
102         public void onChange(String JavaDoc file) {
103             readConfiguration(file);
104         }
105     };
106
107
108     /**
109      * Construct the factory, which is a Singleton.
110      */

111     private URLComposerFactory() {
112         configWatcher.add(CONFIG_FILE);
113         configWatcher.onChange();
114         configWatcher.start();
115
116     }
117
118
119
120     /**
121      * read the factory's configuration, which is the file 'urlcomposers.xml' in config/media/
122      */

123     private synchronized void readConfiguration(String JavaDoc configFile) {
124         if (log.isServiceEnabled()) {
125             log.service("Reading " + configFile);
126         }
127         urlComposerClasses.clear();
128         org.w3c.dom.Document JavaDoc doc;
129         try {
130             doc = ResourceLoader.getConfigurationRoot().getDocument(configFile, true, getClass());
131         } catch (Exception JavaDoc e) {
132             log.error(e.getMessage(), e);
133             return;
134         }
135         if (doc == null) {
136             log.error("Configuration file for URLComposerFactory " + configFile + " does not exist");
137         } else {
138             DocumentReader reader = new DocumentReader(doc);
139             try {
140                 defaultUrlComposer = new ComposerConfig(null, Class.forName(reader.getElementValue(MAIN_TAG + "." + DEFAULT_TAG)), null);
141             } catch (java.lang.ClassNotFoundException JavaDoc e) {
142                 defaultUrlComposer = new ComposerConfig(null, defaultComposerClass, null);
143                 // let it be something in any case
144
log.error(e.toString());
145             }
146
147             for(Iterator e = reader.getChildElements(MAIN_TAG, COMPOSER_TAG); e.hasNext();) {
148                 Element JavaDoc element = (Element JavaDoc)e.next();
149                 String JavaDoc clazz = reader.getElementValue(element);
150                 String JavaDoc f = element.getAttribute(FORMAT_ATT);
151                 List formats;
152                 if ("*".equals(f)) {
153                     formats = Format.getMediaFormats();
154                 } else {
155                     formats = new ArrayList();
156                     formats.add(Format.get(f));
157                 }
158                 String JavaDoc protocol = element.getAttribute(PROTOCOL_ATT);
159                 Iterator i = formats.iterator();
160                 while(i.hasNext()) {
161                     Format format = (Format) i.next();
162                     try {
163                         log.debug("Adding for format " + format + " urlcomposer " + clazz);
164                         urlComposerClasses.add(new ComposerConfig(format, Class.forName(clazz), protocol));
165                     } catch (ClassNotFoundException JavaDoc ex) {
166                         log.error("Cannot load urlcomposer " + clazz + " because " + ex.getMessage());
167                     }
168                 }
169             }
170         }
171     }
172
173
174     /**
175      * Returns the one instance.
176      */

177
178     public static URLComposerFactory getInstance() {
179         return instance;
180     }
181
182
183     /**
184      * You can relate template objects to media fragments. They can be
185      * processed by 'MarkupURLComposers'. For every template a
186      * MarkupURLComposers will be created (if, at least,
187      * MarkupURLComposers are configured in urlcomposers.xml).
188      */

189
190     protected List getTemplates(MMObjectNode fragment) {
191         List templates = new ArrayList();
192
193         if (fragment != null) {
194             MediaFragments bul = (MediaFragments) fragment.getBuilder();
195             Stack stack = bul.getParentFragments(fragment);
196             Iterator i = stack.iterator();
197             while (i.hasNext()) {
198                 MMObjectNode f = (MMObjectNode) i.next();
199                 templates.addAll(f.getRelatedNodes("templates"));
200             }
201         }
202         return templates;
203     }
204
205
206     /**
207      * Add urlcomposer to list of urlcomposers if that is possible.
208      *
209      * @return true if added, false if not.
210      */

211     protected boolean addURLComposer(URLComposer uc, List urls) {
212         if (log.isDebugEnabled()) {
213             log.debug("Trying to add " + uc + " to " + urls);
214         }
215         if (uc == null) {
216             log.debug("Could not make urlcomposer");
217         } else if (urls.contains(uc)) { // avoid duplicates
218
log.debug("This URLComposer already in the list");
219         } else if (!uc.canCompose()) {
220             log.debug("This URLComposer cannot compose");
221         } else {
222             log.debug("Adding a " + uc.getClass().getName());
223             urls.add(uc);
224             return true;
225         }
226         return false;
227     }
228
229     /**
230      * When the provider/source/fragment combo is determined they can
231      * be fed into this function of the urlcomposerfactory, which will
232      * then produce zero or more urlcomposers. They are added to the
233      * provided list, or a new list will be made if the argument List
234      * is 'null'.
235      *
236      * @param provider MMObjectNode
237      * @param source MMObjectNode
238      * @param info A Map with additional options
239      * @param urls A List with URLComposer to which the new ones must be added, or null.
240      *
241      * @return The (new) list with urlcomposers.
242      */

243     public List createURLComposers(MMObjectNode provider, MMObjectNode source, MMObjectNode fragment, Map info, List urls, Set cacheExpireObjects) {
244         if (urls == null) urls = new ArrayList();
245         Format format = Format.get(source.getIntValue("format"));
246         String JavaDoc protocol = provider.getStringValue("protocol");
247         if (log.isDebugEnabled()) log.debug("Creating url-composers for provider " + provider.getNumber() + "(" + format + ")");
248
249         Iterator i = urlComposerClasses.iterator();
250         boolean found = false;
251         while (i.hasNext()) {
252             ComposerConfig cc = (ComposerConfig) i.next();
253             if (log.isDebugEnabled()) {
254                 log.debug("Trying " + cc + " for '" + format + "'/'" + protocol + "'");
255             }
256
257             if (cc.checkFormat(format) && cc.checkProtocol(protocol)) {
258                 if (MarkupURLComposer.class.isAssignableFrom(cc.getComposerClass())) {
259                     // markupurlcomposers need a template, and a fragment can have 0-n of those.
260
List templates = getTemplates(fragment);
261                     Iterator ti = templates.iterator();
262                     while (ti.hasNext()) {
263                         MMObjectNode template = (MMObjectNode) ti.next();
264                         Map templateInfo = new HashMap(info);
265                         templateInfo.put("template", template);
266                         URLComposer uc = cc.getInstance(provider, source, fragment, templateInfo, cacheExpireObjects);
267                         addURLComposer(uc, urls);
268                     }
269                 } else {
270                     // normal urlcomposers are one per fragment of course
271
URLComposer uc = cc.getInstance(provider, source, fragment, info, cacheExpireObjects);
272                     addURLComposer(uc, urls);
273                 }
274                 found = true;
275             } else {
276                 log.debug(cc.checkFormat(format) + "/" + cc.checkProtocol(protocol));
277             }
278         }
279
280         if (! found) { // use default
281
URLComposer uc = defaultUrlComposer.getInstance(provider, source, fragment, info, cacheExpireObjects);
282             if (uc != null && ! urls.contains(uc)) { // avoid duplicates
283
log.debug("No urlcomposer found, adding the default");
284                 urls.add(uc);
285             }
286         }
287         return urls;
288     }
289 }
290
Popular Tags