blob: e94e99023b44b1428fc30944305c89491b8ff038 [file] [log] [blame]
/**
* Copyright (c) 2011, 2014 - Lunifera GmbH (Gross Enzersdorf, Austria), Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Florian Pirchner - Initial implementation
*
* Based on Xtext org.eclipse.xtext.common.types.access.reflect.ReflectionTypeProvider
*
*/
package org.eclipse.osbp.dsl.xtext.types.bundles;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.common.types.JvmType;
import org.eclipse.xtext.common.types.access.IMirror;
import org.eclipse.xtext.common.types.access.TypeResource;
import org.eclipse.xtext.common.types.access.impl.AbstractRuntimeJvmTypeProvider;
import org.eclipse.xtext.common.types.access.impl.ClassMirror;
import org.eclipse.xtext.common.types.access.impl.IndexedJvmTypeAccess;
import org.eclipse.xtext.common.types.access.reflect.ReflectURIHelper;
import org.eclipse.xtext.common.types.access.reflect.ReflectionTypeFactory;
import org.eclipse.osbp.runtime.common.types.IBundleSpace;
@SuppressWarnings({ "restriction", "deprecation" })
public class BundleSpaceTypeProvider extends AbstractRuntimeJvmTypeProvider {
private final IBundleSpace classFinder;
private final ReflectionTypeFactory reflectionTypeFactory;
private final ReflectURIHelper uriHelper;
@Deprecated()
public BundleSpaceTypeProvider(BundleSpace classFinder,
ResourceSet resourceSet, IndexedJvmTypeAccess indexedJvmTypeAccess) {
super(resourceSet, indexedJvmTypeAccess);
this.classFinder = classFinder;
uriHelper = new ReflectURIHelper();
reflectionTypeFactory = new ReflectionTypeFactory(uriHelper);
}
public BundleSpaceTypeProvider(IBundleSpace classFinder,
ResourceSet resourceSet, IndexedJvmTypeAccess indexedJvmTypeAccess) {
super(resourceSet, indexedJvmTypeAccess);
this.classFinder = classFinder;
uriHelper = new ReflectURIHelper();
reflectionTypeFactory = new ReflectionTypeFactory(uriHelper);
}
/**
* Returns the type factory used.
*
* @return
*/
public ReflectionTypeFactory getDeclaredTypeFactory() {
return reflectionTypeFactory;
}
/**
* {@inheritDoc}
*/
@Override
public JvmType findTypeByName(String name) {
try {
// seems to be the only reliable way to locate nested types
// since dollar signs are a quite good indicator but not necessarily
// the best
Class<?> clazz = classFinder.forName(name);
return findTypeByClass(clazz);
} catch (ClassNotFoundException e) {
return tryFindTypeInIndex(name, true);
} catch (NoClassDefFoundError e) {
/*
* Error will be thrown if the contents of the binary class file
* does not match the expectation (transitively). See
* java.lang.ClassLoader.defineClass(String, byte[], int, int,
* ProtectionDomain)
*/
return tryFindTypeInIndex(name, true);
}
}
/**
* {@inheritDoc}
*/
@Override
public JvmType findTypeByName(String name, boolean binaryNestedTypeDelimiter) {
if (isBinaryNestedTypeDelimiter(name, binaryNestedTypeDelimiter)) {
return findTypeByName(name);
}
return doFindTypeByName(name);
}
private JvmType doFindTypeByName(String name) {
try {
// seems to be the only reliable way to locate nested types
// since dollar signs are a quite good indicator but not necessarily
// the best
Class<?> clazz = findClassByName(name);
return findTypeByClass(clazz);
} catch (ClassNotFoundException e) {
return tryFindTypeInIndex(name, false);
} catch (NoClassDefFoundError e) {
/*
* Error will be thrown if the contents of the binary class file
* does not match the expectation (transitively). See
* java.lang.ClassLoader.defineClass(String, byte[], int, int,
* ProtectionDomain)
*/
return tryFindTypeInIndex(name, false);
}
}
private JvmType findTypeByClass(Class<?> clazz) {
IndexedJvmTypeAccess indexedJvmTypeAccess = getIndexedJvmTypeAccess();
URI resourceURI = uriHelper.createResourceURI(clazz);
if (indexedJvmTypeAccess != null) {
URI proxyURI = resourceURI.appendFragment(uriHelper
.getFragment(clazz));
EObject candidate = indexedJvmTypeAccess.getIndexedJvmType(
proxyURI, getResourceSet());
if (candidate instanceof JvmType) {
return (JvmType) candidate;
}
}
TypeResource result = (TypeResource) getResourceSet().getResource(
resourceURI, true);
return findTypeByClass(clazz, result);
}
private Class<?> findClassByName(String name) throws ClassNotFoundException {
try {
Class<?> clazz = classFinder.forName(name);
return clazz;
} catch (ClassNotFoundException exception) {
int index = name.lastIndexOf('.');
if (index <= 0) {
throw exception;
}
String baseName = name.substring(0, index);
try {
Class<?> resolvedOuterClass = findClassByName(baseName);
baseName = resolvedOuterClass.getName();
} catch (ClassNotFoundException baseNameException) {
throw exception;
}
Class<?> clazz = classFinder.forName(baseName + '$'
+ name.substring(index + 1));
return clazz;
}
}
/**
* Uses the index to find the type by its name.
*
* @param name
* @param binaryNestedTypeDelimiter
* @return
*/
protected JvmType tryFindTypeInIndex(String name,
boolean binaryNestedTypeDelimiter) {
TypeInResourceSetAdapter adapter = (TypeInResourceSetAdapter) EcoreUtil
.getAdapter(getResourceSet().eAdapters(),
TypeInResourceSetAdapter.class);
if (adapter != null) {
return adapter.tryFindTypeInIndex(name, this,
binaryNestedTypeDelimiter);
} else {
return doTryFindInIndex(name, binaryNestedTypeDelimiter);
}
}
/**
* {@inheritDoc}
*/
@Override
protected IMirror createMirrorForFQN(String name) {
try {
Class<?> clazz = classFinder.forName(name);
return createMirror(clazz);
} catch (ClassNotFoundException e) {
return null;
}
}
/**
* Creates a mirror for the given class.
*
* @param clazz
* @return
*/
public ClassMirror createMirror(Class<?> clazz) {
return ClassMirror.createClassMirror(clazz, reflectionTypeFactory);
}
/**
* Tries to find the type for the given class and resource.
*
* @param clazz
* @param resource
* @return
*/
public JvmType findTypeByClass(Class<?> clazz, Resource resource) {
String fragment = uriHelper.getFragment(clazz);
JvmType result = (JvmType) resource.getEObject(fragment);
if (result == null) {
throw new IllegalStateException("Resource has not been loaded");
}
return result;
}
}