001 /* 002 * mesopotamia @mesopotamia.version@ 003 * Multilingual parser and repository. 004 * Copyright (C) 2005 Hammurapi Group 005 * 006 * This program is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 2 of the License, or (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with this library; if not, write to the Free Software 018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 019 * 020 * URL: http://http://www.hammurapi.biz 021 * e-Mail: support@hammurapi.biz 022 */ 023 package org.mesopotamia; 024 025 import gnu.trove.TIntHashSet; 026 import gnu.trove.TIntIterator; 027 028 import java.lang.reflect.InvocationTargetException; 029 import java.sql.ResultSet; 030 import java.sql.SQLException; 031 import java.util.logging.Logger; 032 033 import org.mesopotamia.sql.LoaderImpl; 034 035 import biz.hammurapi.config.ConfigurationException; 036 import biz.hammurapi.config.StringConfigurable; 037 import biz.hammurapi.eval.CircularReferenceException; 038 import biz.hammurapi.sql.RowProcessor; 039 import biz.hammurapi.sql.SQLExceptionEx; 040 041 042 /** 043 * Holds loader instance 044 * @author Pavel Vlasov 045 * @revision $Revision$ 046 */ 047 public class LoaderEntry extends LoaderImpl { 048 private Loader loader; 049 private TIntHashSet masters=new TIntHashSet(); 050 private RepositoryLanguage repoLanguage; 051 private static final Logger logger = Logger.getLogger(LoaderEntry.class.getName()); 052 053 /** 054 * @param rs 055 * @throws SQLException 056 */ 057 public LoaderEntry(RepositoryLanguage repoLanguage, ResultSet rs) throws SQLException { 058 super(rs); 059 this.repoLanguage=repoLanguage; 060 try { 061 loader=(Loader) repoLanguage.getClassLoader().loadClass(getLoaderClass()).getConstructor( 062 new Class[] {RepositoryLanguage.class, LoaderEntry.class}). 063 newInstance(new Object[] {repoLanguage, this}); 064 065 if (getLoaderConfig()!=null) { 066 if (loader instanceof StringConfigurable) { 067 try { 068 ((StringConfigurable) loader).configure(getLoaderConfig(), null); 069 } catch (ConfigurationException e) { 070 throw new SQLExceptionEx("Could not configure loader: "+e, e); 071 } 072 } else { 073 logger.warning("Loader "+loader.getClass().getName()+ 074 " has not null configuration, but it doesn't implement "+ 075 StringConfigurable.class.getName()); 076 } 077 } 078 079 repoLanguage.getFactory().getEngine().processLoaderDependencyByDependentLevel( 080 rs.getInt("ID"), 081 new RowProcessor() { 082 083 public boolean process(ResultSet rs) throws SQLException { 084 masters.add(rs.getInt("DEPENDS_ON_LEVEL_ID")); 085 return true; 086 } 087 088 }); 089 } catch (InstantiationException e) { 090 throw new SQLExceptionEx("Cannot instantiate loader "+getLoaderClass(), e); 091 } catch (IllegalAccessException e) { 092 throw new SQLExceptionEx("Cannot instantiate loader "+getLoaderClass(), e); 093 } catch (ClassNotFoundException e) { 094 throw new SQLExceptionEx("Cannot instantiate loader "+getLoaderClass(), e); 095 } catch (SecurityException e) { 096 throw new SQLExceptionEx("Cannot instantiate loader "+getLoaderClass(), e); 097 } catch (InvocationTargetException e) { 098 throw new SQLExceptionEx("Cannot instantiate loader "+getLoaderClass(), e); 099 } catch (NoSuchMethodException e) { 100 throw new SQLExceptionEx("Cannot instantiate loader "+getLoaderClass(), e); 101 } 102 } 103 104 Loader getLoader() { 105 return loader; 106 } 107 108 boolean dependsOn(int master, int originalMaster) { 109 if (getId()==originalMaster) { 110 throw new CircularReferenceException("Circular reference in loader dependency: ["+originalMaster+"] "+getLevel()); 111 } 112 113 if (masters.contains(master)) { 114 return true; 115 } 116 117 TIntIterator it=masters.iterator(); 118 while (it.hasNext()) { 119 if (((LoaderEntry) repoLanguage.loadersMap.get(it.next())).dependsOn(master, originalMaster)) { 120 return true; 121 } 122 } 123 124 return false; 125 } 126 127 boolean isScanDependent() { 128 return isScanDependent(null); 129 } 130 131 /** 132 * @return true if this loader is not dependent of any others 133 */ 134 boolean isIndependent() { 135 return masters.isEmpty(); 136 } 137 138 private boolean isScanDependent(String startingLevel) { 139 if (getScanDependent()) { 140 return true; 141 } 142 143 if (getLevel().equals(startingLevel)) { 144 throw new CircularReferenceException("Circular reference in loader dependency: "+getLevel()); 145 } 146 147 String actualStartingLevel = startingLevel==null ? getLevel() : startingLevel; 148 TIntIterator mit=masters.iterator(); 149 while (mit.hasNext()) { 150 if (((LoaderEntry) repoLanguage.loadersMap.get(mit.next())).isScanDependent(actualStartingLevel)) { 151 return true; 152 } 153 } 154 155 return false; 156 } 157 158 /** 159 * @param loadLevels 160 * @return true if all prerequisite levels were loaded 161 * and this level wasn't. 162 */ 163 boolean isCompatible(TIntHashSet loadLevels) { 164 return !loadLevels.contains(getId()) && loadLevels.containsAll(masters.toArray()); 165 } 166 167 }