提交 5c9be6aa 编写于 作者: S Serge Rider

#6489 Navigator tree meta reading performance improvements


Former-commit-id: adfe75cc
上级 ba0c5a03
......@@ -95,7 +95,7 @@
</extension>
<extension point="org.eclipse.ui.menus">
<menuContribution allPopups="false" locationURI="popup:org.eclipse.ui.popup.any?after=additions">
<menuContribution allPopups="false" locationURI="popup:org.eclipse.ui.popup.any?after=navigator_additions_end">
<command commandId="org.jkiss.dbeaver.ext.oracle.code.compile">
<visibleWhen checkEnabled="true"/>
</command>
......
......@@ -41,7 +41,6 @@ import org.jkiss.utils.CommonUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.*;
......@@ -480,15 +479,14 @@ public abstract class DBNDatabaseNode extends DBNNode implements DBSWrapper, DBP
if (valueObject == null) {
return false;
}
final String propertyName = meta.getPropertyName();
final PropertyValueReader valueReader = new PropertyValueReader(monitor, propertyName, valueObject);
final PropertyValueReader valueReader = new PropertyValueReader(monitor, meta, valueObject);
DBExecUtils.tryExecuteRecover(monitor, getDataSource(), valueReader);
final Object propertyValue = valueReader.propertyValue;
if (propertyValue == null) {
return false;
}
if (!(propertyValue instanceof Collection<?>)) {
log.warn("Bad property '" + propertyName + "' value: " + propertyValue.getClass().getName()); //$NON-NLS-1$ //$NON-NLS-2$
log.warn("Bad property '" + meta.getPropertyName() + "' value: " + propertyValue.getClass().getName()); //$NON-NLS-1$ //$NON-NLS-2$
return false;
}
......@@ -776,8 +774,7 @@ public abstract class DBNDatabaseNode extends DBNNode implements DBSWrapper, DBP
if (valueObject == null) {
return null;
}
String propertyName = childMeta.getPropertyName();
Method getter = findPropertyReadMethod(valueObject.getClass(), propertyName);
Method getter = childMeta.getPropertyReadMethod(valueObject.getClass());
if (getter == null) {
return null;
}
......@@ -796,14 +793,15 @@ public abstract class DBNDatabaseNode extends DBNNode implements DBSWrapper, DBP
////////////////////////////////////////////////////////////////////////////////////
// Reflection utils
private static Object extractPropertyValue(DBRProgressMonitor monitor, Object object, String propertyName)
private static Object extractPropertyValue(DBRProgressMonitor monitor, Object object, DBXTreeItem meta)
throws DBException {
// Read property using reflection
if (object == null) {
if (object == null || meta == null) {
return null;
}
String propertyName = meta.getPropertyName();
try {
Method getter = findPropertyReadMethod(object.getClass(), propertyName);
Method getter = meta.getPropertyReadMethod(object.getClass());
if (getter == null) {
log.warn("Can't find property '" + propertyName + "' read method in '" + object.getClass().getName() + "'");
return null;
......@@ -830,47 +828,22 @@ public abstract class DBNDatabaseNode extends DBNNode implements DBSWrapper, DBP
}
}
private static Method findPropertyReadMethod(Class<?> clazz, String propertyName) {
String methodName = BeanUtils.propertyNameToMethodName(propertyName);
return findPropertyGetter(clazz, "get" + methodName, "is" + methodName);
}
private static Method findPropertyGetter(Class<?> clazz, String getName, String isName) {
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if ((!Modifier.isPublic(method.getModifiers())) ||
(!Modifier.isPublic(method.getDeclaringClass().getModifiers())) ||
(method.getReturnType().equals(void.class)))
{
// skip
} else if (method.getName().equals(getName) || (method.getName().equals(isName) && method.getReturnType().equals(boolean.class))) {
// If it matches the get name, it's the right method
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 0 || (parameterTypes.length == 1 && parameterTypes[0] == DBRProgressMonitor.class)) {
return method;
}
}
}
return clazz == Object.class ? null : findPropertyGetter(clazz.getSuperclass(), getName, isName);
}
private static class PropertyValueReader implements DBRRunnableParametrized<DBRProgressMonitor> {
private final DBRProgressMonitor monitor;
private final String propertyName;
private final DBXTreeItem meta;
private final Object valueObject;
private Object propertyValue;
PropertyValueReader(DBRProgressMonitor monitor, String propertyName, Object valueObject) {
PropertyValueReader(DBRProgressMonitor monitor, DBXTreeItem meta, Object valueObject) {
this.monitor = monitor;
this.propertyName = propertyName;
this.meta = meta;
this.valueObject = valueObject;
}
@Override
public void run(DBRProgressMonitor param) throws InvocationTargetException, InterruptedException {
try {
propertyValue = extractPropertyValue(monitor, valueObject, propertyName);
propertyValue = extractPropertyValue(monitor, valueObject, meta);
} catch (DBException e) {
throw new InvocationTargetException(e);
}
......
......@@ -17,14 +17,20 @@
package org.jkiss.dbeaver.model.navigator.meta;
import org.eclipse.core.runtime.IConfigurationElement;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.DBPTermProvider;
import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.DBPTermProvider;
import org.jkiss.dbeaver.model.impl.AbstractDescriptor;
import org.jkiss.dbeaver.model.messages.ModelMessages;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.utils.BeanUtils;
import org.jkiss.utils.CommonUtils;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.IdentityHashMap;
import java.util.Map;
/**
* DBXTreeItem
*/
......@@ -36,6 +42,20 @@ public class DBXTreeItem extends DBXTreeNode
private String propertyName;
private boolean optional;
private Map<Class<?>, Method> propertyGettersCache = new IdentityHashMap<>();
private static final Method NULL_GETTER;
static {
Method dummyMethod;
try {
dummyMethod = Object.class.getMethod("hashCode");
} catch (NoSuchMethodException e) {
dummyMethod = null;
}
NULL_GETTER = dummyMethod;
}
public DBXTreeItem(
AbstractDescriptor source,
DBXTreeNode parent,
......@@ -146,4 +166,41 @@ public class DBXTreeItem extends DBXTreeNode
return "Item " + label;
}
public synchronized Method getPropertyReadMethod(Class<?> objectClass) {
Method getter = propertyGettersCache.get(objectClass);
if (getter == null) {
getter = findPropertyReadMethod(objectClass, propertyName);
if (getter == null) {
getter = NULL_GETTER;
}
propertyGettersCache.put(objectClass, getter);
}
return getter == NULL_GETTER ? null : getter;
}
private static Method findPropertyReadMethod(Class<?> clazz, String propertyName) {
String methodName = BeanUtils.propertyNameToMethodName(propertyName);
return findPropertyGetter(clazz, "get" + methodName, "is" + methodName);
}
private static Method findPropertyGetter(Class<?> clazz, String getName, String isName) {
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if ((!Modifier.isPublic(method.getModifiers())) ||
(!Modifier.isPublic(method.getDeclaringClass().getModifiers())) ||
(method.getReturnType().equals(void.class)))
{
// skip
} else if (method.getName().equals(getName) || (method.getName().equals(isName) && method.getReturnType().equals(boolean.class))) {
// If it matches the get name, it's the right method
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length == 0 || (parameterTypes.length == 1 && parameterTypes[0] == DBRProgressMonitor.class)) {
return method;
}
}
}
return clazz == Object.class ? null : findPropertyGetter(clazz.getSuperclass(), getName, isName);
}
}
......@@ -264,10 +264,7 @@ public class ObjectPropertyTester extends PropertyTester
if (objectMaker == null) {
return false;
}
if (!objectMaker.canCreateObject(container.getValueObject())) {
return false;
}
return true;
return objectMaker.canCreateObject(container.getValueObject());
}
if (DBNUtils.isReadOnly(node)) {
return false;
......
......@@ -20,7 +20,6 @@ import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.ISelection;
......@@ -49,7 +48,10 @@ import org.jkiss.dbeaver.model.navigator.meta.DBXTreeItem;
import org.jkiss.dbeaver.model.navigator.meta.DBXTreeNode;
import org.jkiss.dbeaver.model.struct.DBSObject;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.dbeaver.ui.*;
import org.jkiss.dbeaver.ui.ActionUtils;
import org.jkiss.dbeaver.ui.DBeaverIcons;
import org.jkiss.dbeaver.ui.UIIcon;
import org.jkiss.dbeaver.ui.UIUtils;
import org.jkiss.dbeaver.ui.internal.UINavigatorMessages;
import org.jkiss.dbeaver.ui.navigator.NavigatorCommands;
import org.jkiss.dbeaver.ui.navigator.NavigatorUtils;
......@@ -69,6 +71,7 @@ import java.util.Map;
public class NavigatorHandlerObjectCreateNew extends NavigatorHandlerObjectCreateBase implements IElementUpdater {
private static final Log log = Log.getLog(NavigatorHandlerObjectCreateNew.class);
public static final Separator DUMMY_CONTRIBUTION_ITEM = new Separator();
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
......@@ -212,17 +215,20 @@ public class NavigatorHandlerObjectCreateNew extends NavigatorHandlerObjectCreat
}
} else {
Class<?> nodeItemClass = node.getObject().getClass();
DBPImage nodeIcon = node.getNodeIconDefault();
if (node instanceof DBNDataSource) {
nodeIcon = UIIcon.SQL_NEW_CONNECTION;
}
DBNNode parentNode = node.getParentNode();
if (isCreateSupported(
node.getParentNode() instanceof DBNDatabaseNode ? (DBNDatabaseNode) node.getParentNode() : null,
parentNode instanceof DBNDatabaseNode ? (DBNDatabaseNode) parentNode : null,
nodeItemClass))
{
createActions.add(
makeCreateContributionItem(
site, nodeItemClass.getName(), node.getNodeType(), nodeIcon, false));
if (site == null) {
createActions.add(DUMMY_CONTRIBUTION_ITEM);
} else {
DBPImage nodeIcon = node instanceof DBNDataSource ?
UIIcon.SQL_NEW_CONNECTION : node.getNodeIconDefault();
createActions.add(
makeCreateContributionItem(
site, nodeItemClass.getName(), node.getNodeType(), nodeIcon, false));
}
}
if (!node.getDataSourceContainer().hasModifyPermission(DBPDataSourcePermission.PERMISSION_EDIT_METADATA)) {
......@@ -281,7 +287,8 @@ public class NavigatorHandlerObjectCreateNew extends NavigatorHandlerObjectCreat
private static IContributionItem makeCommandContributionItem(@Nullable IWorkbenchPartSite site, String commandId)
{
if (site == null) {
return new ActionContributionItem(new EmptyAction(commandId));
// Dummy item. We need only count
return DUMMY_CONTRIBUTION_ITEM;
} else {
return ActionUtils.makeCommandContribution(site, commandId);
}
......@@ -291,7 +298,7 @@ public class NavigatorHandlerObjectCreateNew extends NavigatorHandlerObjectCreat
@Nullable IWorkbenchPartSite site, String objectType, String objectTypeName, DBPImage objectIcon, boolean isFolder)
{
if (site == null) {
return new ActionContributionItem(new EmptyAction(objectType));
return DUMMY_CONTRIBUTION_ITEM;
}
CommandContributionItemParameter params = new CommandContributionItemParameter(
site,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册