/* * 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.dbeaver.DBException; import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.model.DBPCloseableObject; import org.jkiss.dbeaver.model.DBUtils; 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.DBSObject; import org.jkiss.dbeaver.model.struct.DBSObjectContainer; import org.jkiss.utils.CommonUtils; import org.jkiss.wmi.service.*; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * WMI Namespace */ public class WMINamespace extends WMIContainer implements DBSObjectContainer, DBPCloseableObject { private static final Log log = Log.getLog(WMINamespace.class); protected WMIDataSource dataSource; private String name; protected WMIService service; private volatile List<WMINamespace> namespaces; private volatile List<WMIClass> rooClasses; private volatile List<WMIClass> associations; private volatile List<WMIClass> allClasses; public WMINamespace(WMINamespace parent, WMIDataSource dataSource, String name, WMIService service) { super(parent); this.dataSource = dataSource; this.name = name; this.service = service; } @Override public DBSObject getParentObject() { return parent != null ? parent : dataSource.getContainer(); } @NotNull @Override public WMIDataSource getDataSource() { return dataSource; } public WMIService getService() throws WMIException { if (service == null) { this.service = parent.getService().openNamespace(this.name); } return service; } @NotNull @Override @Property(viewable = true, order = 1) public String getName() { return name; } public Collection<WMINamespace> getNamespaces(DBRProgressMonitor monitor) throws DBException { if (namespaces == null) { synchronized (this) { if (namespaces == null) { // Namespaces are not yet loaded - it means we are in datasource object namespaces = loadNamespaces(monitor); } } } return namespaces; } List<WMINamespace> loadNamespaces(DBRProgressMonitor monitor) throws DBException { try { WMIObjectCollectorSink sink = new WMIObjectCollectorSink(monitor, getService()); getService().enumInstances("__NAMESPACE", sink, WMIConstants.WBEM_FLAG_SHALLOW); sink.waitForFinish(); List<WMINamespace> children = new ArrayList<>(); for (WMIObject object : sink.getObjectList()) { String nsName = CommonUtils.toString(object.getValue("Name")); children.add(new WMINamespace(this, dataSource, nsName, null)); object.release(); } DBUtils.orderObjects(children); return children; } catch (WMIException e) { throw new DBException(e, getDataSource()); } } @Association public Collection<WMIClass> getRootClasses(DBRProgressMonitor monitor) throws DBException { if (rooClasses == null) { synchronized (this) { if (rooClasses == null) { // Class are not yet loaded - it means we are in datasource object loadClasses(monitor); } } } return rooClasses; } @Association public Collection<WMIClass> getClasses(DBRProgressMonitor monitor) throws DBException { getRootClasses(monitor); return allClasses; } public WMIClass getClass(DBRProgressMonitor monitor, String name) throws DBException { return DBUtils.findObject(getClasses(monitor), name); } @Association public Collection<WMIClass> getAssociations(DBRProgressMonitor monitor) throws DBException { getRootClasses(monitor); return associations; } void loadClasses(DBRProgressMonitor monitor) throws DBException { boolean showSystemObjects = getDataSource().getContainer().isShowSystemObjects(); try { WMIObjectCollectorSink sink = new WMIObjectCollectorSink(monitor, getService()); getService().enumClasses(null, sink, WMIConstants.WBEM_FLAG_DEEP); sink.waitForFinish(); List<WMIClass> allClasses = new ArrayList<>(); List<WMIClass> allAssociations = new ArrayList<>(); List<WMIClass> rootClasses = new ArrayList<>(); for (WMIObject object : sink.getObjectList()) { WMIClass superClass = null; String superClassName = (String)object.getValue(WMIConstants.CLASS_PROP_SUPER_CLASS); if (superClassName != null) { for (WMIClass c : allClasses) { if (c.getName().equals(superClassName)) { superClass = c; break; } } if (superClass == null) { for (WMIClass c : allAssociations) { if (c.getName().equals(superClassName)) { superClass = c; break; } } if (superClass == null) { log.warn("Super class '" + superClassName + "' not found"); } } } WMIClass wmiClass = new WMIClass(this, superClass, object); if (wmiClass.isAssociation()) { allAssociations.add(wmiClass); } else { allClasses.add(wmiClass); if (superClass == null) { rootClasses.add(wmiClass); } } if (superClass != null) { superClass.addSubClass(wmiClass); } } // filter out system classes if (!showSystemObjects) { for (Iterator<WMIClass> iter = allClasses.iterator(); iter.hasNext(); ) { WMIClass wmiClass = iter.next(); if (wmiClass.isSystem()) { iter.remove(); } } } DBUtils.orderObjects(rootClasses); DBUtils.orderObjects(allClasses); DBUtils.orderObjects(allAssociations); this.rooClasses = rootClasses; this.allClasses = allClasses; this.associations = allAssociations; } catch (WMIException e) { throw new DBException(e, getDataSource()); } } @Override public Collection<? extends WMIContainer> getChildren(@NotNull DBRProgressMonitor monitor) throws DBException { List<WMIContainer> children = new ArrayList<>(); children.addAll(getNamespaces(monitor)); children.addAll(getClasses(monitor)); children.addAll(getAssociations(monitor)); return children; } @Override public WMIContainer getChild(@NotNull DBRProgressMonitor monitor, @NotNull String childName) throws DBException { return DBUtils.findObject(getChildren(monitor), childName); } @Override public Class<? extends WMIContainer> getChildType(@NotNull DBRProgressMonitor monitor) throws DBException { return WMIContainer.class; } @Override public void cacheStructure(@NotNull DBRProgressMonitor monitor, int scope) throws DBException { getNamespaces(monitor); getClasses(monitor); } @Override public void close() { if (!CommonUtils.isEmpty(namespaces)) { for (WMINamespace namespace : namespaces) { namespace.close(); } namespaces.clear(); } if (!CommonUtils.isEmpty(allClasses)) { for (WMIClass wmiClass : allClasses) { wmiClass.close(); } allClasses.clear(); rooClasses.clear(); } if (parent != null && service != null) { service.close(); service = null; } } @Override protected WMIQualifiedObject getQualifiedObject() { return null; } }