1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.jxpath;
19
20 import java.lang.reflect.Constructor;
21 import java.lang.reflect.Method;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Iterator;
25 import java.util.Objects;
26 import java.util.Set;
27
28 import org.apache.commons.jxpath.functions.ConstructorFunction;
29 import org.apache.commons.jxpath.functions.MethodFunction;
30 import org.apache.commons.jxpath.util.ClassLoaderUtil;
31 import org.apache.commons.jxpath.util.MethodLookupUtils;
32 import org.apache.commons.jxpath.util.TypeUtils;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 public class PackageFunctions implements Functions {
68
69 private static final Object[] EMPTY_ARRAY = {};
70 private final String classPrefix;
71 private final String namespace;
72
73
74
75
76
77
78
79 public PackageFunctions(final String classPrefix, final String namespace) {
80 this.classPrefix = classPrefix;
81 this.namespace = namespace;
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99 @Override
100 public Function getFunction(final String namespace, final String name, Object[] parameters) {
101 if (!Objects.equals(this.namespace, namespace)) {
102 return null;
103 }
104 if (parameters == null) {
105 parameters = EMPTY_ARRAY;
106 }
107 if (parameters.length >= 1) {
108 Object target = TypeUtils.convert(parameters[0], Object.class);
109 if (target != null) {
110 Method method = MethodLookupUtils.lookupMethod(target.getClass(), name, parameters);
111 if (method != null) {
112 return new MethodFunction(method);
113 }
114 if (target instanceof NodeSet) {
115 target = ((NodeSet) target).getPointers();
116 }
117 method = MethodLookupUtils.lookupMethod(target.getClass(), name, parameters);
118 if (method != null) {
119 return new MethodFunction(method);
120 }
121 if (target instanceof Collection) {
122 final Iterator iter = ((Collection) target).iterator();
123 if (iter.hasNext()) {
124 target = iter.next();
125 if (target instanceof Pointer) {
126 target = ((Pointer) target).getValue();
127 }
128 } else {
129 target = null;
130 }
131 }
132 }
133 if (target != null) {
134 final Method method = MethodLookupUtils.lookupMethod(target.getClass(), name, parameters);
135 if (method != null) {
136 return new MethodFunction(method);
137 }
138 }
139 }
140 final String fullName = classPrefix + name;
141 final int inx = fullName.lastIndexOf('.');
142 if (inx == -1) {
143 return null;
144 }
145 final String className = fullName.substring(0, inx);
146 final String methodName = fullName.substring(inx + 1);
147 Class<?> functionClass;
148 try {
149 functionClass = ClassLoaderUtil.getClass(className, true);
150 } catch (final ClassNotFoundException ex) {
151 throw new JXPathException("Cannot invoke extension function " + (namespace != null ? namespace + ":" + name : name), ex);
152 }
153 if (methodName.equals("new")) {
154 final Constructor constructor = MethodLookupUtils.lookupConstructor(functionClass, parameters);
155 if (constructor != null) {
156 return new ConstructorFunction(constructor);
157 }
158 } else {
159 final Method method = MethodLookupUtils.lookupStaticMethod(functionClass, methodName, parameters);
160 if (method != null) {
161 return new MethodFunction(method);
162 }
163 }
164 return null;
165 }
166
167
168
169
170
171
172 @Override
173 public Set<String> getUsedNamespaces() {
174 return Collections.singleton(namespace);
175 }
176 }