blob: 000695019e6b10ff23ac1f73adf4243137861493 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2021 Borland Software Corporation and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Borland Software Corporation - initial API and implementation
* Christopher Gerking - bugs 289982, 326871, 472482
*******************************************************************************/
package org.eclipse.m2m.internal.qvt.oml.blackbox.java;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.m2m.internal.qvt.oml.NLS;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEnvFactory;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalModuleEnv;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalStdLibrary;
import org.eclipse.m2m.internal.qvt.oml.blackbox.LoadContext;
import org.eclipse.m2m.internal.qvt.oml.emf.util.EmfUtilPlugin;
import org.eclipse.m2m.internal.qvt.oml.expressions.Library;
abstract class JavaModuleLoader {
private BasicDiagnostic fDiagnostics;
private QvtOperationalModuleEnv fEnv;
private OperationBuilder fOperBuilder;
JavaModuleLoader() {
fDiagnostics = null;
}
public QvtOperationalModuleEnv getLoadedModule() {
return fEnv;
}
public Diagnostic getDiagnostics() {
return (fDiagnostics != null) ? fDiagnostics : Diagnostic.OK_INSTANCE;
}
public Diagnostic loadModule(ModuleHandle moduleHandle, Map<String, List<EOperation>> definedOperations, LoadContext loadContext) {
fDiagnostics = DiagnosticUtil.createRootDiagnostic(NLS.bind(JavaBlackboxMessages.LoadModuleDiagnostics, moduleHandle));
Class<?> javaClass;
try {
javaClass = moduleHandle.getModuleJavaClass();
if(!isModuleClassValid(javaClass)) {
fDiagnostics.add(DiagnosticUtil.createErrorDiagnostic(NLS.bind(
JavaBlackboxMessages.InvalidJavaClassForModule,
javaClass, moduleHandle)));
// no sense to continue
return fDiagnostics;
}
} catch (ClassNotFoundException e) {
fDiagnostics.add(DiagnosticUtil.createErrorDiagnostic(NLS.bind(
JavaBlackboxMessages.ModuleJavaClassNotFound, moduleHandle.getModuleName()), e));
// no sense to continue
return fDiagnostics;
}
Library module = QvtOperationalStdLibrary.createLibrary(moduleHandle.getModuleName());
fEnv = new QvtOperationalEnvFactory(loadContext.getMetamodelRegistry()).createModuleEnvironment(module);
loadModule(fEnv, javaClass);
Collection<String> usedPackages = new LinkedHashSet<String>(moduleHandle.getUsedPackages());
Java2QVTTypeResolver typeResolver = new Java2QVTTypeResolver(fEnv, usedPackages, fDiagnostics);
fOperBuilder = new OperationBuilder(typeResolver);
try {
Method[] methods = javaClass.getDeclaredMethods();
for (Method method : methods) {
if(!isLibraryOperation(method)) {
continue;
}
EOperation operation = fOperBuilder.buildOperation(method);
Diagnostic operationStatus = fOperBuilder.getDiagnostics();
if(EmfUtilPlugin.isSuccess(operationStatus)) {
loadOperation(operation, method);
List<EOperation> listOp = definedOperations.get(operation.getName());
if (listOp == null) {
listOp = new LinkedList<EOperation>();
definedOperations.put(operation.getName(), listOp);
}
listOp.add(operation);
}
if(operationStatus.getSeverity() != Diagnostic.OK) {
fDiagnostics.add(operationStatus);
}
}
} catch (NoClassDefFoundError e) {
fDiagnostics.add(DiagnosticUtil.createErrorDiagnostic(NLS.bind(
JavaBlackboxMessages.ModuleJavaClassNotLoadable, moduleHandle.getModuleName()), new Exception(e)));
// no sense to continue
return fDiagnostics;
}
return fDiagnostics;
}
protected abstract void loadModule(QvtOperationalModuleEnv moduleEnv, Class<?> javaModule);
protected abstract void loadOperation(EOperation eOperation, Method javaOperation);
private static boolean isLibraryOperation(Method method) {
return Modifier.isPublic(method.getModifiers());
}
private static boolean isModuleClassValid(Class<?> javaClass) {
Class<?>[] noParams = new Class<?>[0];
try {
Constructor<?> constructor = javaClass.getDeclaredConstructor(noParams);
if(!Modifier.isPublic(constructor.getModifiers())) {
return false;
}
} catch (SecurityException e) {
return false;
} catch (NoSuchMethodException e) {
return false;
} catch (NoClassDefFoundError e) {
return false;
} catch(LinkageError e) {
return false;
}
return Modifier.isPublic(javaClass.getModifiers());
}
}