/*
* 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.actions.navigator;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.handlers.HandlerUtil;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.core.DBeaverUI;
import org.jkiss.dbeaver.model.navigator.DBNDatabaseNode;
import org.jkiss.dbeaver.model.navigator.DBNNode;
import org.jkiss.dbeaver.model.navigator.DBNResource;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.DBRRunnableWithProgress;
import org.jkiss.dbeaver.ui.UIUtils;
import org.jkiss.dbeaver.ui.dnd.TreeNodeTransfer;
import org.jkiss.dbeaver.ui.navigator.NavigatorUtils;
import org.jkiss.dbeaver.utils.RuntimeUtils;
import org.jkiss.utils.CommonUtils;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Map;
public class NavigatorHandlerObjectCreateCopy extends NavigatorHandlerObjectCreateBase {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
final ISelection selection = HandlerUtil.getCurrentSelection(event);
DBNNode curNode = NavigatorUtils.getSelectedNode(selection);
if (curNode != null) {
Clipboard clipboard = new Clipboard(Display.getDefault());
try {
@SuppressWarnings("unchecked")
Collection<DBNNode> cbNodes = (Collection<DBNNode>) clipboard.getContents(TreeNodeTransfer.getInstance());
if (cbNodes != null) {
for (DBNNode nodeObject : cbNodes) {
if (nodeObject instanceof DBNDatabaseNode) {
createNewObject(HandlerUtil.getActiveWorkbenchWindow(event), curNode, ((DBNDatabaseNode) nodeObject));
} else if (nodeObject instanceof DBNResource && curNode instanceof DBNResource) {
pasteResource((DBNResource) nodeObject, (DBNResource) curNode);
}
}
} else if (curNode instanceof DBNResource) {
String[] files = (String[]) clipboard.getContents(FileTransfer.getInstance());
if (files != null) {
for (String fileName : files) {
final File file = new File(fileName);
if (file.exists()) {
pasteResource(file, (DBNResource) curNode);
}
}
} else {
UIUtils.showErrorDialog(HandlerUtil.getActiveShell(event), "Paste error", "Unsupported clipboard format. File or folder were expected.");
}
} else {
UIUtils.showErrorDialog(HandlerUtil.getActiveShell(event), "Paste error", "Clipboard contains data in unsupported format");
}
} finally {
clipboard.dispose();
}
}
return null;
}
private void pasteResource(DBNResource resourceNode, DBNResource toFolder) {
final IResource resource = resourceNode.getResource();
final IResource targetResource = toFolder.getResource();
assert resource != null;
assert targetResource != null;
final IContainer targetFolder = targetResource instanceof IContainer ? (IContainer) targetResource : targetResource.getParent();
try {
DBeaverUI.runInProgressService(new DBRRunnableWithProgress() {
@Override
public void run(DBRProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
copyResource(monitor, resource, targetFolder);
} catch (Exception e) {
throw new InvocationTargetException(e);
}
}
});
} catch (InvocationTargetException e) {
UIUtils.showErrorDialog(null, "Copy error", "Error copying resource", e.getTargetException());
} catch (InterruptedException e) {
// ignore
}
}
private void copyResource(@NotNull DBRProgressMonitor monitor, @NotNull IResource resource, @NotNull IContainer targetFolder) throws CoreException, IOException {
final IProgressMonitor nestedMonitor = RuntimeUtils.getNestedMonitor(monitor);
final String extension = resource.getFileExtension();
String targetName = resource.getName();
if (resource.getParent().equals(targetFolder)) {
String plainName = extension != null && !extension.isEmpty() && targetName.endsWith(extension) ?
targetName.substring(0, targetName.length() - extension.length() - 1) : targetName;
for (int i = 1; ; i++) {
String testName = plainName + "-" + i;
if (!CommonUtils.isEmpty(extension)) {
testName += "." + extension;
}
if (targetFolder.findMember(testName) == null) {
targetName = testName;
break;
}
}
} else if (targetFolder.findMember(targetName) != null) {
throw new IOException("Target resource '" + targetName + "' already exists");
}
if (resource instanceof IFile) {
// Copy single file
final IFile targetFile = targetFolder.getFile(new Path(targetName));
if (!targetFile.exists()) {
targetFile.create(new ByteArrayInputStream(new byte[0]), true, nestedMonitor);
}
final Map<QualifiedName, String> props = resource.getPersistentProperties();
if (props != null && !props.isEmpty()) {
for (Map.Entry<QualifiedName, String> prop : props.entrySet()) {
targetFile.setPersistentProperty(prop.getKey(), prop.getValue());
}
}
try (InputStream is = ((IFile) resource).getContents()) {
targetFile.setContents(is, true, true, nestedMonitor);
}
} else if (resource instanceof IFolder) {
// Copy folder with all files and subfolders
}
}
private void pasteResource(final File file, DBNResource toFolder) {
final IResource targetResource = toFolder.getResource();
assert targetResource != null;
final IContainer targetFolder = targetResource instanceof IContainer ? (IContainer) targetResource : targetResource.getParent();
try {
DBeaverUI.runInProgressService(new DBRRunnableWithProgress() {
@Override
public void run(DBRProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
final IFile targetFile = targetFolder.getFile(new Path(file.getName()));
if (targetFile.exists()) {
throw new IOException("Target file '" + targetFile.getFullPath() + "' already exists");
}
try (InputStream is = new FileInputStream(file)) {
targetFile.create(is, true, monitor.getNestedMonitor());
}
} catch (Exception e) {
throw new InvocationTargetException(e);
}
}
});
} catch (InvocationTargetException e) {
UIUtils.showErrorDialog(null, "Copy error", "Error copying resource", e.getTargetException());
} catch (InterruptedException e) {
// ignore
}
}
}