/* * 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.ui.resources; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.*; import org.jkiss.code.Nullable; import org.jkiss.dbeaver.DBeaverPreferences; import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.core.DBeaverCore; import org.jkiss.dbeaver.model.DBPDataSourceContainer; import org.jkiss.dbeaver.model.DBPDataSourceFolder; import org.jkiss.dbeaver.model.sql.SQLUtils; import org.jkiss.dbeaver.ui.editors.EditorUtils; import org.jkiss.dbeaver.utils.ContentUtils; import org.jkiss.dbeaver.utils.GeneralUtils; import org.jkiss.utils.ArrayUtils; import org.jkiss.utils.CommonUtils; import java.io.ByteArrayInputStream; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * ResourceUtils */ public class ResourceUtils { private static final Log log = Log.getLog(ResourceUtils.class); public static final String SCRIPT_FILE_EXTENSION = "sql"; //$NON-NLS-1$ public static class ResourceInfo { private final IResource resource; private final File localFile; private final DBPDataSourceContainer dataSource; private final List<ResourceInfo> children; private String description; public ResourceInfo(IFile file, DBPDataSourceContainer dataSource) { this.resource = file; this.localFile = file.getLocation().toFile(); this.dataSource = dataSource; this.children = null; } public ResourceInfo(IFolder folder) { this.resource = folder; this.localFile = folder.getLocation().toFile(); this.dataSource = null; this.children = new ArrayList<>(); } public ResourceInfo(File localFile, DBPDataSourceContainer dataSource) { this.resource = null; this.localFile = localFile; this.dataSource = dataSource; this.children = null; } public IResource getResource() { return resource; } public File getLocalFile() { return localFile; } public String getName() { return resource != null ? resource.getName() : localFile.getName(); } public DBPDataSourceContainer getDataSource() { return dataSource; } public boolean isDirectory() { return resource instanceof IFolder; } public List<ResourceInfo> getChildren() { return children; } public String getDescription() { if (description == null) { description = getResourceDescription(resource); } return description; } @Override public String toString() { return getName(); } } public static String getResourceDescription(IResource resource) { if (resource instanceof IFolder) { return ""; } else if (resource instanceof IFile && SCRIPT_FILE_EXTENSION.equals(resource.getFileExtension())) { String description = SQLUtils.getScriptDescription((IFile) resource); if (CommonUtils.isEmptyTrimmed(description)) { description = "<empty>"; } return description; } else { return ""; } } public static IFolder getScriptsFolder(IProject project, boolean forceCreate) throws CoreException { if (project == null) { IStatus status = new Status(IStatus.ERROR, DBeaverCore.getCorePluginID(), "No active project to locate Script Folder"); throw new CoreException(status); } return DBeaverCore.getInstance().getProjectRegistry().getResourceDefaultRoot(project, ScriptsHandlerImpl.class, forceCreate); } @Nullable public static ResourceInfo findRecentScript(IProject project, @Nullable DBPDataSourceContainer container) throws CoreException { List<ResourceInfo> scripts = new ArrayList<>(); findScriptList(getScriptsFolder(project, false), container, scripts); long recentTimestamp = 0l; ResourceInfo recentFile = null; for (ResourceInfo file : scripts) { if (file.localFile.lastModified() > recentTimestamp) { recentTimestamp = file.localFile.lastModified(); recentFile = file; } } return recentFile; } private static void findScriptList(IFolder folder, @Nullable DBPDataSourceContainer container, List<ResourceInfo> result) { try { // Search in project scripts for (IResource resource : folder.members()) { if (resource instanceof IFile && SCRIPT_FILE_EXTENSION.equals(resource.getFileExtension())) { final DBPDataSourceContainer scriptDataSource = EditorUtils.getFileDataSource((IFile) resource); if (container == null || scriptDataSource == container) { result.add(new ResourceInfo((IFile) resource, scriptDataSource)); } } else if (resource instanceof IFolder) { findScriptList((IFolder) resource, container, result); } } if (container != null) { // Search in external files for (Map.Entry<String, Map<String, Object>> fileEntry : DBeaverCore.getInstance().getExternalFileManager().getAllFiles().entrySet()) { if (container.getId().equals(fileEntry.getValue().get(EditorUtils.PROP_SQL_DATA_SOURCE))) { File extFile = new File(fileEntry.getKey()); if (extFile.exists()) { result.add(new ResourceInfo(extFile, container)); } } } } } catch (CoreException e) { log.debug(e.getMessage()); } } public static List<ResourceInfo> findScriptTree(IFolder folder, @Nullable DBPDataSourceContainer[] containers) { List<ResourceInfo> result = new ArrayList<>(); try { for (IResource resource : folder.members()) { if (resource instanceof IFile && SCRIPT_FILE_EXTENSION.equals(resource.getFileExtension())) { final DBPDataSourceContainer scriptDataSource = EditorUtils.getFileDataSource((IFile) resource); if (containers == null || ArrayUtils.containsRef(containers, scriptDataSource)) { result.add(new ResourceInfo((IFile) resource, scriptDataSource)); } } else if (resource instanceof IFolder) { final ResourceInfo folderInfo = new ResourceInfo((IFolder) resource); if (findChildScripts(folderInfo, containers)) { result.add(folderInfo); } } } if (!ArrayUtils.isEmpty(containers)) { // Search in external files for (Map.Entry<String, Map<String, Object>> fileEntry : DBeaverCore.getInstance().getExternalFileManager().getAllFiles().entrySet()) { final Object fileContainerId = fileEntry.getValue().get(EditorUtils.PROP_SQL_DATA_SOURCE); if (fileContainerId != null) { File extFile = new File(fileEntry.getKey()); if (extFile.exists()) { for (DBPDataSourceContainer container : containers) { if (container.getId().equals(fileContainerId)) { result.add(new ResourceInfo(extFile, container)); break; } } } } } } } catch (CoreException e) { log.debug(e); } return result; } private static boolean findChildScripts(ResourceInfo folder, @Nullable DBPDataSourceContainer[] containers) throws CoreException { boolean hasScripts = false; for (IResource resource : ((IFolder)folder.resource).members()) { if (resource instanceof IFile && SCRIPT_FILE_EXTENSION.equals(resource.getFileExtension())) { final DBPDataSourceContainer scriptDataSource = EditorUtils.getFileDataSource((IFile) resource); if (containers == null || ArrayUtils.containsRef(containers, scriptDataSource)) { folder.children.add(new ResourceInfo((IFile) resource, scriptDataSource)); hasScripts = true; } } else if (resource instanceof IFolder) { final ResourceInfo folderInfo = new ResourceInfo((IFolder) resource); if (findChildScripts(folderInfo, containers)) { folder.children.add(folderInfo); hasScripts = true; } } } return hasScripts; } public static IFile createNewScript(IProject project, @Nullable IFolder folder, @Nullable DBPDataSourceContainer dataSourceContainer) throws CoreException { final IProgressMonitor progressMonitor = new NullProgressMonitor(); // Get folder final IFolder scriptsRootFolder = ResourceUtils.getScriptsFolder(project, true); IFolder scriptsFolder = folder; if (scriptsFolder == null) { scriptsFolder = scriptsRootFolder; } if (CommonUtils.equalObjects(scriptsRootFolder, scriptsFolder)) { // We are in the root folder if (dataSourceContainer != null) { if (dataSourceContainer.getPreferenceStore().getBoolean(DBeaverPreferences.SCRIPT_CREATE_CONNECTION_FOLDERS)) { // Create script folders according to connection folders DBPDataSourceFolder conFolder = dataSourceContainer.getFolder(); if (conFolder != null) { List<DBPDataSourceFolder> conFolders = new ArrayList<>(); for (DBPDataSourceFolder f = conFolder; f != null; f = f.getParent()) { conFolders.add(0, f); } for (DBPDataSourceFolder f : conFolders) { IFolder dbFolder = scriptsFolder.getFolder(CommonUtils.escapeFileName(f.getName())); if (dbFolder != null) { if (!dbFolder.exists()) { dbFolder.create(true, true, progressMonitor); } scriptsFolder = dbFolder; } } } } if (dataSourceContainer.getPreferenceStore().getBoolean(DBeaverPreferences.SCRIPT_AUTO_FOLDERS)) { // Create special folder for connection IFolder dbFolder = scriptsFolder.getFolder(CommonUtils.escapeFileName(dataSourceContainer.getName())); if (dbFolder != null) { if (!dbFolder.exists()) { dbFolder.create(true, true, progressMonitor); } scriptsFolder = dbFolder; } } } } // Make new script file IFile tempFile = ContentUtils.getUniqueFile(scriptsFolder, "Script", SCRIPT_FILE_EXTENSION); tempFile.create(new ByteArrayInputStream(new byte[]{}), true, progressMonitor); //tempFile.setCharset(GeneralUtils.getDefaultFileEncoding(), progressMonitor); // Save ds container reference if (dataSourceContainer != null) { EditorUtils.setFileDataSource(tempFile, dataSourceContainer); } return tempFile; } }