001    /*
002     * 
003     * $Revision: 13085 $ $Date: 2008-02-06 18:27:24 +0100 (Mi, 06 Feb 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.datamodel.ifs;
025    
026    import java.util.Hashtable;
027    
028    import org.apache.log4j.Logger;
029    import org.mycore.common.MCRArgumentChecker;
030    import org.mycore.common.MCRConfiguration;
031    import org.mycore.common.MCRConfigurationException;
032    import org.mycore.common.MCRException;
033    
034    /**
035     * This class manages instances of MCRContentStore and MCRAudioVideoExtender and
036     * provides methods to get these for a given Store ID or MCRFile instance. The
037     * class is responsible for looking up, loading, instantiating and remembering
038     * the implementations of MCRContentStore and MCRAudioVideoExtender that are
039     * used in the system.
040     * 
041     * @author Frank Lützenkirchen
042     * @author Thomas Scheffler (yagee)
043     * @version $Revision: 13085 $ $Date: 2008-02-06 18:27:24 +0100 (Mi, 06 Feb 2008) $
044     */
045    public class MCRContentStoreFactory {
046        /** Hashtable StoreID to MCRContentStore instance */
047        protected static Hashtable STORES;
048    
049        /** Hashtable StoreID to Class that implements MCRAudioVideoExtender */
050        protected static Hashtable EXTENDER_CLASSES;
051    
052        /**
053         * Hashtable StoreID to MCRContentStore implementing
054         * {@link org.mycore.services.query.MCRTextSearchInterface}
055         */
056        protected static Hashtable INDEX_STORES;
057    
058        /** The MCRContentStoreSelector implementation that will be used */
059        protected static MCRContentStoreSelector STORE_SELECTOR;
060    
061        private static final Logger LOGGER = Logger.getLogger(MCRContentStoreFactory.class);
062    
063        /**
064         * Returns the MCRContentStore instance that is configured for this StoreID.
065         * The instance that is returned is configured by the property
066         * <tt>MCR.IFS.ContentStore.<StoreID>.Class</tt> in mycore.properties.
067         * 
068         * @param storeID
069         *            the non-null ID of the MCRContentStore implementation
070         * @return the MCRContentStore instance that uses this storeID
071         * @throws MCRConfigurationException
072         *             if no MCRContentStore implementation is configured for this
073         *             storeID
074         */
075        public static MCRContentStore getStore(String storeID) {
076            if (STORES == null) {
077                STORES = new Hashtable();
078            }
079    
080            if (INDEX_STORES == null) {
081                INDEX_STORES = new Hashtable();
082            }
083    
084            MCRArgumentChecker.ensureNotEmpty(storeID, "Store ID");
085    
086            if (!STORES.containsKey(storeID)) {
087                try {
088                    String storeClass = "MCR.IFS.ContentStore." + storeID + ".Class";
089                    LOGGER.debug("getting StoreClass: " + storeClass);
090    
091                    Object obj = MCRConfiguration.instance().getInstanceOf(storeClass);
092                    MCRContentStore s = (MCRContentStore) (obj);
093                    s.init(storeID);
094                    STORES.put(storeID, s);
095    
096                } catch (Exception ex) {
097                    String msg = "Could not load MCRContentStore with store ID = " + storeID;
098                    throw new MCRConfigurationException(msg, ex);
099                }
100            }
101    
102            return (MCRContentStore) (STORES.get(storeID));
103        }
104    
105        /**
106         * Returns the MCRContentStore instance that should be used to store the
107         * content of the given file. The configured MCRContentStoreSelector is used
108         * to make this decision.
109         * 
110         * @see MCRContentStoreSelector
111         * @see MCRContentStore
112         */
113        public static MCRContentStore selectStore(MCRFile file) {
114            if (STORE_SELECTOR == null) {
115                initStoreSelector();
116            }
117    
118            String store = STORE_SELECTOR.selectStore(file);
119    
120            return getStore(store);
121        }
122    
123        private static void initStoreSelector() {
124            String property = "MCR.IFS.ContentStoreSelector.Class";
125            Object obj = MCRConfiguration.instance().getInstanceOf(property);
126            STORE_SELECTOR = (MCRContentStoreSelector) obj;
127        }
128    
129        /**
130         * Returns the Class instance that implements the MCRAudioVideoExtender for
131         * the MCRContentStore with the given ID. That class is configured by the
132         * property <tt>MCR.IFS.AVExtender.<StoreID>.Class</tt> in
133         * mycore.properties.
134         * 
135         * @param storeID
136         *            the non-null StoreID of the MCRContentStore
137         * @return the Class that implements MCRAudioVideoExtender for the StoreID
138         *         given, or null
139         * @throws MCRConfigurationException
140         *             if the MCRAudioVideoExtender implementation class could not
141         *             be loaded
142         */
143        protected static Class getExtenderClass(String storeID) {
144            if (EXTENDER_CLASSES == null) {
145                EXTENDER_CLASSES = new Hashtable();
146            }
147    
148            MCRArgumentChecker.ensureNotNull(storeID, "store ID");
149    
150            String storeClass = "MCR.IFS.AVExtender." + storeID + ".Class";
151    
152            String value = MCRConfiguration.instance().getString(storeClass, "");
153    
154            if (value.equals("")) {
155                return null;
156            }
157    
158            if (!EXTENDER_CLASSES.containsKey(storeID)) {
159                try {
160                    Class cl = Class.forName(value);
161                    EXTENDER_CLASSES.put(storeID, cl);
162                } catch (Exception ex) {
163                    String msg = "Could not load AudioVideoExtender class " + value;
164                    throw new MCRConfigurationException(msg, ex);
165                }
166            }
167    
168            return (Class) (EXTENDER_CLASSES.get(storeID));
169        }
170    
171        /**
172         * Returns true if the MCRContentStore with the given StoreID provides an
173         * MCRAudioVideoExtender implementation, false otherwise. The
174         * MCRAudioVideoExtender for a certain MCRContentStore is configured by the
175         * property <tt>MCR.IFS.AVExtender.<StoreID>.Class</tt> in
176         * mycore.properties.
177         * 
178         * @param storeID
179         *            the non-null StoreID of the MCRContentStore
180         * @return the MCRAudioVideoExtender for the StoreID given, or null
181         * @throws MCRConfigurationException
182         *             if the MCRAudioVideoExtender implementation class could not
183         *             be loaded
184         */
185        static boolean providesAudioVideoExtender(String storeID) {
186            return (getExtenderClass(storeID) != null);
187        }
188    
189        /**
190         * If the MCRContentStore of the MCRFile given provides an
191         * MCRAudioVideoExtender implementation, this method creates and initializes
192         * the MCRAudioVideoExtender instance for the MCRFile. The instance that is
193         * returned is configured by the property
194         * <tt>MCR.IFS.AVExtender.<StoreID>.Class</tt> in mycore.properties.
195         * 
196         * @param file
197         *            the non-null MCRFile that should get an MCRAudioVideoExtender
198         * @return the MCRAudioVideoExtender for the MCRFile given, or null
199         * @throws MCRConfigurationException
200         *             if the MCRAudioVideoExtender implementation class could not
201         *             be loaded
202         */
203        static MCRAudioVideoExtender buildExtender(MCRFileReader file) {
204            MCRArgumentChecker.ensureNotNull(file, "file");
205    
206            if (!providesAudioVideoExtender(file.getStoreID())) {
207                return null;
208            }
209    
210            Class cl = getExtenderClass(file.getStoreID());
211    
212            try {
213                Object obj = cl.newInstance();
214                MCRAudioVideoExtender ext = (MCRAudioVideoExtender) obj;
215                ext.init(file);
216    
217                return ext;
218            } catch (Exception exc) {
219                if (exc instanceof MCRException) {
220                    throw (MCRException) exc;
221                }
222    
223                String msg = "Could not build MCRAudioVideoExtender instance";
224                throw new MCRConfigurationException(msg, exc);
225            }
226        }
227    }