Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2020-12-09 07:38:38 +0000
committerEike Stepper2020-12-09 07:38:38 +0000
commit7968f34ab4457e97fb5b38f6f0f02d44f7542645 (patch)
treea603c3fe83c4a695c2445e08ccb5cf3f14b9d6cd
parentd2ca99148ea11b360d2dbef78a6173373484dcc8 (diff)
downloadcdo-7968f34ab4457e97fb5b38f6f0f02d44f7542645.tar.gz
cdo-7968f34ab4457e97fb5b38f6f0f02d44f7542645.tar.xz
cdo-7968f34ab4457e97fb5b38f6f0f02d44f7542645.zip
[569572] [UI] Allows to open a model editor on a CDOFileResource in a CDOCheckout
https://bugs.eclipse.org/bugs/show_bug.cgi?id=569572
-rw-r--r--plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/actions/OpenWithActionProvider.java103
-rw-r--r--plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/explorer/CDOExplorerUtil.java5
-rw-r--r--plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/CDOExplorerURIHandler.java325
-rw-r--r--plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/bundle/OM.java67
-rw-r--r--plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/checkouts/CDOCheckoutViewProvider.java2
-rw-r--r--plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOLobEditorInput.java28
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOURIHandler.java131
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IORunnable.java1
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IOUtil.java15
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/ReaderInputStream.java155
10 files changed, 693 insertions, 139 deletions
diff --git a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/actions/OpenWithActionProvider.java b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/actions/OpenWithActionProvider.java
index e65fad2812..0b81a63a53 100644
--- a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/actions/OpenWithActionProvider.java
+++ b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/actions/OpenWithActionProvider.java
@@ -13,15 +13,17 @@ package org.eclipse.emf.cdo.explorer.ui.checkouts.actions;
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.eresource.CDOFileResource;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.eresource.CDOResourceFolder;
import org.eclipse.emf.cdo.eresource.CDOResourceLeaf;
import org.eclipse.emf.cdo.eresource.CDOResourceNode;
-import org.eclipse.emf.cdo.eresource.CDOTextResource;
import org.eclipse.emf.cdo.explorer.CDOExplorerUtil;
import org.eclipse.emf.cdo.explorer.checkouts.CDOCheckout;
import org.eclipse.emf.cdo.explorer.ui.bundle.OM;
+import org.eclipse.emf.cdo.internal.explorer.CDOExplorerURIHandler;
import org.eclipse.emf.cdo.internal.ui.dialogs.EditObjectDialog;
+import org.eclipse.emf.cdo.internal.ui.editor.CDOLobEditorInput;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.ui.CDOEditorOpener;
import org.eclipse.emf.cdo.ui.CDOEditorUtil;
@@ -29,6 +31,7 @@ import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.net4j.util.ObjectUtil;
+import org.eclipse.net4j.util.om.OMPlatform;
import org.eclipse.net4j.util.ui.UIUtil;
import org.eclipse.emf.common.command.BasicCommandStack;
@@ -46,7 +49,6 @@ import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IActionBars;
-import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWorkbenchPage;
@@ -63,37 +65,7 @@ import org.eclipse.ui.navigator.ICommonViewerWorkbenchSite;
*/
public class OpenWithActionProvider extends CommonActionProvider
{
- // private static final String WORKBENCH_PART_KEY = IWorkbenchPart.class.getName();
- //
- // private static final Map<IEditorPart, Pair<CDOView, Pair<CDOResourceLeaf, String>>> VIEWS = new
- // HashMap<IEditorPart, Pair<CDOView, Pair<CDOResourceLeaf, String>>>();
- //
- // private static final Map<Pair<CDOResourceLeaf, String>, Object> EDITORS = new HashMap<Pair<CDOResourceLeaf,
- // String>, Object>();
- //
- // private static final Object EDITOR_OPENING = new Object();
- //
- // private static final IPartListener2 PART_LISTENER = new PartListener();
- //
- // private static final IPageListener PAGE_LISTENER = new PageListener();
- //
- // private static final IWindowListener WINDOW_LISTENER = new WindowListener();
- //
- // static
- // {
- // IWorkbench workbench = UIUtil.getWorkbench();
- // for (IWorkbenchWindow window : workbench.getWorkbenchWindows())
- // {
- // window.addPageListener(PAGE_LISTENER);
- //
- // for (IWorkbenchPage page : window.getPages())
- // {
- // page.addPartListener(PART_LISTENER);
- // }
- // }
- //
- // workbench.addWindowListener(WINDOW_LISTENER);
- // }
+ private static final boolean OMIT_LOB_HANDLER_URI = OMPlatform.INSTANCE.isProperty("org.eclipse.emf.cdo.explorer.ui.omitLobHandlerURI");
private ICommonViewerWorkbenchSite viewSite;
@@ -224,61 +196,6 @@ public class OpenWithActionProvider extends CommonActionProvider
return cdoObject.cdoResource();
}
- // private static IEditorInput createEditorInput(String editorID, CDOCheckout checkout, CDOResourceLeaf resourceLeaf)
- // {
- // if (CDOEditorUtil.EDITOR_ID.equals(editorID))
- // {
- // return CDOEditorUtil.createEditorInput(editorID, resourceLeaf, false, true);
- // }
- //
- // String path = resourceLeaf.getPath();
- // URI uri = checkout.createResourceURI(path);
- // return new URIEditorInput(uri);
- // }
- //
- // private static void openEditor(final IWorkbenchPage page, final CDOObject object, final CDOResourceLeaf
- // resourceLeaf,
- // final String editorID, final Pair<CDOResourceLeaf, String> key)
- // {
- // new Job("Open")
- // {
- // @Override
- // protected IStatus run(IProgressMonitor monitor)
- // {
- // final CDOCheckout checkout = CDOExplorerUtil.getCheckout(object);
- // final CDOView view = checkout.openView();
- //
- // final CDOResourceLeaf contextualLeaf = view.getObject(resourceLeaf);
- // final IEditorInput editorInput = createEditorInput(editorID, checkout, contextualLeaf);
- //
- // Shell shell = page.getWorkbenchWindow().getShell();
- // if (!shell.isDisposed())
- // {
- // shell.getDisplay().asyncExec(new Runnable()
- // {
- // public void run()
- // {
- // try
- // {
- // IEditorPart editor = page.openEditor(editorInput, editorID);
- // if (editor != null)
- // {
- // registerEditor(editor, view, key);
- // }
- // }
- // catch (Exception ex)
- // {
- // OM.LOG.error(ex);
- // }
- // }
- // });
- // }
- //
- // return Status.OK_STATUS;
- // }
- // }.schedule();
- // }
-
public static void openEditor(IWorkbenchPage page, ComposedAdapterFactory adapterFactory, EObject object, String editorOpenerID)
{
if (page == null)
@@ -383,7 +300,7 @@ public class OpenWithActionProvider extends CommonActionProvider
}
}
}
- else if (resourceLeaf instanceof CDOTextResource)
+ else if (resourceLeaf instanceof CDOFileResource)
{
String editorID = CDOEditorUtil.getEffectiveEditorID(resourceLeaf);
if (editorID != null)
@@ -395,7 +312,13 @@ public class OpenWithActionProvider extends CommonActionProvider
try
{
- IEditorInput editorInput = CDOEditorUtil.createLobEditorInput(txLeaf, true);
+ CDOLobEditorInput editorInput = (CDOLobEditorInput)CDOEditorUtil.createLobEditorInput(txLeaf, true);
+
+ if (!OMIT_LOB_HANDLER_URI)
+ {
+ editorInput.setURI(CDOExplorerURIHandler.createURI(checkout, txLeaf));
+ }
+
IEditorPart editor = page.openEditor(editorInput, editorID);
page.addPartListener(new IPartListener()
diff --git a/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/explorer/CDOExplorerUtil.java b/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/explorer/CDOExplorerUtil.java
index a0385b54d0..1255253850 100644
--- a/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/explorer/CDOExplorerUtil.java
+++ b/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/explorer/CDOExplorerUtil.java
@@ -39,6 +39,11 @@ import java.util.LinkedList;
*/
public final class CDOExplorerUtil
{
+ /**
+ * @since 4.8
+ */
+ public static final String URI_SCHEME = "cdo.checkout";
+
public static CDORepositoryManager getRepositoryManager()
{
return OM.getRepositoryManager();
diff --git a/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/CDOExplorerURIHandler.java b/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/CDOExplorerURIHandler.java
new file mode 100644
index 0000000000..21da85f350
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/CDOExplorerURIHandler.java
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2020 Eike Stepper (Loehne, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.internal.explorer;
+
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
+import org.eclipse.emf.cdo.common.lob.CDOBlob;
+import org.eclipse.emf.cdo.common.lob.CDOClob;
+import org.eclipse.emf.cdo.common.lob.CDOLobStore;
+import org.eclipse.emf.cdo.common.util.CDOException;
+import org.eclipse.emf.cdo.common.util.CDOResourceNodeNotFoundException;
+import org.eclipse.emf.cdo.eresource.CDOBinaryResource;
+import org.eclipse.emf.cdo.eresource.CDOResourceNode;
+import org.eclipse.emf.cdo.eresource.CDOTextResource;
+import org.eclipse.emf.cdo.explorer.CDOExplorerUtil;
+import org.eclipse.emf.cdo.explorer.checkouts.CDOCheckout;
+import org.eclipse.emf.cdo.transaction.CDOTransaction;
+import org.eclipse.emf.cdo.view.CDOView;
+
+import org.eclipse.emf.internal.cdo.view.CDOURIHandler;
+
+import org.eclipse.net4j.util.io.IOUtil;
+import org.eclipse.net4j.util.io.ReaderInputStream;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.URIConverter;
+import org.eclipse.emf.ecore.resource.impl.URIHandlerImpl;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.StringReader;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class CDOExplorerURIHandler<NODE extends CDOResourceNode> extends URIHandlerImpl
+{
+ public static final CDOExplorerURIHandler<CDOTextResource> TEXT = new TextURIHandler();
+
+ public static final CDOExplorerURIHandler<CDOBinaryResource> BINARY = new BinaryURIRHandler();
+
+ private final String scheme;
+
+ protected CDOExplorerURIHandler(String schemeType)
+ {
+ this.scheme = CDOExplorerUtil.URI_SCHEME + "." + schemeType;
+ }
+
+ public final String getScheme()
+ {
+ return scheme;
+ }
+
+ @Override
+ public boolean canHandle(URI uri)
+ {
+ return scheme.equals(uri.scheme());
+ }
+
+ @Override
+ public boolean exists(URI uri, Map<?, ?> options)
+ {
+ CDOView view = getView(uri);
+ NODE node = null;
+
+ try
+ {
+ node = getNode(view, uri.path());
+ }
+ catch (CDOResourceNodeNotFoundException ex)
+ {
+ //$FALL-THROUGH$
+ }
+
+ return node != null;
+ }
+
+ @Override
+ public Map<String, ?> getAttributes(URI uri, Map<?, ?> options)
+ {
+ CDOView view = getView(uri);
+ Map<String, ?> attributes = CDOURIHandler.getAttributes(view, uri.path(), options);
+
+ // The view of a checkout is always read-only, so remove this attribute.
+ attributes.remove(URIConverter.ATTRIBUTE_READ_ONLY);
+
+ return attributes;
+ }
+
+ @Override
+ public InputStream createInputStream(URI uri, Map<?, ?> options) throws IOException
+ {
+ CDOView view = getView(uri);
+ NODE node = getNode(view, uri.path());
+ return createInputStream(node);
+ }
+
+ @Override
+ public OutputStream createOutputStream(URI uri, Map<?, ?> options) throws IOException
+ {
+ return new ByteArrayOutputStream()
+ {
+ @Override
+ public void close() throws IOException
+ {
+ super.close();
+ byte[] bytes = toByteArray();
+
+ CDOCheckout checkout = getCheckout(uri);
+ CDOLobStore lobStore = checkout.getView().getSession().options().getLobCache();
+
+ modify(checkout, uri.path(), true, node -> setContents(node, bytes, lobStore));
+ }
+ };
+ }
+
+ @Override
+ public void delete(URI uri, Map<?, ?> options) throws IOException
+ {
+ CDOCheckout checkout = getCheckout(uri);
+ modify(checkout, uri.path(), false, node -> node.delete(options));
+ }
+
+ protected abstract NODE getNode(CDOView view, String path) throws CDOResourceNodeNotFoundException;
+
+ protected abstract NODE getOrCreateNode(CDOTransaction transaction, String path);
+
+ protected abstract InputStream createInputStream(NODE node) throws IOException;
+
+ protected abstract void setContents(NODE node, byte[] bytes, CDOLobStore lobStore) throws IOException;
+
+ private CDOCheckout getCheckout(URI uri)
+ {
+ String id = uri.authority();
+
+ CDOCheckout checkout = CDOExplorerUtil.getCheckout(id);
+ if (checkout == null)
+ {
+ throw new CDOException("No checkout exists for " + uri);
+ }
+
+ if (!checkout.isOpen())
+ {
+ throw new CDOException("Checkout '" + checkout.getLabel() + "' is not open");
+ }
+
+ return checkout;
+ }
+
+ private CDOView getView(URI uri)
+ {
+ CDOCheckout checkout = getCheckout(uri);
+ return checkout.getView();
+ }
+
+ private void modify(CDOCheckout checkout, String path, boolean createOnDemand, ResourceNodeModifier<NODE> modifier) throws IOException
+ {
+ CDOTransaction transaction = null;
+
+ try
+ {
+ transaction = checkout.openTransaction();
+
+ NODE node = createOnDemand ? getOrCreateNode(transaction, path) : getNode(transaction, path);
+ modifier.modify(node);
+
+ CDOCommitInfo commitInfo = transaction.commit();
+ if (commitInfo != null)
+ {
+ CDOView view = checkout.getView();
+ view.waitForUpdate(commitInfo.getTimeStamp());
+ }
+ }
+ catch (Exception ex)
+ {
+ throw IOUtil.ioException(ex);
+ }
+ finally
+ {
+ IOUtil.closeSilent(transaction);
+ }
+ }
+
+ private static CDOExplorerURIHandler<?> getURIHandler(CDOResourceNode node)
+ {
+ if (node instanceof CDOTextResource)
+ {
+ return TEXT;
+ }
+
+ if (node instanceof CDOBinaryResource)
+ {
+ return TEXT;
+ }
+
+ return null;
+ }
+
+ public static URI createURI(CDOCheckout checkout, CDOResourceNode node)
+ {
+ CDOExplorerURIHandler<?> uriHandler = getURIHandler(node);
+ if (uriHandler == null)
+ {
+ return null;
+ }
+
+ String scheme = uriHandler.getScheme();
+ String authority = checkout.getID();
+ String[] segments = node.getURI().segments();
+
+ return URI.createHierarchicalURI(scheme, authority, null, segments, null, null);
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ @FunctionalInterface
+ private interface ResourceNodeModifier<NODE extends CDOResourceNode>
+ {
+ public void modify(NODE node) throws IOException;
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private static final class TextURIHandler extends CDOExplorerURIHandler<CDOTextResource>
+ {
+ public TextURIHandler()
+ {
+ super("text");
+ }
+
+ @Override
+ protected CDOTextResource getNode(CDOView view, String path) throws CDOResourceNodeNotFoundException
+ {
+ return view.getTextResource(path);
+ }
+
+ @Override
+ protected CDOTextResource getOrCreateNode(CDOTransaction transaction, String path)
+ {
+ return transaction.getOrCreateTextResource(path);
+ }
+
+ @Override
+ protected InputStream createInputStream(CDOTextResource node) throws IOException
+ {
+ CDOClob clob = node.getContents();
+ if (clob == null)
+ {
+ return new InputStream()
+ {
+ @Override
+ public int read() throws IOException
+ {
+ return IOUtil.EOF;
+ }
+ };
+ }
+
+ return new ReaderInputStream(clob.getContents(), node.getEncoding());
+ }
+
+ @Override
+ protected void setContents(CDOTextResource node, byte[] bytes, CDOLobStore lobStore) throws IOException
+ {
+ String encoding = node.getEncoding();
+ if (encoding == null)
+ {
+ encoding = StandardCharsets.UTF_8.toString();
+ }
+
+ CDOClob clob = new CDOClob(new StringReader(new String(bytes, encoding)), lobStore);
+ node.setContents(clob);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private static final class BinaryURIRHandler extends CDOExplorerURIHandler<CDOBinaryResource>
+ {
+ public BinaryURIRHandler()
+ {
+ super("binary");
+ }
+
+ @Override
+ protected CDOBinaryResource getNode(CDOView view, String path) throws CDOResourceNodeNotFoundException
+ {
+ return view.getBinaryResource(path);
+ }
+
+ @Override
+ protected CDOBinaryResource getOrCreateNode(CDOTransaction transaction, String path)
+ {
+ return transaction.getOrCreateBinaryResource(path);
+ }
+
+ @Override
+ protected InputStream createInputStream(CDOBinaryResource node) throws IOException
+ {
+ return node.getContents().getContents();
+ }
+
+ @Override
+ protected void setContents(CDOBinaryResource node, byte[] bytes, CDOLobStore lobStore) throws IOException
+ {
+ CDOBlob blob = new CDOBlob(new ByteArrayInputStream(bytes), lobStore);
+ node.setContents(blob);
+ }
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/bundle/OM.java b/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/bundle/OM.java
index 1d803b960d..f6470f5b55 100644
--- a/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/bundle/OM.java
+++ b/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/bundle/OM.java
@@ -11,6 +11,7 @@
*/
package org.eclipse.emf.cdo.internal.explorer.bundle;
+import org.eclipse.emf.cdo.internal.explorer.CDOExplorerURIHandler;
import org.eclipse.emf.cdo.internal.explorer.checkouts.CDOCheckoutManagerImpl;
import org.eclipse.emf.cdo.internal.explorer.repositories.CDORepositoryManagerImpl;
@@ -21,7 +22,16 @@ import org.eclipse.net4j.util.om.OSGiActivator;
import org.eclipse.net4j.util.om.log.OMLogger;
import org.eclipse.net4j.util.om.trace.OMTracer;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.URIConverter;
+import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl;
+import org.eclipse.emf.ecore.resource.impl.ResourceFactoryImpl;
+import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
+import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
+
import java.io.File;
+import java.util.Map;
/**
* The <em>Operations & Maintenance</em> class of this bundle.
@@ -40,6 +50,8 @@ public abstract class OM
private static final String STATE_LOCATION = OMPlatform.INSTANCE.getProperty("org.eclipse.emf.cdo.explorer.stateLocation");
+ private static final boolean OMIT_CHECKOUT_FILE_URI_HANDLERS = OMPlatform.INSTANCE.isProperty("org.eclipse.emf.cdo.explorer.omitCheckoutFileURIHandlers");
+
private static String stateLocation;
private static CDORepositoryManagerImpl repositoryManager;
@@ -116,6 +128,54 @@ public abstract class OM
*/
public static final class Activator extends OSGiActivator
{
+ private static final Resource.Factory TEXT_RESOURCE_FACTORY = new XMIResourceFactoryImpl()
+ {
+ @Override
+ public Resource createResource(URI uri)
+ {
+ return new XMIResourceImpl(uri)
+ {
+ private URIConverter uriConverter;
+
+ @Override
+ protected URIConverter getURIConverter()
+ {
+ if (uriConverter == null)
+ {
+ uriConverter = super.getURIConverter();
+ uriConverter.getURIHandlers().add(0, CDOExplorerURIHandler.TEXT);
+ }
+
+ return uriConverter;
+ }
+ };
+ }
+ };
+
+ private static final Resource.Factory BINARY_RESOURCE_FACTORY = new ResourceFactoryImpl()
+ {
+ @Override
+ public Resource createResource(URI uri)
+ {
+ return new BinaryResourceImpl(uri)
+ {
+ private URIConverter uriConverter;
+
+ @Override
+ protected URIConverter getURIConverter()
+ {
+ if (uriConverter == null)
+ {
+ uriConverter = super.getURIConverter();
+ uriConverter.getURIHandlers().add(0, CDOExplorerURIHandler.TEXT);
+ }
+
+ return uriConverter;
+ }
+ };
+ }
+ };
+
public Activator()
{
super(BUNDLE);
@@ -126,6 +186,13 @@ public abstract class OM
{
super.doStart();
+ if (!OMIT_CHECKOUT_FILE_URI_HANDLERS)
+ {
+ Map<String, Object> factoryMap = Resource.Factory.Registry.INSTANCE.getProtocolToFactoryMap();
+ factoryMap.put(CDOExplorerURIHandler.TEXT.getScheme(), TEXT_RESOURCE_FACTORY);
+ factoryMap.put(CDOExplorerURIHandler.BINARY.getScheme(), BINARY_RESOURCE_FACTORY);
+ }
+
stateLocation = STATE_LOCATION != null ? STATE_LOCATION : BUNDLE.getStateLocation();
initializeManagers(new File(stateLocation));
}
diff --git a/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/checkouts/CDOCheckoutViewProvider.java b/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/checkouts/CDOCheckoutViewProvider.java
index 1e0a054cea..caae1dc27c 100644
--- a/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/checkouts/CDOCheckoutViewProvider.java
+++ b/plugins/org.eclipse.emf.cdo.explorer/src/org/eclipse/emf/cdo/internal/explorer/checkouts/CDOCheckoutViewProvider.java
@@ -39,7 +39,7 @@ import java.util.Map;
*/
public class CDOCheckoutViewProvider extends AbstractCDOViewProvider
{
- public static final String SCHEME = "cdo.checkout";
+ public static final String SCHEME = CDOExplorerUtil.URI_SCHEME;
// TODO Move to activator and deactivate via stop().
private static final ReferenceMonitor<ResourceSet> MONITOR = new ReferenceMonitor<ResourceSet>()
diff --git a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOLobEditorInput.java b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOLobEditorInput.java
index 2bf858fff1..922fe5f0e3 100644
--- a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOLobEditorInput.java
+++ b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOLobEditorInput.java
@@ -12,6 +12,8 @@ package org.eclipse.emf.cdo.internal.ui.editor;
import org.eclipse.emf.cdo.eresource.CDOResourceLeaf;
+import org.eclipse.emf.common.util.URI;
+
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.IEditorInput;
@@ -28,6 +30,8 @@ public class CDOLobEditorInput extends PlatformObject implements IEditorInput
private final boolean commitOnSave;
+ private URI uri;
+
public CDOLobEditorInput(CDOResourceLeaf resource)
{
this(resource, false);
@@ -49,6 +53,16 @@ public class CDOLobEditorInput extends PlatformObject implements IEditorInput
return commitOnSave;
}
+ public final URI getURI()
+ {
+ return uri == null ? resource.getURI() : uri;
+ }
+
+ public final void setURI(URI uri)
+ {
+ this.uri = uri;
+ }
+
@Override
public boolean exists()
{
@@ -78,4 +92,18 @@ public class CDOLobEditorInput extends PlatformObject implements IEditorInput
{
return resource.getURI().toString();
}
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getAdapter(Class<T> type)
+ {
+ T adapter = super.getAdapter(type);
+
+ if (adapter == null && type == URI.class)
+ {
+ adapter = (T)getURI();
+ }
+
+ return adapter;
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOURIHandler.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOURIHandler.java
index d749af89f4..5be36fc821 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOURIHandler.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOURIHandler.java
@@ -11,11 +11,15 @@
*/
package org.eclipse.emf.internal.cdo.view;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.common.commit.CDOCommitInfo;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.eresource.CDOResourceFolder;
import org.eclipse.emf.cdo.eresource.CDOResourceNode;
+import org.eclipse.emf.cdo.session.CDOSession;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.util.CDOURIUtil;
+import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.cdo.view.CDOViewProvider;
import org.eclipse.emf.cdo.view.CDOViewProvider.CDOViewProvider2;
import org.eclipse.emf.cdo.view.CDOViewProviderRegistry;
@@ -101,26 +105,7 @@ public class CDOURIHandler implements URIHandler
@Override
public void delete(URI uri, Map<?, ?> options) throws IOException
{
- String path = CDOURIUtil.extractResourcePath(uri);
- CDOTransaction transaction = null;
-
- try
- {
- transaction = view.getSession().openTransaction();
- CDOResourceNode node = transaction.getResourceNode(path);
- node.delete(options);
- transaction.commit();
- }
- catch (Exception ex)
- {
- IOException ioException = new IOException(ex.getMessage());
- ioException.initCause(ex);
- throw ioException;
- }
- finally
- {
- IOUtil.closeSilent(transaction);
- }
+ modify(uri, node -> node.delete(options));
}
@Override
@@ -144,33 +129,10 @@ public class CDOURIHandler implements URIHandler
}
@Override
- @SuppressWarnings("unchecked")
public Map<String, ?> getAttributes(URI uri, Map<?, ?> options)
{
- Map<String, Object> result = new HashMap<>();
- String path = CDOURIUtil.extractResourcePath(uri);
- CDOResourceNode node = view.getResourceNode(path);
- if (node != null)
- {
- Set<String> requestedAttributes = (Set<String>)options.get(URIConverter.OPTION_REQUESTED_ATTRIBUTES);
- if (requestedAttributes == null || requestedAttributes.contains(URIConverter.ATTRIBUTE_TIME_STAMP))
- {
- long stamp = node instanceof CDOResource ? ((CDOResource)node).getTimeStamp() : URIConverter.NULL_TIME_STAMP;
- result.put(URIConverter.ATTRIBUTE_TIME_STAMP, stamp);
- }
-
- if (requestedAttributes == null || requestedAttributes.contains(URIConverter.ATTRIBUTE_DIRECTORY))
- {
- result.put(URIConverter.ATTRIBUTE_DIRECTORY, node instanceof CDOResourceFolder);
- }
-
- if (requestedAttributes == null || requestedAttributes.contains(URIConverter.ATTRIBUTE_READ_ONLY))
- {
- result.put(URIConverter.ATTRIBUTE_READ_ONLY, view.isReadOnly());
- }
- }
-
- return result;
+ String path = getPath(uri);
+ return getAttributes(view, path, options);
}
@Override
@@ -180,6 +142,12 @@ public class CDOURIHandler implements URIHandler
// storing that attribute in the server. Due to CDOResouce distributed nature, changing it wouldn't make much sense.
}
+ void setViewProvider2(CDOViewProvider2 viewProvider2)
+ {
+ this.viewProvider2 = viewProvider2;
+ viewURI = viewProvider2.getViewURI(view);
+ }
+
private String getPath(URI uri)
{
if (CDO_URI_SCHEME.equals(uri.scheme()))
@@ -198,9 +166,76 @@ public class CDOURIHandler implements URIHandler
return null;
}
- void setViewProvider2(CDOViewProvider2 viewProvider2)
+ private void modify(URI uri, ResourceNodeModifier modifier) throws IOException
{
- this.viewProvider2 = viewProvider2;
- viewURI = viewProvider2.getViewURI(view);
+ if (view.isHistorical())
+ {
+ throw new IOException("View is historical: " + view);
+ }
+
+ String path = getPath(uri);
+ CDOTransaction transaction = null;
+
+ try
+ {
+ CDOSession session = view.getSession();
+ CDOBranch branch = view.getBranch();
+ transaction = session.openTransaction(branch);
+
+ CDOResourceNode node = transaction.getResourceNode(path);
+ modifier.modify(node);
+
+ CDOCommitInfo commitInfo = transaction.commit();
+ if (commitInfo != null)
+ {
+ view.waitForUpdate(commitInfo.getTimeStamp());
+ }
+ }
+ catch (Exception ex)
+ {
+ throw IOUtil.ioException(ex);
+ }
+ finally
+ {
+ IOUtil.closeSilent(transaction);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Map<String, ?> getAttributes(CDOView view, String path, Map<?, ?> options)
+ {
+ Map<String, Object> result = new HashMap<>();
+
+ CDOResourceNode node = view.getResourceNode(path);
+ if (node != null)
+ {
+ Set<String> requestedAttributes = (Set<String>)options.get(URIConverter.OPTION_REQUESTED_ATTRIBUTES);
+ if (requestedAttributes == null || requestedAttributes.contains(URIConverter.ATTRIBUTE_TIME_STAMP))
+ {
+ long stamp = node instanceof CDOResource ? ((CDOResource)node).getTimeStamp() : URIConverter.NULL_TIME_STAMP;
+ result.put(URIConverter.ATTRIBUTE_TIME_STAMP, stamp);
+ }
+
+ if (requestedAttributes == null || requestedAttributes.contains(URIConverter.ATTRIBUTE_DIRECTORY))
+ {
+ result.put(URIConverter.ATTRIBUTE_DIRECTORY, node instanceof CDOResourceFolder);
+ }
+
+ if (requestedAttributes == null || requestedAttributes.contains(URIConverter.ATTRIBUTE_READ_ONLY))
+ {
+ result.put(URIConverter.ATTRIBUTE_READ_ONLY, view.isReadOnly());
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ @FunctionalInterface
+ private interface ResourceNodeModifier
+ {
+ public void modify(CDOResourceNode node) throws IOException;
}
}
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IORunnable.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IORunnable.java
index 7c40dabea0..8876a0bb30 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IORunnable.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IORunnable.java
@@ -16,6 +16,7 @@ import java.io.IOException;
/**
* @author Eike Stepper
*/
+@FunctionalInterface
public interface IORunnable<IO extends Closeable>
{
public void run(IO io) throws IOException;
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IOUtil.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IOUtil.java
index 9bb821777f..a55380e4d9 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IOUtil.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/IOUtil.java
@@ -108,6 +108,21 @@ public final class IOUtil
}
/**
+ * @since 3.13
+ */
+ public static IOException ioException(Exception ex)
+ {
+ if (ex instanceof IOException)
+ {
+ return (IOException)ex;
+ }
+
+ IOException ioException = new IOException(ex.getMessage());
+ ioException.initCause(ex);
+ return ioException;
+ }
+
+ /**
* @since 3.1
*/
public static void print(StackTraceElement[] elements)
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/ReaderInputStream.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/ReaderInputStream.java
new file mode 100644
index 0000000000..b9291ef374
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/ReaderInputStream.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2020 Eike Stepper (Loehne, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.net4j.util.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * An input stream for reading a {@link Reader}.
+ *
+ * @author Eike Stepper
+ * @since 3.13
+ */
+public class ReaderInputStream extends InputStream
+{
+ private static final int MASK = 0xFF;
+
+ private final Charset charset;
+
+ private Reader reader;
+
+ private CharBuffer chars = CharBuffer.allocate(IOUtil.DEFAULT_BUFFER_SIZE);
+
+ private ByteBuffer bytes;
+
+ public ReaderInputStream(Reader reader, String encoding) throws IOException
+ {
+ this.reader = reader;
+ charset = encoding == null ? StandardCharsets.UTF_8 : Charset.forName(encoding);
+ }
+
+ public ReaderInputStream(Reader reader) throws IOException
+ {
+ this(reader, null);
+ }
+
+ @Override
+ public int available() throws IOException
+ {
+ checkClosed();
+ ensureBytes();
+
+ if (bytes == null)
+ {
+ return 0;
+ }
+
+ return bytes.remaining();
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException
+ {
+ checkClosed();
+
+ if (len == 0)
+ {
+ return 0;
+ }
+
+ ensureBytes();
+ if (bytes == null)
+ {
+ return IOUtil.EOF;
+ }
+
+ int count = 0;
+ do
+ {
+ ensureBytes();
+
+ if (bytes == null)
+ {
+ // No more to read.
+ break;
+ }
+
+ int toRead = Math.min(bytes.remaining(), len - count);
+ bytes.get(b, off + count, toRead);
+ count = count + toRead;
+ } while (count < len);
+
+ return count;
+ }
+
+ @Override
+ public int read() throws IOException
+ {
+ checkClosed();
+
+ ensureBytes();
+ if (bytes == null)
+ {
+ return IOUtil.EOF;
+ }
+
+ return bytes.get() & MASK;
+ }
+
+ @Override
+ public void close() throws IOException
+ {
+ if (reader != null)
+ {
+ reader.close();
+ reader = null;
+ bytes = null;
+ chars = null;
+ }
+ }
+
+ private void ensureBytes() throws IOException
+ {
+ if (bytes == null || !bytes.hasRemaining())
+ {
+ checkClosed();
+
+ Buffer buffer = chars;
+ buffer.rewind();
+
+ int count = reader.read(chars);
+ if (count > 0)
+ {
+ buffer.flip();
+ bytes = charset.encode(chars);
+ }
+ else
+ {
+ bytes = null;
+ }
+ }
+ }
+
+ private void checkClosed() throws IOException
+ {
+ if (reader == null)
+ {
+ throw new IOException("Reader is closed"); //$NON-NLS-1$
+ }
+ }
+}

Back to the top