001: /*--
002:
003: Copyright (C) 2002-2005 Adrian Price.
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009:
010: 1. Redistributions of source code must retain the above copyright
011: notice, this list of conditions, and the following disclaimer.
012:
013: 2. Redistributions in binary form must reproduce the above copyright
014: notice, this list of conditions, and the disclaimer that follows
015: these conditions in the documentation and/or other materials
016: provided with the distribution.
017:
018: 3. The names "OBE" and "Open Business Engine" must not be used to
019: endorse or promote products derived from this software without prior
020: written permission. For written permission, please contact
021: adrianprice@sourceforge.net.
022:
023: 4. Products derived from this software may not be called "OBE" or
024: "Open Business Engine", nor may "OBE" or "Open Business Engine"
025: appear in their name, without prior written permission from
026: Adrian Price (adrianprice@users.sourceforge.net).
027:
028: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
029: WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
030: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
031: DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
032: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
033: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
034: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
035: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
036: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
037: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
038: POSSIBILITY OF SUCH DAMAGE.
039:
040: For more information on OBE, please see
041: <http://obe.sourceforge.net/>.
042:
043: */
044:
045: package org.obe.client.api.repository;
046:
047: import org.apache.commons.logging.Log;
048: import org.apache.commons.logging.LogFactory;
049: import org.obe.util.ClassUtils;
050: import org.obe.xpdl.model.data.*;
051: import org.xml.sax.EntityResolver;
052:
053: import java.lang.reflect.Method;
054: import java.util.Arrays;
055:
056: /**
057: * Describes a procedure implemented by a Java class.
058: *
059: * @author Adrian Price
060: */
061: public class JavaMethodMetaData extends ToolAgentMetaData {
062: private static final long serialVersionUID = -285543509428840735L;
063: private static final Log _logger = LogFactory
064: .getLog(JavaMethodMetaData.class);
065: private static final String IMPL_CLASS = "org.obe.runtime.tool.JavaMethod";
066: private static final String[] IMPL_CTOR_SIG = { JavaMethodMetaData.class
067: .getName() };
068: protected String _className;
069: protected String _method;
070: protected String[] _methodSig;
071:
072: public JavaMethodMetaData() {
073: }
074:
075: // TODO: find a way to pass the target to the execute method.
076: public JavaMethodMetaData(String id, String displayName,
077: String description, String docUrl, String author,
078: String clazz, String method, String[] methodArgTypes) {
079:
080: super (id, displayName, description, docUrl, author, true);
081: _className = clazz;
082: _method = method;
083: _methodSig = methodArgTypes;
084: }
085:
086: private JavaMethodMetaData(String className, String methodSig)
087: throws ClassNotFoundException, NoSuchMethodException {
088:
089: Method method = ClassUtils.findMethod(className, methodSig);
090: Class[] parmTypes = method.getParameterTypes();
091: _className = method.getDeclaringClass().getName();
092: _methodSig = ClassUtils.namesForClasses(parmTypes);
093: _formalParameters = new FormalParameter[parmTypes.length];
094: for (int i = 0; i < parmTypes.length; i++) {
095: Class parmType = parmTypes[i];
096: // TODO: Support INOUT parameter mode via ~Holder classes.
097: _formalParameters[i] = new FormalParameter("p" + i, null,
098: ParameterMode.IN, DataTypes
099: .dataTypeForClass(parmType),
100: "Java parameter type is " + parmType.getName());
101: }
102:
103: if (_logger.isDebugEnabled()) {
104: _logger.debug("introspect: _formalParameters="
105: + _formalParameters);
106: }
107: }
108:
109: public ToolAgentMetaData introspect(ExternalReference extRef,
110: EntityResolver entityResolver) throws RepositoryException {
111:
112: // If the location has a java: prefix or looks like a fully qualified
113: // Java class name, attempt to introspect it as such.
114: String location = extRef.getLocation();
115: boolean javaPrefix = location.startsWith("java:");
116: String className = javaPrefix ? location.substring(5)
117: : location;
118: int n = location.length();
119: boolean validClassName = n != 0;
120: for (int i = 0; i < n; i++) {
121: char c = className.charAt(i);
122: if (i != 0 && !Character.isJavaIdentifierPart(c) || i == 0
123: && !Character.isJavaIdentifierStart(c)) {
124:
125: validClassName = false;
126: break;
127: }
128: }
129:
130: JavaMethodMetaData metaData = null;
131: if (validClassName) {
132: try {
133: metaData = new JavaMethodMetaData(className, extRef
134: .getXref());
135: } catch (ClassNotFoundException e) {
136: throw new RepositoryException(e);
137: } catch (NoSuchMethodException e) {
138: throw new RepositoryException(e);
139: }
140: }
141: return metaData;
142: }
143:
144: public void init() {
145: if (_methodSig == null)
146: return;
147:
148: // Load the classes referenced by the method signature.
149: Class[] methodSig;
150: try {
151: methodSig = ClassUtils.classesForNames(_methodSig);
152: } catch (ClassNotFoundException e) {
153: _logger.error("init() error in " + this , e);
154: return;
155: }
156:
157: // Since we have a method signature, we also need formal parameters.
158: if (_formalParameters == null)
159: _formalParameters = new FormalParameter[methodSig.length];
160:
161: // Ensure that every formal parameter has a data type.
162: int len = Math.min(methodSig.length, _formalParameters.length);
163: for (int i = 0; i < len; i++) {
164: FormalParameter parm = _formalParameters[i];
165:
166: // Make sure we know what data type this parameter has.
167: DataType dataType = parm == null ? null : parm
168: .getDataType();
169: if (dataType == null)
170: dataType = DataTypes.dataTypeForClass(methodSig[i]);
171:
172: // Create any missing formal parameter.
173: if (parm == null) {
174: _formalParameters[i] = new FormalParameter("arg" + i,
175: null, ParameterMode.IN, dataType, null);
176: } else {
177: // Make sure every formal parameter has an ID and a data type.
178: if (parm.getId() == null)
179: parm.setId("arg" + i);
180: if (parm.getDataType() == null)
181: parm.setDataType(dataType);
182: }
183: }
184: }
185:
186: protected String getImplClass() {
187: return IMPL_CLASS;
188: }
189:
190: protected String[] getImplCtorSig() {
191: return IMPL_CTOR_SIG;
192: }
193:
194: public String getClassName() {
195: return _className != null ? _className : _type == null
196: || !allowInheritance ? null
197: : ((JavaMethodMetaData) _type).getClassName();
198: }
199:
200: public void setClassName(String className) {
201: _className = className;
202: }
203:
204: public String getMethod() {
205: return _method != null ? _method : _type == null
206: || !allowInheritance ? null
207: : ((JavaMethodMetaData) _type).getMethod();
208: }
209:
210: public void setMethod(String method) {
211: _method = method;
212: }
213:
214: public String[] getMethodSig() {
215: return _methodSig != null ? _methodSig : _type == null
216: || !allowInheritance ? null
217: : ((JavaMethodMetaData) _type).getMethodSig();
218: }
219:
220: public void setMethodSig(String[] methodSig) {
221: _methodSig = methodSig;
222: }
223:
224: public String toString() {
225: return "JavaMethodMetaData[id='"
226: + _id
227: + "', implClass='"
228: + IMPL_CLASS
229: + "', implCtorSig="
230: + (IMPL_CTOR_SIG == null ? null : Arrays
231: .asList(IMPL_CTOR_SIG))
232: + ", displayName='"
233: + _displayName
234: + "', description='"
235: + _description
236: + "', docUrl='"
237: + _docUrl
238: + "', author='"
239: + _author
240: + "', threadsafe="
241: + _threadsafe
242: + "', className="
243: + _className
244: + "', method="
245: + _method
246: + "', methodSig="
247: + (_methodSig == null ? null : Arrays
248: .asList(_methodSig)) + ",_type=" + _type + ']';
249: }
250: }
|