001    /*
002     * 
003     * $Revision: 13883 $ $Date: 2008-08-20 11:52:39 +0200 (Mi, 20 Aug 2008) $
004     *
005     * This file is part of ***  M y C o R e  ***
006     * See http://www.mycore.de/ for details.
007     *
008     * This program is free software; you can use it, redistribute it
009     * and / or modify it under the terms of the GNU General Public License
010     * (GPL) as published by the Free Software Foundation; either version 2
011     * of the License or (at your option) any later version.
012     *
013     * This program is distributed in the hope that it will be useful, but
014     * WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program, in a file called gpl.txt or license.txt.
020     * If not, write to the Free Software Foundation Inc.,
021     * 59 Temple Place - Suite 330, Boston, MA  02111-1307 USA
022     */
023    
024    package org.mycore.services.plugins;
025    
026    import java.io.File;
027    import java.io.InputStream;
028    import java.io.Reader;
029    import java.io.StringReader;
030    import java.net.MalformedURLException;
031    import java.net.URL;
032    import java.util.Collection;
033    import java.util.HashSet;
034    import java.util.Hashtable;
035    import java.util.Iterator;
036    import java.util.Properties;
037    import java.util.Enumeration;
038    
039    import org.apache.log4j.Logger;
040    import org.mycore.common.MCRConfiguration;
041    import org.mycore.datamodel.ifs.MCRFileContentType;
042    
043    /**
044     * Loads and manages plugins
045     * 
046     * @author Thomas Scheffler (yagee)
047     */
048    public class TextFilterPluginManager {
049        /** The logger */
050        private static final Logger LOGGER = Logger.getLogger(TextFilterPluginManager.class);
051    
052        /** The configuration */
053        private static final MCRConfiguration CONF = MCRConfiguration.instance();
054    
055        /** Pluginbasket */
056        private static Hashtable CONTENT_TYPE_PLUGIN_BAG = null;
057    
058        private static Hashtable PLUGINS = null;
059    
060        /** initialized */
061        private static TextFilterPluginManager SINGLETON;
062    
063        /**
064         * 
065         */
066        private TextFilterPluginManager() {
067            init();
068        }
069    
070        public static TextFilterPluginManager getInstance() {
071            if (SINGLETON == null) {
072                SINGLETON = new TextFilterPluginManager();
073            }
074    
075            return SINGLETON;
076        }
077    
078        private void init() {
079            CONTENT_TYPE_PLUGIN_BAG = new Hashtable();
080            PLUGINS = new Hashtable();
081            loadPlugins();
082        }
083    
084        /**
085         * load TextFilterPlugins from the MCR.PluginDirectory
086         * 
087         */
088        public void loadPlugins() {
089            MCRConfiguration config = MCRConfiguration.instance();
090            String prefix = "MCR.TextFilterPlugin.";
091            Properties props = config.getProperties(prefix);
092            if (props == null) {
093                return;
094            }
095            
096            TextFilterPlugin filter = null;
097            MCRFileContentType ct;
098            
099            Enumeration e = props.propertyNames();
100            while (e.hasMoreElements())
101            {
102              String propertyName = (String) e.nextElement();
103              try
104              {
105                Object o = config.getInstanceOf(propertyName);
106                if (null != o)
107                {
108                  filter = (TextFilterPlugin)o;
109                  LOGGER.info(new StringBuffer(propertyName + "Loading TextFilterPlugin: ").append(filter.getName()).append(" v:").append(filter.getMajorNumber()).append('.').append(filter.getMinorNumber()).toString());
110                  for (Iterator CtIterator = filter.getSupportedContentTypes().iterator(); CtIterator.hasNext();) {
111                    // Add MIME Type filters to the basket
112                    ct = (MCRFileContentType) CtIterator.next();
113    
114                    if (ct != null) {
115                        CONTENT_TYPE_PLUGIN_BAG.put(ct, filter);
116                    }
117                }
118    
119                PLUGINS.put(filter.getClass().getName(), filter);
120                }
121                else LOGGER.info("TextFilterPlugin not available: "+ propertyName + " with property: " + props.getProperty(propertyName));
122              } catch (Exception e1)
123              {
124                LOGGER.info(e1.toString());
125              }
126           
127            }
128        }
129    
130        /**
131         * removes all plugins from the manager
132         * 
133         */
134        public void clear() {
135            init();
136        }
137    
138        /**
139         * removes all plugins and reload plugins after that
140         * 
141         * This is when you delete a plugin while the application is running,
142         * replacing one with a new version or if you just add one.
143         */
144        public void reloadPlugins() {
145            clear();
146            loadPlugins();
147        }
148    
149        /**
150         * returns a Collection of all loaded plugins.
151         * 
152         * @return a Collection of Plugins
153         */
154        public Collection getPlugins() {
155            return PLUGINS.values();
156        }
157    
158        /**
159         * returns TextFilterPlugin to corresponding MIME type
160         * 
161         * @param ct supported
162         *            MIME type
163         * @return corresponding TextFilterPlugin or null if MIME is emtpy or null
164         */
165        public TextFilterPlugin getPlugin(MCRFileContentType ct) {
166            return (ct == null) ? null : (TextFilterPlugin) CONTENT_TYPE_PLUGIN_BAG.get(ct);
167        }
168    
169        /**
170         * checks whether content type is supported
171         * 
172         * @param ct content type
173         *            of Inputstream
174         * @return true if content type is supported, else false
175         */
176        public boolean isSupported(MCRFileContentType ct) {
177            return (ct == null) ? false : CONTENT_TYPE_PLUGIN_BAG.containsKey(ct);
178        }
179    
180        /**
181         * returns a Reader for the characters of the InputStream
182         * 
183         * @param ct
184         *            ContentType of the InputStream
185         * @param input
186         *            InputStream to be parsed
187         * @return null if ContentType is unsupported, else a Reader for the parsed
188         *         characters
189         * @throws FilterPluginTransformException
190         */
191        public Reader transform(MCRFileContentType ct, InputStream input) throws FilterPluginTransformException {
192            if (isSupported(ct)) {
193                try {
194                    return getPlugin(ct).transform(ct, input);
195                } catch (Exception ex) {
196                    LOGGER.warn("Exception in text filter plug-in:", ex);
197                    return new StringReader("");
198                }
199            }
200    
201            return null;
202        }
203    
204    }