/* * DBeaver - Universal Database Manager * Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org) * * Licensed 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. */ package org.jkiss.dbeaver.ext.wmi.model; import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; import org.jkiss.dbeaver.DBException; import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.ext.wmi.Activator; import org.jkiss.dbeaver.model.*; import org.jkiss.dbeaver.model.data.DBDDataFilter; import org.jkiss.dbeaver.model.data.DBDDataReceiver; import org.jkiss.dbeaver.model.exec.DBCException; import org.jkiss.dbeaver.model.exec.DBCExecutionSource; import org.jkiss.dbeaver.model.exec.DBCSession; import org.jkiss.dbeaver.model.exec.DBCStatistics; import org.jkiss.dbeaver.model.meta.Association; import org.jkiss.dbeaver.model.meta.Property; import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor; import org.jkiss.dbeaver.model.struct.*; import org.jkiss.utils.CommonUtils; import org.jkiss.wmi.service.*; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * WMI class */ public class WMIClass extends WMIContainer implements DBSEntity, DBPCloseableObject, DBPQualifiedObject, DBPSystemObject, DBSDataContainer, DBPImageProvider { private static final Log log = Log.getLog(WMIClass.class); static final String ICON_LOCATION_PREFIX = "platform:/plugin/" + Activator.PLUGIN_ID + "/icons/"; private static DBPImage IMG_CLASS; private static DBPImage IMG_CLASS_ABSTRACT; private static DBPImage IMG_CLASS_FINAL; private static DBPImage IMG_CLASS_ABSTRACT_FINAL; private static DBPImage IMG_ASSOCIATION; private static DBPImage IMG_ASSOCIATION_ABSTRACT; private static DBIcon IMG_ABSTRACT_OVR = new DBIcon(ICON_LOCATION_PREFIX + "ovr_abstract.png"); private static DBIcon IMG_FINAL_OVR = new DBIcon(ICON_LOCATION_PREFIX + "ovr_final.png"); static { IMG_CLASS = DBIcon.TREE_CLASS; IMG_CLASS_ABSTRACT = new DBIconComposite(IMG_CLASS, false, null, IMG_ABSTRACT_OVR, null, null); IMG_CLASS_ABSTRACT_FINAL = new DBIconComposite(IMG_CLASS, false, null, IMG_ABSTRACT_OVR, null, IMG_FINAL_OVR); IMG_CLASS_FINAL = new DBIconComposite(IMG_CLASS, false, null, null, null, IMG_FINAL_OVR); IMG_ASSOCIATION = DBIcon.TREE_ASSOCIATION; IMG_ASSOCIATION_ABSTRACT = new DBIconComposite(IMG_ASSOCIATION, false, null, IMG_ABSTRACT_OVR, null, null); } private WMIClass superClass; private WMIObject classObject; private String name; private List<WMIClass> subClasses = null; private List<WMIClassAttribute> attributes = null; private List<WMIClassReference> referenceAttributes = null; private List<WMIClassMethod> methods = null; public WMIClass(WMINamespace parent, WMIClass superClass, WMIObject classObject) { super(parent); this.superClass = superClass; this.classObject = classObject; } public boolean isAbstract() throws DBException { return getFlagQualifier(WMIConstants.Q_Abstract); } public boolean isAssociation() throws DBException { return getFlagQualifier(WMIConstants.Q_Association); } public boolean isAggregation() throws DBException { return getFlagQualifier(WMIConstants.Q_Aggregation); } public boolean isFinal() throws DBException { return getFlagQualifier(WMIConstants.Q_Terminal); } @Property(viewable = true, order = 10) public WMIClass getSuperClass() { return superClass; } public WMINamespace getNamespace() { return parent; } public WMIObject getClassObject() { return classObject; } @Association public List<WMIClass> getSubClasses() { return subClasses; } @Association public Collection<WMIClass> getClasses(DBRProgressMonitor monitor) throws DBException { return subClasses; } void addSubClass(WMIClass wmiClass) { if (subClasses == null) { subClasses = new ArrayList<>(); } subClasses.add(wmiClass); } @NotNull @Override @Property(viewable = true, order = 1) public String getName() { if (name == null && classObject != null) { try { name = CommonUtils.toString( classObject.getValue(WMIConstants.CLASS_PROP_CLASS_NAME)); } catch (WMIException e) { log.error(e); return e.getMessage(); } } if (name == null) { name = "?" + hashCode(); } return name; } @Property(viewable = true, order = 2) public String getPath() { try { return CommonUtils.toString( classObject.getValue(WMIConstants.CLASS_PROP_PATH)); } catch (WMIException e) { log.error(e); return e.getMessage(); } } @NotNull @Override public String getFullyQualifiedName(DBPEvaluationContext context) { //if (classObject == null) { return getName(); //} } @Override public boolean isSystem() { return getName().startsWith("__"); } @NotNull @Override public DBSEntityType getEntityType() { try { if (isAssociation()) { return DBSEntityType.ASSOCIATION; } } catch (DBException e) { log.warn(e); } return DBSEntityType.CLASS; } public Collection<WMIClassReference> getReferenceAttributes(DBRProgressMonitor monitor) throws DBException { if (attributes == null) { readAttributes(monitor); } return referenceAttributes; } @Override public Collection<WMIClassAttribute> getAttributes(@NotNull DBRProgressMonitor monitor) throws DBException { if (attributes == null) { readAttributes(monitor); } return attributes; } @Nullable @Override public Collection<? extends DBSEntityConstraint> getConstraints(@NotNull DBRProgressMonitor monitor) throws DBException { List<WMIClassConstraint> constraints = null; for (WMIClassAttribute attr : getAllAttributes(monitor)) { if (attr.isKey()) { if (constraints == null) { constraints = new ArrayList<>(); } constraints.add(new WMIClassConstraint(this, attr)); } } return constraints; } @Override public WMIClassAttribute getAttribute(@NotNull DBRProgressMonitor monitor, @NotNull String attributeName) throws DBException { return DBUtils.findObject(getAttributes(monitor), attributeName); } @Association public Collection<WMIClassAttribute> getAllAttributes(DBRProgressMonitor monitor) throws DBException { if (superClass == null) { return getAttributes(monitor); } else { List<WMIClassAttribute> allAttrs = new ArrayList<>(); for (WMIClass c = this; c != null; c = c.superClass) { for (WMIClassAttribute attr : c.getAttributes(monitor)) { boolean overridden = false; for (WMIClassAttribute a : allAttrs) { if (attr.getName().equals(a.getName())) { overridden = true; break; } } if (!overridden) { allAttrs.add(attr); } } } return allAttrs; } } private synchronized void readAttributes(DBRProgressMonitor monitor) throws DBException { if (attributes != null) { return; } try { attributes = new ArrayList<>(); for (WMIObjectAttribute prop : classObject.getAttributes(WMIConstants.WBEM_FLAG_CLASS_LOCAL_AND_OVERRIDES)) { if (monitor.isCanceled()) { break; } if (prop.getType() == WMIConstants.CIM_REFERENCE) { Object refClassPath = prop.getQualifier(WMIConstants.Q_CIMTYPE); if (refClassPath == null) { log.warn("No " + WMIConstants.Q_CIMTYPE + " qualifier for reference property"); continue; } String refClassName = refClassPath.toString(); if (!refClassName.startsWith("ref:")) { log.warn("Invalid class reference qualifier: " + refClassName); continue; } refClassName = refClassName.substring(4); WMIClass refClass = getNamespace().getClass(monitor, refClassName); if (refClass == null) { log.warn("Referenced class '" + refClassName + "' not found in '" + getNamespace().getName() + "'"); continue; } if (referenceAttributes == null) { referenceAttributes = new ArrayList<>(); } WMIClassReference reference = new WMIClassReference(this, prop, refClass); referenceAttributes.add(reference); attributes.add(reference); } else if (!prop.isSystem()) { attributes.add(new WMIClassAttribute(this, prop)); } } } catch (WMIException e) { throw new DBException(e, getDataSource()); } } @Association public List<WMIClassMethod> getMethods(DBRProgressMonitor monitor) throws DBException { if (methods == null) { readMethods(monitor); } return methods; } public WMIClassMethod getMethod(DBRProgressMonitor monitor, String methodName) throws DBException { if (methods == null) { readMethods(monitor); } return DBUtils.findObject(methods, methodName); } private synchronized void readMethods(DBRProgressMonitor monitor) throws DBException { if (methods != null) { return; } try { methods = new ArrayList<>(); for (WMIObjectMethod prop : classObject.getMethods(WMIConstants.WBEM_FLAG_LOCAL_ONLY)) { if (monitor.isCanceled()) { break; } methods.add(new WMIClassMethod(this, prop)); } } catch (WMIException e) { throw new DBException(e, getDataSource()); } } @Override public List<? extends DBSEntityAssociation> getAssociations(@NotNull DBRProgressMonitor monitor) throws DBException { // Read attributes and references getAttributes(monitor); if (superClass == null && CommonUtils.isEmpty(referenceAttributes)) { return null; } List<DBSEntityAssociation> associations = new ArrayList<>(); if (superClass != null) { associations.add(new WMIClassInheritance(superClass, this)); } if (referenceAttributes != null) { associations.addAll(referenceAttributes); } return associations; } @Override public List<? extends DBSEntityAssociation> getReferences(@NotNull DBRProgressMonitor monitor) throws DBException { List<DBSEntityAssociation> references = new ArrayList<>(); if (subClasses != null) { for (WMIClass ss : subClasses) { references.add(new WMIClassInheritance(this, ss)); } } if (!this.isAssociation()) { // Try to find references on self in association classes for (WMIClass assoc : getNamespace().getAssociations(monitor)) { Collection<WMIClassReference> refAttrs = assoc.getReferenceAttributes(monitor); if (refAttrs != null) { for (WMIClassReference ref : refAttrs) { if (ref.getAssociatedEntity() == this) { // Add all association ref attributes references.add(ref); break; } } } } } return references; } @Override public void close() { if (classObject != null) { classObject.release(); classObject = null; } } @Override public String toString() { if (classObject == null) { return super.toString(); } return getName(); } /////////////////////////////////////////////////////////////////////// // Data container @Override public int getSupportedFeatures() { return DATA_SELECT; } @NotNull @Override public DBCStatistics readData(@NotNull DBCExecutionSource source, @NotNull DBCSession session, @NotNull DBDDataReceiver dataReceiver, DBDDataFilter dataFilter, long firstRow, long maxRows, long flags) throws DBCException { DBCStatistics statistics = new DBCStatistics(); try { long startTime = System.currentTimeMillis(); WMIObjectCollectorSink sink = new WMIObjectCollectorSink( session.getProgressMonitor(), getNamespace().getService(), firstRow, maxRows); getNamespace().getService().enumInstances( getName(), sink, WMIConstants.WBEM_FLAG_SHALLOW); statistics.setExecuteTime(System.currentTimeMillis() - startTime); startTime = System.currentTimeMillis(); sink.waitForFinish(); WMIResultSet resultSet = new WMIResultSet(session, this, sink.getObjectList()); long resultCount = 0; try { dataReceiver.fetchStart(session, resultSet, firstRow, maxRows); while (resultSet.nextRow()) { resultCount++; dataReceiver.fetchRow(session, resultSet); } } finally { try { dataReceiver.fetchEnd(session, resultSet); } catch (DBCException e) { log.error("Error while finishing result set fetch", e); //$NON-NLS-1$ } resultSet.close(); dataReceiver.close(); } statistics.setFetchTime(System.currentTimeMillis() - startTime); statistics.setRowsFetched(resultCount); return statistics; } catch (WMIException e) { throw new DBCException(e, getDataSource()); } } @Override public long countData(@NotNull DBCExecutionSource source, @NotNull DBCSession session, DBDDataFilter dataFilter) { return -1; } @Nullable @Override public DBPImage getObjectImage() { try { if (isAssociation()) { return isAbstract() ? IMG_ASSOCIATION_ABSTRACT : IMG_ASSOCIATION; } else if (isAbstract()) { return isFinal() ? IMG_CLASS_ABSTRACT_FINAL : IMG_CLASS_ABSTRACT; } else if (isFinal()) { return IMG_CLASS_FINAL; } } catch (DBException e) { log.warn(e); } return IMG_CLASS; } @Override protected WMIQualifiedObject getQualifiedObject() { return classObject; } }