1 10 package org.mmbase.util.functions; 11 12 import org.mmbase.util.logging.Logger; 13 import org.mmbase.util.logging.Logging; 14 import org.mmbase.util.xml.DocumentReader; 15 import org.mmbase.util.*; 16 import org.mmbase.module.core.*; 17 18 import java.io.*; 19 import java.util.*; 20 import org.xml.sax.InputSource ; 21 import org.w3c.dom.*; 22 import java.net.*; 23 24 25 26 42 public class FunctionSets { 43 44 public static final String DTD_FUNCTIONSET_1_0 = "functionset_1_0.dtd"; 45 public static final String DTD_FUNCTIONSETS_1_0 = "functionsets_1_0.dtd"; 46 47 public static final String PUBLIC_ID_FUNCTIONSET_1_0 = "-//MMBase//DTD functionset config 1.0//EN"; 48 public static final String PUBLIC_ID_FUNCTIONSETS_1_0 = "-//MMBase//DTD functionsets config 1.0//EN"; 49 50 private static final Logger log = Logging.getLoggerInstance(FunctionSets.class); 51 52 private static final Map functionSets = new HashMap(); 53 54 static { 55 XMLEntityResolver.registerPublicID(PUBLIC_ID_FUNCTIONSET_1_0, DTD_FUNCTIONSET_1_0, FunctionSets.class); 56 XMLEntityResolver.registerPublicID(PUBLIC_ID_FUNCTIONSETS_1_0, DTD_FUNCTIONSETS_1_0, FunctionSets.class); 57 } 58 59 67 public static Function getFunction(String setName, String functionName) { 68 FunctionSet set = getFunctionSet(setName); 69 if (set != null) { 70 Function fun = set.getFunction(functionName); 71 if (fun != null) { 72 return fun; 73 } else { 74 log.warn("No function with name : " + functionName + " in set : " + setName + ", functions available: " + set); 75 } 76 } else { 77 log.warn("No functionset with name : " + setName); 78 } 79 return null; 80 } 81 82 static { 83 ResourceLoader functionLoader = ResourceLoader.getConfigurationRoot().getChildResourceLoader("functions"); 84 try { 86 ResourceWatcher watcher = new ResourceWatcher(functionLoader) { 87 public void onChange(String resource) { 88 functionSets.clear(); 89 clear(); 90 add(resource); 91 readSets(this); 92 } 93 }; 94 watcher.start(); 95 watcher.onChange("functionsets.xml"); 96 } catch (Throwable t) { 97 log.error(t.getClass().getName() + ": " + Logging.stackTrace(t)); 98 } 99 100 } 101 102 110 public static FunctionSet getFunctionSet(String setName) { 111 return (FunctionSet)functionSets.get(setName); 112 } 113 114 119 120 private static void readSets(ResourceWatcher watcher) { 121 122 List resources = watcher.getResourceLoader().getResourceList("functionsets.xml"); 123 log.service("Using " + resources); 124 ListIterator i = resources.listIterator(); 125 while (i.hasNext()) i.next(); 126 while (i.hasPrevious()) { 127 try { 128 URL u = (URL) i.previous(); 129 log.service("Reading " + u); 130 URLConnection con = u.openConnection(); 131 if (con.getDoInput()) { 132 InputSource source = new InputSource (con.getInputStream()); 133 DocumentReader reader = new DocumentReader(source, FunctionSets.class); 134 135 for(Iterator ns = reader.getChildElements("functionsets", "functionset"); ns.hasNext(); ) { 136 Element n = (Element)ns.next(); 137 138 String setName = n.getAttribute("name"); 139 if (functionSets.containsKey(setName)) { 140 log.warn("The function-set '" + setName + "' did exist already"); 141 } 142 String setResource = n.getAttribute("resource"); 143 if (setResource.equals("")) setResource = n.getAttribute("file"); watcher.add(setResource); 145 decodeFunctionSet(watcher.getResourceLoader(), setResource, setName); 146 } 147 } 148 } catch (Exception e) { 149 log.error(e); 150 } 151 } 152 } 153 154 160 private static void decodeFunctionSet(ResourceLoader loader, String setResource, String setName) throws IOException { 161 DocumentReader reader = new DocumentReader(loader.getInputSource(setResource), FunctionSets.class); 162 163 String setDescription = reader.getElementValue("functionset.description"); 164 165 FunctionSet functionSet = new FunctionSet(setName, setDescription); 166 functionSets.put(setName, functionSet); 167 168 for (Iterator functionElements = reader.getChildElements("functionset", "function"); functionElements.hasNext();) { 169 Element element = (Element)functionElements.next(); 170 String functionName = reader.getElementAttributeValue(element,"name"); 171 if (functionName != null) { 172 173 Element a = reader.getElementByPath(element, "function.type"); 174 175 String type = reader.getElementValue(a); 177 a = reader.getElementByPath(element, "function.description"); 178 String description = reader.getElementValue(a); 179 180 a = reader.getElementByPath(element, "function.class"); 181 String className = reader.getElementValue(a); 182 183 a = reader.getElementByPath(element, "function.method"); 184 String methodName = reader.getElementValue(a); 185 186 a = reader.getElementByPath(element, "function.return"); 188 ReturnType returnType = null; 189 if (a != null) { 190 String returnTypeClassName = reader.getElementAttributeValue(a, "type"); 191 if (returnTypeClassName != null) { 192 try { 193 Class returnTypeClass = getClassFromName(returnTypeClassName); 194 returnType = new ReturnType(returnTypeClass, ""); 195 } catch (Exception e) { 196 log.warn("Cannot determine return type : " + returnTypeClassName + ", will auto-detect"); 197 } 198 } 199 } 200 201 202 215 216 List parameterList = new ArrayList(); 218 for (Iterator parameterElements = reader.getChildElements(element,"param"); parameterElements.hasNext();) { 219 Element parameterElement = (Element)parameterElements.next(); 220 String parameterName = reader.getElementAttributeValue(parameterElement, "name"); 221 String parameterType = reader.getElementAttributeValue(parameterElement, "type"); 222 String required = reader.getElementAttributeValue(parameterElement, "required"); 223 description = reader.getElementAttributeValue(parameterElement, "description"); 224 225 Parameter parameter = null; 226 227 Class parameterClass = getClassFromName(parameterType); 228 parameter = new Parameter(parameterName, parameterClass); 229 parameter.dataType.setRequired("true".equals(required)); 230 231 if (parameterClass.isPrimitive() && parameter.getDefaultValue() == null && ! parameter.isRequired()) { 232 parameter.setDefaultValue(Casting.toType(parameterClass, new Integer (-1))); 234 log.info("Primitive parameter '" + parameterName + "' had default value null, which is impossible for primitive types. Setting to " + parameter.getDefaultValue()); 235 } 236 org.w3c.dom.Node n3 = parameterElement.getFirstChild(); 238 if (n3 != null) { 239 parameter.setDefaultValue(parameter.autoCast(n3.getNodeValue())); 240 } 241 parameterList.add(parameter); 242 243 } 244 245 Parameter[] parameters = (Parameter[]) parameterList.toArray(new Parameter[0]); 246 247 try { 248 SetFunction fun = new SetFunction(functionName, parameters, returnType, className, methodName); 249 fun.setType(type); 250 fun.setDescription(description); 251 functionSet.addFunction(fun); 252 } catch (Exception e) { 253 log.error(e); 254 log.error(Logging.stackTrace(e)); 255 log.error(Logging.stackTrace(e.getCause())); 256 } 257 } 258 } 259 } 260 261 265 private static Class getClassFromName(String className) { 266 String fullClassName = className; 267 boolean fullyQualified = className.indexOf('.') > -1; 268 if (!fullyQualified) { 269 if (className.equals("int")) { return int.class; 271 } else if (className.equals("NodeList")) { 272 return org.mmbase.bridge.NodeList.class; 273 } else if (className.equals("Node")) { 274 return org.mmbase.bridge.Node.class; 275 } 276 fullClassName = "java.lang." + fullClassName; 277 } 278 try { 279 return Class.forName(fullClassName); 280 } catch (ClassNotFoundException cne) { 281 log.warn("Cannot determine parameter type : '" + className + "' (expanded to: '" + fullClassName + "'), using Object as type instead."); 282 return Object .class; 283 } 284 } 285 286 } 287 | Popular Tags |