/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* @author Neeraj Joshi <jneeraj@us.ibm.com>
*
*/
package org.apache.imperius.javaspl;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import org.apache.imperius.spl.core.Argument;
import org.apache.imperius.spl.core.DataCollector;
import org.apache.imperius.spl.core.TypeConstants;
import org.apache.imperius.spl.parser.compiler.symboltable.MethodSymbol;
import org.apache.imperius.spl.parser.compiler.symboltable.PropertySymbol;
import org.apache.imperius.spl.parser.compiler.symboltable.Symbol;
import org.apache.imperius.spl.parser.exceptions.SPLException;
import org.apache.imperius.spl.parser.statements.impl.ArgumentImpl;
public class JavaDataCollectorImpl implements DataCollector {
private URL[] fUrls = null;
public JavaDataCollectorImpl() {
}
public JavaDataCollectorImpl(URL[] urls) {
fUrls = urls;
}
/**
* Use reflection to retrieve properties of the given class and load them into
* the symbol map
* @param className
* @param symbolMap
* @throws SPLException
*/
private void _populateClassMembers(String className, Map symbolMap)
throws SPLException {
Class c;
try {
// Load class
if(fUrls == null) {
c = Class.forName(className);
} else {
URLClassLoader uc = new URLClassLoader(fUrls);
c = uc.loadClass(className);
}
// Iterate over it's fields
Field[] fields = c.getFields();
for (int i = 0; i < fields.length; i++) {
Field f = fields[i];
String fieldName = f.getName();
String javaType = f.getType().toString();
// Retrieve the SPL type constant corresponding to the java type
int internalType = JavaSPLTypeConstants.convertJavaTypeToInternalType(javaType);
// check if its an array
boolean isArray = JavaSPLTypeConstants.getIsArray(javaType);
// if type is reference get the class name
String referenceTypeName = "";
if (internalType == TypeConstants.referenceType) {
referenceTypeName = JavaSPLTypeConstants.getReferenceTypeName(javaType);
}
boolean isPropertyOfClass = true;
boolean isKey = false;
// create a new property symbol object
Symbol s = new PropertySymbol(f.getName(), internalType,
referenceTypeName, isArray, isKey, isPropertyOfClass);
// insert into map
// xiping's test 06/19/09
// a Java class field name must be unique
symbolMap.put(fieldName, s);
}
} catch (Exception e) {
e.printStackTrace();
throw new SPLException(e.getMessage());
}
}
/**
* Use reflection to retrieve the public methods supported by the given class
* and populate into the given Map
* @param className
* @param symbolMap
* @throws SPLException
*/
private void _populateClassMethods(String className, Map symbolMap)
throws SPLException {
Class c;
try {
// Load Class
if(fUrls == null) {
c = Class.forName(className);
} else {
URLClassLoader uc = new URLClassLoader(fUrls);
c = uc.loadClass(className);
}
// Iterate over the methods
Method[] methods = c.getMethods();
for (int j = 0; j < methods.length; j++) {
Method m = methods[j];
String methodName = m.getName();
String returnType = m.getReturnType().getName();
// Retrieve the SPL type constant corresponding to the java method return type
int internalReturnType = JavaSPLTypeConstants.convertJavaTypeToInternalType(returnType);
// In case of type reference retrieve the class name
String returnReferenceTypeName = "";
if (internalReturnType == TypeConstants.referenceType) {
returnReferenceTypeName = JavaSPLTypeConstants.getReferenceTypeName(returnType);
}
// Check if returning an array
boolean isReturnArray = JavaSPLTypeConstants.getIsArray(returnType);
// Get the list of formal parameters to the method
Class[] paramTypes = m.getParameterTypes();
List argTypeList = new ArrayList();
// Iterate over the formal parameters
for (int k = 0; k < paramTypes.length; k++) {
Class p = paramTypes[k];
String javaType = p.getName();
// Get the SPL type constant for the java type of the paramter
int internalType = JavaSPLTypeConstants.convertJavaTypeToInternalType(javaType);
// Get the class name in case of Reference type
String referenceTypeName = "";
if (internalType == TypeConstants.referenceType) {
referenceTypeName = JavaSPLTypeConstants
.getReferenceTypeName(javaType);
}
// check if array
boolean isArray = JavaSPLTypeConstants.getIsArray(javaType);
// Construct an argument object
Argument param;
String paramName = "";
try {
param = new ArgumentImpl(internalType, paramName, isArray, referenceTypeName);
argTypeList.add(param);
} catch (SPLException e) {
e.printStackTrace();
throw new SPLException(e.getMessage());
}
}
// construct a method symbol
Symbol s = new MethodSymbol(methodName, internalReturnType, isReturnArray, returnReferenceTypeName, argTypeList, null);
// // Insert into map
// symbolMap.put(methodName, s);
// xiping's test 06/19/09
// a Java class can have multiple methods that have the same method name
Vector v = null;
if (symbolMap.containsKey(methodName)) {
v = (Vector) symbolMap.get(methodName);
} else {
v = new Vector();
}
v.add(s);
symbolMap.put(methodName, v);
//
}
} catch (Exception e) {
e.printStackTrace();
throw new SPLException(e.getMessage());
}
}
public Map getSymbolsForClass(String className, String qualifier) throws SPLException {
String formattedClass = null;
if (className.startsWith("\"")) // string of form ""lkasdlk""
{
formattedClass = className.substring(1, className.length() - 1);
} else {
formattedClass = className;
}
Map symbolMap = new Hashtable();
_populateClassMembers(formattedClass, symbolMap);
_populateClassMethods(formattedClass, symbolMap);
return symbolMap;
}
/**
* Get symbols for the given instance
*/
public Map getSymbolsForInstance(String className, String qualifier, Object instance) throws SPLException {
Map instanceMemberValues = new Hashtable();
Class c;
try {
// Load the class
if(fUrls == null) {
c = Class.forName(className);
} else {
URLClassLoader uc = new URLClassLoader(fUrls);
c = uc.loadClass(className);
}
Field[] fields = c.getFields();
// Iterate over the fields
for (int i = 0; i < fields.length; i++) {
Field f = fields[i];
// Get the instance value of the current field
Object value = f.get(instance);
String fieldName = f.getName();
// Insert into map
if (value != null) { // value is not null
instanceMemberValues.put(fieldName, value);
} else { //value is null so insert empty object
// in case the policy part of the action would
// like to set it to something
instanceMemberValues.put(fieldName, new Object());
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new SPLException(e.getMessage());
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw new SPLException(e.getMessage());
} catch (IllegalAccessException e) {
e.printStackTrace();
throw new SPLException(e.getMessage());
}
return instanceMemberValues;
}
/**
* Not applicable for java spl
*/
public boolean associationExists(String nameSpace, String className,
String resultClass, String assocClass, String role, String resultRole) throws SPLException {
throw new SPLException("associationExists not supported in JAVA-SPL");
}
public List getAssociatedInstanceReferences(Object srcReference,
String classPath, String resultInstancesClassFilter,
String assocClass, String role, String resultRole) throws SPLException {
throw new SPLException("getAssociatedInstanceReferences not supported in JAVA-SPL");
}
public List enumerateInstanceNames(String className, String qualifier) throws SPLException {
throw new SPLException("enumerateInstanceNames not supported in JAVA-SPL");
}
public String getReferenceTypeName(String reference) {
String refTypeNm = JavaSPLTypeConstants.getReferenceTypeName(reference);
return refTypeNm;
}
public boolean isInstance(String anchorClassName, Object instance)
throws SPLException
{
boolean isInst = false;
try
{
Class anchorClass = Class.forName(anchorClassName);
isInst = anchorClass.isInstance(instance);
}
catch (ClassNotFoundException e)
{
throw new SPLException(e.getMessage());
}
return isInst;
}
}