1 10 package mondrian.olap.fun; 11 12 import java.io.BufferedReader ; 13 import java.io.IOException ; 14 import java.io.InputStreamReader ; 15 import java.net.URL ; 16 import java.util.ArrayList ; 17 import java.util.Enumeration ; 18 import java.util.List ; 19 import java.util.Set ; 20 import java.util.Collection ; 21 import java.util.HashSet ; 22 23 import mondrian.olap.FunTable; 24 import mondrian.olap.Syntax; 25 import mondrian.olap.Util; 26 import mondrian.olap.type.Type; 27 import mondrian.resource.MondrianResource; 28 import mondrian.spi.UserDefinedFunction; 29 30 import org.apache.log4j.Logger; 31 32 38 public class GlobalFunTable extends FunTableImpl { 39 40 private static Logger logger = Logger.getLogger(GlobalFunTable.class); 41 42 private static GlobalFunTable instance = new GlobalFunTable(); 43 44 public static GlobalFunTable instance() { 45 return instance; 46 } 47 48 private GlobalFunTable() { 49 super(); 50 init(); 51 } 52 53 protected void defineFunctions() { 54 final FunTable builtinFunTable = BuiltinFunTable.instance(); 55 final List <String > reservedWords = builtinFunTable.getReservedWords(); 56 for (String reservedWord : reservedWords) { 57 defineReserved(reservedWord); 58 } 59 final List <Resolver> resolvers = builtinFunTable.getResolvers(); 60 for (Resolver resolver : resolvers) { 61 define(resolver); 62 } 63 64 for (String className : lookupUdfImplClasses()) { 65 defineUdf(className); 66 } 67 } 68 69 70 private Collection <String > lookupUdfImplClasses() { 71 ClassLoader cl = this.getClass().getClassLoader(); 72 List <URL > serviceUrls = new ArrayList <URL >(); 73 try { 74 Enumeration <URL > serviceEnum = cl.getResources("META-INF/services/mondrian.spi.UserDefinedFunction"); 75 for (; serviceEnum.hasMoreElements();) { 76 serviceUrls.add(serviceEnum.nextElement()); 77 } 78 } catch (IOException e) { 79 logger.warn("Error while finding service files for user-defined functions", e); 80 } 81 Set <String > classNames = new HashSet <String >(); 82 for (URL url : serviceUrls) { 83 BufferedReader reader = null; 84 try { 85 reader = 86 new BufferedReader (new InputStreamReader (url.openStream(), 87 "UTF-8")); 88 String line; 89 while ((line = reader.readLine()) != null) { 90 line = line.trim(); 91 if (line.length() > 0) { 92 if (line.charAt(0) == '#') { 93 continue; 94 } 95 int comment = line.indexOf('#'); 96 if (comment != -1) { 97 line = line.substring(0, comment).trim(); 98 } 99 classNames.add(line); 100 } 101 } 102 } catch (IOException e) { 103 logger.warn("Error when loading service file '" + url + "'", e); 104 } finally { 105 if (reader != null) { 106 try { 107 reader.close(); 108 } catch (IOException ignored) { 109 } 110 } 111 } 112 } 113 return classNames; 114 } 115 116 125 private void defineUdf(String className) { 126 final Class <?> udfClass; 128 try { 129 udfClass = Class.forName(className); 130 } catch (ClassNotFoundException e) { 131 throw MondrianResource.instance().UdfClassNotFound.ex("",className); 132 } 133 134 final UserDefinedFunction udf; 136 try { 137 udf = (UserDefinedFunction) udfClass.newInstance(); 138 } catch (InstantiationException e) { 139 throw MondrianResource.instance().UdfClassWrongIface.ex("", 140 className, UserDefinedFunction.class.getName()); 141 } catch (IllegalAccessException e) { 142 throw MondrianResource.instance().UdfClassWrongIface.ex("", 143 className, UserDefinedFunction.class.getName()); 144 } catch (ClassCastException e) { 145 throw MondrianResource.instance().UdfClassWrongIface.ex("", 146 className, UserDefinedFunction.class.getName()); 147 } 148 149 validateFunction(udf); 151 152 define(new UdfResolver(udf)); 154 } 155 156 160 private void validateFunction(final UserDefinedFunction udf) { 161 final String udfName = udf.getName(); 163 if (udfName == null || udfName.equals("")) { 164 throw Util.newInternal("User-defined function defined by class '" + 165 udf.getClass() + "' has empty name"); 166 } 167 170 final Type[] parameterTypes = udf.getParameterTypes(); 171 for (int i = 0; i < parameterTypes.length; i++) { 172 Type parameterType = parameterTypes[i]; 173 if (parameterType == null) { 174 throw Util.newInternal("Invalid user-defined function '" + 175 udfName + "': parameter type #" + i + 176 " is null"); 177 } 178 } 179 180 183 final Type returnType = udf.getReturnType(parameterTypes); 187 if (returnType == null) { 188 throw Util.newInternal("Invalid user-defined function '" + 189 udfName + "': return type is null"); 190 } 191 final Syntax syntax = udf.getSyntax(); 192 if (syntax == null) { 193 throw Util.newInternal("Invalid user-defined function '" + 194 udfName + "': syntax is null"); 195 } 196 } 197 198 199 } 200 201 | Popular Tags |