November 30, 2017
++ The Eclipse Foundation makes available all content in this plug-in + ("Content"). Unless otherwise indicated below, the Content + is provided to you under the terms and conditions of the Eclipse + Public License Version 2.0 ("EPL"). A copy of the EPL is + available at http://www.eclipse.org/legal/epl-2.0. + For purposes of the EPL, "Program" will mean the Content. +
+ ++ If you did not receive this Content directly from the Eclipse + Foundation, the Content is being redistributed by another party + ("Redistributor") and different terms and conditions may + apply to your use of any object code in the Content. Check the + Redistributor's license that was provided with the Content. If no such + license exists, contact the Redistributor. Unless otherwise indicated + below, the terms and conditions of the EPL still apply to any source + code in the Content and such source code may be obtained at http://www.eclipse.org. +
+ + + \ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.transport.native/build.properties b/bundles/org.eclipse.equinox.p2.transport.native/build.properties new file mode 100644 index 0000000000..02493d4636 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.transport.native/build.properties @@ -0,0 +1,23 @@ +############################################################################### +# Copyright (c) 2011 Sonatype Corporation and others. +# +# This program and the accompanying materials +# are made available under the terms of the Eclipse Public License 2.0 +# which accompanies this distribution, and is available at +# https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# Sonatype Corporation - initial API and implementation +# IBM Corporation - ongoing development +############################################################################### +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + OSGI-INF/,\ + about.html,\ + plugin.properties +src.includes = about.html + diff --git a/bundles/org.eclipse.equinox.p2.transport.native/forceQualifierUpdate.txt b/bundles/org.eclipse.equinox.p2.transport.native/forceQualifierUpdate.txt new file mode 100644 index 0000000000..d5e8883295 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.transport.native/forceQualifierUpdate.txt @@ -0,0 +1,4 @@ +# To force a version qualifier update add the bug here +Bug 403352 - Update all parent versions to match our build stream +Bug 527899 [9] Implement JEP 280: Indify String Concatenation +https://github.com/eclipse-platform/eclipse.platform.releng.aggregator/issues/1659 \ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.transport.native/plugin.properties b/bundles/org.eclipse.equinox.p2.transport.native/plugin.properties new file mode 100644 index 0000000000..9dde14708e --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.transport.native/plugin.properties @@ -0,0 +1,15 @@ +############################################################################### +# Copyright (c) 2010 - 2011 Sonatype, Inc. and others. +# +# This program and the accompanying materials +# are made available under the terms of the Eclipse Public License 2.0 +# which accompanies this distribution, and is available at +# https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# Sonatype, Inc. - initial API and implementation +############################################################################### +pluginName = Equinox Provisioning ECF based Transport +providerName = Eclipse.org - Equinox diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/Activator.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/Activator.java new file mode 100644 index 0000000000..859bd500c0 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/Activator.java @@ -0,0 +1,191 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 Cloudsmith Inc and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Cloudsmith Inc - initial API and implementation + * IBM Corporation - ongoing development + * Genuitec - Bug 291926 + * Red Hat Inc. - Bug 460967 + ******************************************************************************/ +package org.eclipse.equinox.internal.p2.transport.ecf; + +import java.util.*; +import org.eclipse.ecf.filetransfer.service.IRetrieveFileTransferFactory; +import org.eclipse.ecf.provider.filetransfer.IFileTransferProtocolToFactoryMapper; +import org.osgi.framework.*; +import org.osgi.util.tracker.ServiceTracker; + +/** + * The activator class controls the plug-in life cycle. This activator has + * helper methods to get file transfer service tracker, and for making sure + * required ECF bundles are started. + */ +@SuppressWarnings("restriction") +public class Activator implements BundleActivator { + + public static final String ID = "org.eclipse.equinox.p2.transport.ecf"; //$NON-NLS-1$ + private static final String HTTP = "http"; //$NON-NLS-1$ + private static final String HTTPS = "https"; //$NON-NLS-1$ + + private static BundleContext context; + // tracker for ECF service + private ServiceTrackernull
+ */
+ private synchronized void setStatistics(ProgressStatistics statistics) {
+ this.statistics = statistics;
+ }
+
+ /**
+ * Returns the progress statistics. This method is synchronized because the
+ * field is accessed from both the transfer thread and the thread initiating the
+ * transfer and we need to ensure field values are consistent across threads.
+ *
+ * @return the statistics, or null
+ */
+ private synchronized ProgressStatistics getStatistics() {
+ return statistics;
+ }
+
+ /**
+ * An interface to allow automated tests to hook into file reader events
+ *
+ * @see #setTestProbe
+ */
+ public interface IFileReaderProbe {
+ public void onStart(FileReader reader, IIncomingFileTransfer source, IProgressMonitor monitor);
+
+ public void onData(FileReader reader, IIncomingFileTransfer source, IProgressMonitor monitor);
+
+ public void onDone(FileReader reader, IIncomingFileTransfer source, IProgressMonitor monitor);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/Messages.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/Messages.java
new file mode 100644
index 0000000000..e582743625
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/Messages.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2012 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Cloudsmith Inc - additional messages
+ * Sonatype Inc - ongoing development
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.transport.ecf;
+
+import org.eclipse.osgi.util.NLS;
+
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.equinox.internal.p2.transport.ecf.messages"; //$NON-NLS-1$
+
+ public static String artifact_not_found;
+ public static String io_failedRead;
+
+ public static String exception_malformedRepoURI;
+ public static String TransportErrorTranslator_400;
+ public static String TransportErrorTranslator_401;
+ public static String TransportErrorTranslator_402;
+ public static String TransportErrorTranslator_403;
+ public static String TransportErrorTranslator_404;
+ public static String TransportErrorTranslator_405;
+ public static String TransportErrorTranslator_406;
+ public static String TransportErrorTranslator_407;
+ public static String TransportErrorTranslator_408;
+ public static String TransportErrorTranslator_409;
+ public static String TransportErrorTranslator_410;
+ public static String TransportErrorTranslator_411;
+ public static String TransportErrorTranslator_412;
+ public static String TransportErrorTranslator_413;
+ public static String TransportErrorTranslator_414;
+ public static String TransportErrorTranslator_415;
+ public static String TransportErrorTranslator_416;
+ public static String TransportErrorTranslator_417;
+ public static String TransportErrorTranslator_418;
+ public static String TransportErrorTranslator_422;
+ public static String TransportErrorTranslator_423;
+ public static String TransportErrorTranslator_424;
+ public static String TransportErrorTranslator_425;
+ public static String TransportErrorTranslator_426;
+ public static String TransportErrorTranslator_449;
+ public static String TransportErrorTranslator_450;
+ public static String TransportErrorTranslator_500;
+ public static String TransportErrorTranslator_501;
+ public static String TransportErrorTranslator_502;
+ public static String TransportErrorTranslator_503;
+ public static String TransportErrorTranslator_504;
+ public static String TransportErrorTranslator_505;
+ public static String TransportErrorTranslator_506;
+ public static String TransportErrorTranslator_507;
+ public static String TransportErrorTranslator_508;
+ public static String TransportErrorTranslator_510;
+ public static String TransportErrorTranslator_MalformedRemoteFileReference;
+ public static String TransportErrorTranslator_UnableToConnectToRepository_0;
+
+ public static String TransportErrorTranslator_UnknownErrorCode;
+ public static String TransportErrorTranslator_UnknownHost;
+
+ static {
+ // initialize resource bundles
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ // Do not instantiate
+ }
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/P2SSLContextFactory.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/P2SSLContextFactory.java
new file mode 100644
index 0000000000..4cfd64597c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/P2SSLContextFactory.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2025 Christoph Läubrich and others.
+ * The code, documentation and other materials contained herein have been
+ * licensed under the Eclipse Public License - v 1.0 by the copyright holder
+ * listed above, as the Initial Contributor under such license. The text of
+ * such license is available at www.eclipse.org.
+ * Contributors:
+ * Christoph Läubrich - initial implementation
+ ******************************************************************************/
+package org.eclipse.equinox.internal.p2.transport.ecf;
+
+import java.security.*;
+import javax.net.ssl.SSLContext;
+import org.eclipse.ecf.core.security.SSLContextFactory;
+import org.osgi.framework.Constants;
+import org.osgi.service.component.annotations.Component;
+
+@Component(property = Constants.SERVICE_RANKING + ":Integer=100")
+public class P2SSLContextFactory implements SSLContextFactory {
+
+ @Override
+ public SSLContext getDefault() throws NoSuchAlgorithmException {
+ // the default is guaranteed to be initialized always
+ return SSLContext.getDefault();
+ }
+
+ @Override
+ public SSLContext getInstance(String protocol) throws NoSuchAlgorithmException, NoSuchProviderException {
+ SSLContext context = SSLContext.getInstance(protocol);
+ try {
+ // init it as we have a new context here
+ context.init(null, null, null);
+ } catch (KeyManagementException e) {
+ throw new NoSuchProviderException();
+ }
+ return context;
+ }
+
+ @Override
+ public SSLContext getInstance(String protocol, String providerName)
+ throws NoSuchAlgorithmException, NoSuchProviderException {
+ SSLContext context = SSLContext.getInstance(protocol, providerName);
+ try {
+ // init it as we have a new context here
+ context.init(null, null, null);
+ } catch (KeyManagementException e) {
+ throw new NoSuchProviderException();
+ }
+ return context;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/RepositoryStatus.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/RepositoryStatus.java
new file mode 100644
index 0000000000..78440042dd
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/RepositoryStatus.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2010 Cloudsmith Inc. and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Cloudsmith Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.equinox.internal.p2.transport.ecf;
+
+import org.eclipse.equinox.internal.p2.repository.DownloadStatus;
+import org.eclipse.equinox.p2.core.ProvisionException;
+
+import java.io.FileNotFoundException;
+import java.net.*;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.ecf.core.identity.IDCreateException;
+import org.eclipse.ecf.filetransfer.BrowseFileTransferException;
+import org.eclipse.ecf.filetransfer.IncomingFileTransferException;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Utility class to transform transport errors into error messages.
+ */
+public class RepositoryStatus {
+
+ public static String codeToMessage(int code, String toDownload) {
+ switch (code) {
+ case 400 :
+ return NLS.bind(Messages.TransportErrorTranslator_400, toDownload);
+ case 401 :
+ return NLS.bind(Messages.TransportErrorTranslator_401, toDownload);
+ case 402 :
+ return NLS.bind(Messages.TransportErrorTranslator_402, toDownload);
+ case 403 :
+ return NLS.bind(Messages.TransportErrorTranslator_403, toDownload);
+ case 404 :
+ return NLS.bind(Messages.TransportErrorTranslator_404, toDownload);
+ case 405 :
+ return NLS.bind(Messages.TransportErrorTranslator_405, toDownload);
+ case 406 :
+ return NLS.bind(Messages.TransportErrorTranslator_406, toDownload);
+ case 407 :
+ return NLS.bind(Messages.TransportErrorTranslator_407, toDownload);
+ case 408 :
+ return NLS.bind(Messages.TransportErrorTranslator_408, toDownload);
+ case 409 :
+ return NLS.bind(Messages.TransportErrorTranslator_409, toDownload);
+ case 410 :
+ return NLS.bind(Messages.TransportErrorTranslator_410, toDownload);
+ case 411 :
+ return NLS.bind(Messages.TransportErrorTranslator_411, toDownload);
+ case 412 :
+ return NLS.bind(Messages.TransportErrorTranslator_412, toDownload);
+ case 413 :
+ return NLS.bind(Messages.TransportErrorTranslator_413, toDownload);
+ case 414 :
+ return NLS.bind(Messages.TransportErrorTranslator_414, toDownload);
+ case 415 :
+ return NLS.bind(Messages.TransportErrorTranslator_415, toDownload);
+ case 416 :
+ return NLS.bind(Messages.TransportErrorTranslator_416, toDownload);
+ case 417 :
+ return NLS.bind(Messages.TransportErrorTranslator_417, toDownload);
+ case 418 :
+ return NLS.bind(Messages.TransportErrorTranslator_418, toDownload);
+ case 422 :
+ return NLS.bind(Messages.TransportErrorTranslator_422, toDownload);
+ case 423 :
+ return NLS.bind(Messages.TransportErrorTranslator_423, toDownload);
+ case 424 :
+ return NLS.bind(Messages.TransportErrorTranslator_424, toDownload);
+ case 425 :
+ return NLS.bind(Messages.TransportErrorTranslator_425, toDownload);
+ case 426 :
+ return NLS.bind(Messages.TransportErrorTranslator_426, toDownload);
+ case 449 :
+ return NLS.bind(Messages.TransportErrorTranslator_449, toDownload);
+ case 450 :
+ return NLS.bind(Messages.TransportErrorTranslator_450, toDownload);
+
+ case 500 :
+ return NLS.bind(Messages.TransportErrorTranslator_500, toDownload);
+ case 501 :
+ return NLS.bind(Messages.TransportErrorTranslator_501, toDownload);
+ case 502 :
+ return NLS.bind(Messages.TransportErrorTranslator_502, toDownload);
+ case 503 :
+ return NLS.bind(Messages.TransportErrorTranslator_503, toDownload);
+ case 504 :
+ return NLS.bind(Messages.TransportErrorTranslator_504, toDownload);
+ case 505 :
+ return NLS.bind(Messages.TransportErrorTranslator_505, toDownload);
+ case 506 :
+ return NLS.bind(Messages.TransportErrorTranslator_506, toDownload);
+ case 507 :
+ return NLS.bind(Messages.TransportErrorTranslator_507, toDownload);
+ case 508 :
+ return NLS.bind(Messages.TransportErrorTranslator_508, toDownload);
+ case 510 :
+ return NLS.bind(Messages.TransportErrorTranslator_510, toDownload);
+
+ default :
+ return NLS.bind(Messages.TransportErrorTranslator_UnknownErrorCode, Integer.toString(code), toDownload);
+ }
+ }
+
+ public static DownloadStatus forStatus(IStatus original, URI toDownload) {
+ Throwable t = original.getException();
+ return forException(t, toDownload);
+ }
+
+ public static DownloadStatus forException(Throwable t, URI toDownload) {
+ if (t instanceof FileNotFoundException || (t instanceof IncomingFileTransferException && ((IncomingFileTransferException) t).getErrorCode() == 404)) {
+ return new DownloadStatus(IStatus.ERROR, Activator.ID, ProvisionException.ARTIFACT_NOT_FOUND, NLS.bind(Messages.artifact_not_found, toDownload), t);
+ }
+ if (t instanceof ConnectException) {
+ return new DownloadStatus(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_FAILED_READ, NLS.bind(Messages.TransportErrorTranslator_UnableToConnectToRepository_0, toDownload), t);
+ }
+ if (t instanceof UnknownHostException) {
+ return new DownloadStatus(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_INVALID_LOCATION, NLS.bind(Messages.TransportErrorTranslator_UnknownHost, toDownload), t);
+ }
+ if (t instanceof IDCreateException) {
+ IStatus status = ((IDCreateException) t).getStatus();
+ if (status != null && status.getException() != null) {
+ t = status.getException();
+ }
+
+ return new DownloadStatus(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_INVALID_LOCATION, NLS.bind(Messages.TransportErrorTranslator_MalformedRemoteFileReference, toDownload), t);
+ }
+ int code = 0;
+
+ // default to report as read repository error
+ int provisionCode = ProvisionException.REPOSITORY_FAILED_READ;
+
+ if (t instanceof IncomingFileTransferException) {
+ code = ((IncomingFileTransferException) t).getErrorCode();
+ } else if (t instanceof BrowseFileTransferException) {
+ code = ((BrowseFileTransferException) t).getErrorCode();
+ }
+
+ // Switch on error codes in the HTTP error code range.
+ // Note that 404 uses ARTIFACT_NOT_FOUND (as opposed to REPOSITORY_NOT_FOUND, which
+ // is determined higher up in the calling chain).
+ if (code == 401) {
+ provisionCode = ProvisionException.REPOSITORY_FAILED_AUTHENTICATION;
+ } else if (code == 404) {
+ provisionCode = ProvisionException.ARTIFACT_NOT_FOUND;
+ }
+
+ // Add more specific translation here
+
+ return new DownloadStatus(IStatus.ERROR, Activator.ID, provisionCode, //
+ code == 0 ? NLS.bind(Messages.io_failedRead, toDownload) //
+ : codeToMessage(code, toDownload.toString()), t);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/RepositoryStatusHelper.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/RepositoryStatusHelper.java
new file mode 100644
index 0000000000..99b216d4c7
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/RepositoryStatusHelper.java
@@ -0,0 +1,342 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2011 Cloudsmith Inc, and other.
+ * The code, documentation and other materials contained herein have been
+ * licensed under the Eclipse Public License - v 1.0 by the individual
+ * copyright holders listed above, as Initial Contributors under such license.
+ * The text of such license is available at www.eclipse.org.
+ * Contributors:
+ * Cloudsmith Inc. - Initial API and implementation
+ * IBM Corporation - Original Implementation of checkPermissionDenied
+ * IBM Corportaion - Ongoing development
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.transport.ecf;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.util.concurrent.ExecutionException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ecf.filetransfer.BrowseFileTransferException;
+import org.eclipse.ecf.filetransfer.IncomingFileTransferException;
+import org.eclipse.equinox.internal.p2.repository.AuthenticationFailedException;
+import org.eclipse.equinox.internal.p2.repository.JREHttpClientRequiredException;
+import org.eclipse.equinox.p2.core.ProvisionException;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * RepositoryStatusHelper is a utility class for processing of exceptions and status.
+ */
+public abstract class RepositoryStatusHelper {
+
+ protected static final String SERVER_REDIRECT = "Server redirected too many times"; //$NON-NLS-1$
+
+ public static IStatus createStatus(String nlsMessage, Object arg) {
+ return createExceptionStatus(null, nlsMessage, new Object[] {arg});
+ }
+
+ public static IStatus createStatus(String nlsMessage, Object arg1, Object arg2) {
+ return createExceptionStatus(null, nlsMessage, new Object[] {arg1, arg2});
+ }
+
+ public static IStatus createStatus(String nlsMessage, Object arg1, Object arg2, Object arg3) {
+ return createExceptionStatus(null, nlsMessage, new Object[] {arg1, arg2, arg3});
+ }
+
+ public static IStatus createStatus(String nlsMessage, Object[] args) {
+ return createExceptionStatus(null, nlsMessage, args);
+ }
+
+ public static IStatus createStatus(String nlsMessage) {
+ return createExceptionStatus(null, nlsMessage, new Object[] {});
+ }
+
+ public static IStatus createExceptionStatus(Throwable cause) {
+ return (cause instanceof CoreException c) ? c.getStatus() : new Status(IStatus.ERROR, Activator.ID, IStatus.OK, cause.getMessage(), cause);
+ }
+
+ public static IStatus createExceptionStatus(Throwable cause, String nlsMessage, Object[] args) {
+ if (args != null && args.length > 0) {
+ nlsMessage = NLS.bind(nlsMessage, args);
+ }
+ return new Status(IStatus.ERROR, Activator.ID, IStatus.OK, nlsMessage, cause);
+ }
+
+ public static IStatus createExceptionStatus(Throwable cause, String nlsMessage, Object arg1, Object arg2, Object arg3) {
+ return createExceptionStatus(cause, nlsMessage, new Object[] {arg1, arg2, arg3});
+ }
+
+ public static IStatus createExceptionStatus(Throwable cause, String nlsMessage, Object arg1, Object arg2) {
+ return createExceptionStatus(cause, nlsMessage, new Object[] {arg1, arg2});
+ }
+
+ public static IStatus createExceptionStatus(Throwable cause, String nlsMessage, Object arg1) {
+ return createExceptionStatus(cause, nlsMessage, new Object[] {arg1});
+ }
+
+ public static IStatus createExceptionStatus(Throwable cause, String nlsMessage) {
+ return createExceptionStatus(cause, nlsMessage, new Object[] {});
+ }
+
+ public static void deeplyPrint(Throwable e, PrintStream strm, boolean stackTrace) {
+ deeplyPrint(e, strm, stackTrace, 0);
+ }
+
+ public static CoreException fromMessage(String nlsMessage, Object[] args) {
+ return fromExceptionMessage(null, nlsMessage, args);
+ }
+
+ public static CoreException fromMessage(String nlsMessage, Object arg1) {
+ return fromExceptionMessage(null, nlsMessage, new Object[] {arg1});
+ }
+
+ public static CoreException fromMessage(String nlsMessage, Object arg1, Object arg2) {
+ return fromExceptionMessage(null, nlsMessage, new Object[] {arg1, arg2});
+ }
+
+ public static CoreException fromMessage(String nlsMessage, Object arg1, Object arg2, Object arg3) {
+ return fromExceptionMessage(null, nlsMessage, new Object[] {arg1, arg2, arg3});
+ }
+
+ public static CoreException fromMessage(String nlsMessage) {
+ return fromExceptionMessage(null, nlsMessage, new Object[] {});
+ }
+
+ public static CoreException fromExceptionMessage(Throwable cause, String nlsMessage, Object[] args) {
+ CoreException ce = new CoreException(createExceptionStatus(cause, nlsMessage, args));
+ if (cause != null) {
+ ce.initCause(cause);
+ }
+ return ce;
+ }
+
+ public static CoreException fromExceptionMessage(Throwable cause, String nlsMessage, Object arg1, Object arg2, Object arg3) {
+ return fromExceptionMessage(cause, nlsMessage, new Object[] {arg1, arg2, arg3});
+ }
+
+ public static CoreException fromExceptionMessage(Throwable cause, String nlsMessage, Object arg1, Object arg2) {
+ return fromExceptionMessage(cause, nlsMessage, new Object[] {arg1, arg2});
+ }
+
+ public static CoreException fromExceptionMessage(Throwable cause, String nlsMessage, Object arg1) {
+ return fromExceptionMessage(cause, nlsMessage, new Object[] {arg1});
+ }
+
+ public static CoreException fromExceptionMessage(Throwable cause, String nlsMessage) {
+ return fromExceptionMessage(cause, nlsMessage, new Object[] {});
+ }
+
+ public static Throwable unwind(Throwable t) {
+ for (;;) {
+ Class extends Throwable> tc = t.getClass();
+
+ // We don't use instanceof operator since we want
+ // the explicit class, not subclasses.
+ //
+ if (tc != RuntimeException.class && tc != InvocationTargetException.class && tc != IOException.class
+ && tc != ExecutionException.class) {
+ break;
+ }
+
+ Throwable cause = t.getCause();
+ if (cause == null) {
+ break;
+ }
+
+ String msg = t.getMessage();
+ if (msg != null && !msg.equals(cause.toString())) {
+ break;
+ }
+
+ t = cause;
+ }
+ return t;
+ }
+
+ public static CoreException unwindCoreException(CoreException exception) {
+ IStatus status = exception.getStatus();
+ while (status != null && status.getException() instanceof CoreException) {
+ exception = (CoreException) status.getException();
+ status = exception.getStatus();
+ }
+ return exception;
+ }
+
+ public static CoreException wrap(IStatus status) {
+ CoreException e = new CoreException(status);
+ Throwable t = status.getException();
+ if (t != null) {
+ e.initCause(t);
+ }
+ return e;
+ }
+
+ public static CoreException wrap(Throwable t) {
+ t = unwind(t);
+ if (t instanceof CoreException) {
+ return unwindCoreException((CoreException) t);
+ }
+
+ if (t instanceof OperationCanceledException || t instanceof InterruptedException) {
+ return new CoreException(Status.CANCEL_STATUS);
+ }
+
+ String msg = t.toString();
+ return fromExceptionMessage(t, msg);
+ }
+
+ private static void appendLevelString(PrintStream strm, int level) {
+ if (level > 0) {
+ strm.print("[0"); //$NON-NLS-1$
+ for (int idx = 1; idx < level; ++idx) {
+ strm.print('.');
+ strm.print(level);
+ }
+ strm.print(']');
+ }
+ }
+
+ private static void deeplyPrint(CoreException ce, PrintStream strm, boolean stackTrace, int level) {
+ appendLevelString(strm, level);
+ if (stackTrace) {
+ ce.printStackTrace(strm);
+ }
+ deeplyPrint(ce.getStatus(), strm, stackTrace, level);
+ }
+
+ private static void deeplyPrint(IStatus status, PrintStream strm, boolean stackTrace, int level) {
+ appendLevelString(strm, level);
+ String msg = status.getMessage();
+ strm.println(msg);
+ Throwable cause = status.getException();
+ if (cause != null) {
+ strm.print("Caused by: "); //$NON-NLS-1$
+ if (stackTrace || !(msg.equals(cause.getMessage()) || msg.equals(cause.toString()))) {
+ deeplyPrint(cause, strm, stackTrace, level);
+ }
+ }
+
+ if (status.isMultiStatus()) {
+ IStatus[] children = status.getChildren();
+ for (IStatus child : children) {
+ deeplyPrint(child, strm, stackTrace, level + 1);
+ }
+ }
+ }
+
+ private static void deeplyPrint(Throwable t, PrintStream strm, boolean stackTrace, int level) {
+ if (t instanceof CoreException) {
+ deeplyPrint((CoreException) t, strm, stackTrace, level);
+ } else {
+ appendLevelString(strm, level);
+ if (stackTrace) {
+ t.printStackTrace(strm);
+ } else {
+ strm.println(t.toString());
+ Throwable cause = t.getCause();
+ if (cause != null) {
+ strm.print("Caused by: "); //$NON-NLS-1$
+ deeplyPrint(cause, strm, stackTrace, level);
+ }
+ }
+ }
+ }
+
+ /**
+ * Check if the given exception represents that a switch to the JRE HTTP Client
+ * is required. ECF sets the HTTP status code 477 to indicate this.
+ * If the JRE HTTP client is required a JREHttpClientRequiredException is thrown.
+ */
+ public static void checkJREHttpClientRequired(Throwable t) throws JREHttpClientRequiredException {
+ if (t instanceof IncomingFileTransferException) {
+ if (((IncomingFileTransferException) t).getErrorCode() == 477) {
+ throw new JREHttpClientRequiredException();
+ }
+ } else if (t instanceof BrowseFileTransferException) {
+ if (((BrowseFileTransferException) t).getErrorCode() == 477) {
+ throw new JREHttpClientRequiredException();
+ }
+ }
+
+ }
+
+ /**
+ * Check if the given exception represents a permission failure (401 for HTTP),
+ * and throw a AuthenticationFailedException if a permission failure was encountered.
+ */
+ public static void checkPermissionDenied(Throwable t) throws AuthenticationFailedException {
+ // From Use of File Transfer
+ if (t instanceof IncomingFileTransferException) {
+ if (((IncomingFileTransferException) t).getErrorCode() == 401) {
+ throw new AuthenticationFailedException();
+ }
+ IStatus status = ((IncomingFileTransferException) t).getStatus();
+ t = status == null ? t : status.getException();
+ // From Use of Browse
+ } else if (t instanceof BrowseFileTransferException) {
+ if (((BrowseFileTransferException) t).getErrorCode() == 401) {
+ throw new AuthenticationFailedException();
+ }
+ IStatus status = ((BrowseFileTransferException) t).getStatus();
+ t = status == null ? t : status.getException();
+ }
+
+ if (t == null || !(t instanceof IOException)) {
+ return;
+ }
+
+ // TODO: is this needed (for 401) now that ECF throws exceptions with codes?
+ // try to figure out if we have a 401 by parsing the exception message
+ // There is unfortunately no specific (general) exception for "redirected too many times" - which is commonly
+ // caused by a failed login. The message and exception are different in different implementations
+ // of http client.
+ String m = t.getMessage();
+ if (m != null && (m.contains(" 401 ") || m.contains(SERVER_REDIRECT))) { //$NON-NLS-1$
+ throw new AuthenticationFailedException();
+ }
+ if ("org.apache.commons.httpclient.RedirectException".equals(t.getClass().getName())) { //$NON-NLS-1$
+ throw new AuthenticationFailedException();
+ }
+ }
+
+ /**
+ * Translates exceptions representing "FileNotFound" into FileNotFoundException.
+ * @param t the throwable to check
+ * @param toDownload the URI the exception was thrown for
+ * @throws FileNotFoundException if 't' represents a file not found
+ */
+ public static void checkFileNotFound(Throwable t, URI toDownload) throws FileNotFoundException {
+ if (t instanceof IncomingFileTransferException e) {
+ if (e.getErrorCode() == 404 || e.getErrorCode() == 403 || e.getErrorCode() == 300) {
+ throw new FileNotFoundException(toDownload.toString());
+ }
+ }
+ if (t instanceof BrowseFileTransferException e) {
+ if (e.getErrorCode() == 404 || e.getErrorCode() == 403 || e.getErrorCode() == 300) {
+ throw new FileNotFoundException(toDownload.toString());
+ }
+ }
+
+ if (t instanceof FileNotFoundException) {
+ throw (FileNotFoundException) t;
+ }
+ if (t instanceof CoreException) {
+ IStatus status = ((CoreException) t).getStatus();
+ Throwable e = status == null ? null : status.getException();
+ if (e instanceof FileNotFoundException) {
+ throw (FileNotFoundException) e;
+ }
+ }
+ }
+
+ public static IStatus malformedAddressStatus(String address, Throwable t) {
+ return new Status(IStatus.ERROR, Activator.ID, //
+ ProvisionException.REPOSITORY_INVALID_LOCATION, NLS.bind(Messages.exception_malformedRepoURI, address), t);
+
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/RepositoryTransport.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/RepositoryTransport.java
new file mode 100644
index 0000000000..8e123abc98
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/RepositoryTransport.java
@@ -0,0 +1,393 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2022 IBM Corporation and others.
+ * The code, documentation and other materials contained herein have been
+ * licensed under the Eclipse Public License - v 1.0 by the copyright holder
+ * listed above, as the Initial Contributor under such license. The text of
+ * such license is available at www.eclipse.org.
+ *
+ * Contributors
+ * IBM Corporation - Initial API and implementation.
+ * Cloudsmith Inc - Implementation
+ * Christoph Läubrich - Issue #6 - Deprecate Transport.download(URI, OutputStream, long, IProgressMonitor)
+ ******************************************************************************/
+
+package org.eclipse.equinox.internal.p2.transport.ecf;
+
+import java.io.*;
+import java.net.*;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import org.eclipse.core.runtime.*;
+import org.eclipse.ecf.core.identity.IDCreateException;
+import org.eclipse.ecf.core.security.ConnectContextFactory;
+import org.eclipse.ecf.core.security.IConnectContext;
+import org.eclipse.ecf.filetransfer.*;
+import org.eclipse.equinox.internal.p2.repository.*;
+import org.eclipse.equinox.internal.p2.repository.Credentials.LoginCanceledException;
+import org.eclipse.equinox.internal.p2.repository.Messages;
+import org.eclipse.equinox.internal.provisional.p2.core.eventbus.IProvisioningEventBus;
+import org.eclipse.equinox.internal.provisional.p2.core.eventbus.ProvisioningListener;
+import org.eclipse.equinox.internal.provisional.p2.repository.IStateful;
+import org.eclipse.equinox.p2.core.IProvisioningAgent;
+import org.eclipse.equinox.p2.core.ProvisionException;
+import org.eclipse.equinox.p2.core.UIServices.AuthenticationInfo;
+import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * RepositoryTransport adapts p2 to ECF file download and file browsing.
+ * Download is performed by {@link FileReader}, and file browsing is performed
+ * by {@link FileInfoReader}.
+ */
+public class RepositoryTransport extends Transport {
+
+ public static final String TIMEOUT_RETRY = "org.eclipse.equinox.p2.transport.ecf.retry"; //$NON-NLS-1$
+
+ private static class Retry {
+ long LIFETIME = TimeUnit.MINUTES.toMillis(10);
+ long expiration;
+ int count;
+
+ public Retry() {
+ expiration = System.currentTimeMillis() + LIFETIME;
+ }
+
+ public synchronized int increment() {
+ long now = System.currentTimeMillis();
+ if (now > expiration) {
+ expiration = now + LIFETIME;
+ count = 1;
+ return 1;
+ }
+ return ++count;
+ }
+ }
+
+ private static final Mapnull, it means client would like to use
+ * RepositoryTransport as a download utility, don't want to publish
+ * download progress.
+ */
+ public RepositoryTransport(IProvisioningAgent agent) {
+ this.agent = agent;
+ }
+
+ @Override
+ public IStatus download(URI toDownload, OutputStream target, IProgressMonitor monitor) {
+ boolean promptUser = false;
+ boolean useJREHttp = false;
+ AuthenticationInfo loginDetails = null;
+ URI secureToDownload;
+ try {
+ secureToDownload = getSecureLocation(toDownload);
+ } catch (CoreException e) {
+ return e.getStatus();
+ }
+ for (int i = RepositoryPreferences.getLoginRetryCount(); i > 0; i--) {
+ FileReader reader = null;
+ try {
+ loginDetails = Credentials.forLocation(secureToDownload, promptUser, loginDetails);
+ IConnectContext context = (loginDetails == null) ? null
+ : ConnectContextFactory.createUsernamePasswordConnectContext(loginDetails.getUserName(),
+ loginDetails.getPassword());
+
+ // perform the download
+ reader = new FileReader(agent, context);
+ ProvisioningListener listener = null;
+ IProvisioningEventBus eventBus = null;
+ try {
+ if (agent != null) {
+ eventBus = agent.getService(IProvisioningEventBus.class);
+ if (eventBus != null) {
+ final FileReader fileReader = reader;
+ listener = event -> {
+ if (event instanceof DownloadPauseResumeEvent) {
+ if (((DownloadPauseResumeEvent) event)
+ .getType() == DownloadPauseResumeEvent.TYPE_PAUSE) {
+ fileReader.pause();
+ } else if (((DownloadPauseResumeEvent) event)
+ .getType() == DownloadPauseResumeEvent.TYPE_RESUME) {
+ fileReader.resume();
+ }
+ }
+ };
+ eventBus.addListener(listener);
+ }
+ }
+ reader.readInto(secureToDownload, target, -1, monitor);
+ } finally {
+ if (eventBus != null) {
+ eventBus.removeListener(listener);
+ }
+ }
+
+ // check that job ended ok - throw exceptions otherwise
+ IStatus result = reader.getResult();
+ if (result == null) {
+ String msg = NLS.bind(Messages.RepositoryTransport_failedReadRepo, secureToDownload);
+ DownloadStatus ds = new DownloadStatus(IStatus.ERROR, Activator.ID,
+ ProvisionException.REPOSITORY_FAILED_READ, msg, null);
+ return statusOn(target, ds, reader);
+ }
+ if (result.getSeverity() == IStatus.CANCEL) {
+ throw new OperationCanceledException();
+ }
+ if (!result.isOK()) {
+ throw new CoreException(result);
+ }
+
+ // Download status is expected on success
+ DownloadStatus status = new DownloadStatus(IStatus.OK, Activator.ID, Status.OK_STATUS.getMessage());
+ return statusOn(target, status, reader);
+ } catch (UserCancelledException e) {
+ statusOn(target, new DownloadStatus(IStatus.CANCEL, Activator.ID, 1, "", null), reader); //$NON-NLS-1$
+ throw new OperationCanceledException();
+ } catch (OperationCanceledException e) {
+ statusOn(target, new DownloadStatus(IStatus.CANCEL, Activator.ID, 1, "", null), reader); //$NON-NLS-1$
+ throw e;
+ } catch (CoreException e) {
+ if (e.getStatus().getException() == null) {
+ return statusOn(target, forException(e, secureToDownload), reader);
+ }
+ return statusOn(target, forStatus(e.getStatus(), secureToDownload), reader);
+ } catch (FileNotFoundException e) {
+ return statusOn(target, forException(e, secureToDownload), reader);
+ } catch (AuthenticationFailedException e) {
+ promptUser = true;
+ } catch (Credentials.LoginCanceledException e) {
+ DownloadStatus status = new DownloadStatus(IStatus.ERROR, Activator.ID,
+ ProvisionException.REPOSITORY_FAILED_AUTHENTICATION, //
+ NLS.bind(Messages.UnableToRead_0_UserCanceled, secureToDownload), null);
+ return statusOn(target, status, null);
+ } catch (JREHttpClientRequiredException e) {
+ if (!useJREHttp) {
+ useJREHttp = true; // only do this once
+ i++; // need an extra retry
+ Activator.getDefault().useJREHttpClient();
+ }
+ }
+ }
+ // reached maximum number of retries without success
+ DownloadStatus status = new DownloadStatus(IStatus.ERROR, Activator.ID,
+ ProvisionException.REPOSITORY_FAILED_AUTHENTICATION, //
+ NLS.bind(Messages.UnableToRead_0_TooManyAttempts, secureToDownload), null);
+ return statusOn(target, status, null);
+ }
+
+ @Override
+ public InputStream stream(URI toDownload, IProgressMonitor monitor)
+ throws FileNotFoundException, CoreException, AuthenticationFailedException {
+
+ boolean promptUser = false;
+ boolean useJREHttp = false;
+ AuthenticationInfo loginDetails = null;
+ URI secureToDownload = getSecureLocation(toDownload);
+ for (int i = RepositoryPreferences.getLoginRetryCount(); i > 0; i--) {
+ FileReader reader = null;
+ try {
+ loginDetails = Credentials.forLocation(secureToDownload, promptUser, loginDetails);
+ IConnectContext context = (loginDetails == null) ? null
+ : ConnectContextFactory.createUsernamePasswordConnectContext(loginDetails.getUserName(),
+ loginDetails.getPassword());
+
+ // perform the streamed download
+ reader = new FileReader(agent, context);
+ return reader.read(secureToDownload, monitor);
+ } catch (UserCancelledException e) {
+ throw new OperationCanceledException();
+ } catch (AuthenticationFailedException e) {
+ promptUser = true;
+ } catch (CoreException e) {
+ // must translate this core exception as it is most likely not informative to a
+ // user
+ if (e.getStatus().getException() == null) {
+ throw new CoreException(forException(e, secureToDownload));
+ }
+ throw new CoreException(forStatus(e.getStatus(), secureToDownload));
+ } catch (LoginCanceledException e) {
+ // i.e. same behavior when user cancels as when failing n attempts.
+ throw new AuthenticationFailedException();
+ } catch (JREHttpClientRequiredException e) {
+ if (!useJREHttp) {
+ useJREHttp = true; // only do this once
+ i++; // need an extra retry
+ Activator.getDefault().useJREHttpClient();
+ }
+ }
+ }
+ throw new AuthenticationFailedException();
+ }
+
+ /**
+ * Set the status on the output stream if it implements IStateful. Update the
+ * DownloadStatus with information from FileReader.
+ *
+ * @param target an OutputStream possibly implementing IStateful
+ * @param status a DownloadStatus configured with status message, code, etc
+ * @param reader a FileReade that was used to download (or null if not known).
+ * @throws OperationCanceledException if the operation was canceled by the user.
+ * @return the configured DownloadStatus status.
+ */
+ private static DownloadStatus statusOn(OutputStream target, DownloadStatus status, FileReader reader) {
+ if (reader != null) {
+ FileInfo fi = reader.getLastFileInfo();
+ if (fi != null) {
+ status.setFileSize(fi.getSize());
+ status.setLastModified(fi.getLastModified());
+ status.setTransferRate(fi.getAverageSpeed());
+ }
+ }
+ if (target instanceof IStateful) {
+ ((IStateful) target).setStatus(status);
+ }
+ return status;
+ }
+
+ @Override
+ public long getLastModified(URI toDownload, IProgressMonitor monitor)
+ throws CoreException, FileNotFoundException, AuthenticationFailedException {
+ boolean promptUser = false;
+ boolean useJREHttp = false;
+ AuthenticationInfo loginDetails = null;
+ URI secureToDownload = getSecureLocation(toDownload);
+ for (int i = RepositoryPreferences.getLoginRetryCount(); i > 0; i--) {
+ try {
+ loginDetails = Credentials.forLocation(secureToDownload, promptUser, loginDetails);
+ IConnectContext context = (loginDetails == null) ? null
+ : ConnectContextFactory.createUsernamePasswordConnectContext(loginDetails.getUserName(),
+ loginDetails.getPassword());
+ // get the remote info
+ FileInfoReader reader = new FileInfoReader(context);
+ return reader.getLastModified(secureToDownload, monitor);
+ } catch (UserCancelledException e) {
+ throw new OperationCanceledException();
+ } catch (CoreException e) {
+ // must translate this core exception as it is most likely not informative to a
+ // user
+ if (e.getStatus().getException() == null) {
+ throw new CoreException(forException(e, secureToDownload));
+ }
+ throw new CoreException(forStatus(e.getStatus(), secureToDownload));
+ } catch (AuthenticationFailedException e) {
+ promptUser = true;
+ } catch (LoginCanceledException e) {
+ // same behavior as if user failed n attempts.
+ throw new AuthenticationFailedException();
+ } catch (JREHttpClientRequiredException e) {
+ if (!useJREHttp) {
+ useJREHttp = true; // only do this once
+ i++; // need an extra retry
+ Activator.getDefault().useJREHttpClient();
+ }
+ }
+
+ }
+ // reached maximum number of authentication retries without success
+ throw new AuthenticationFailedException();
+ }
+
+ private static boolean isForgiveableException(Throwable t) {
+ if (t instanceof SocketTimeoutException) {
+ return true;
+ } else if (t instanceof SocketException) {
+ return true;
+ } else if (t instanceof IncomingFileTransferException
+ && ((IncomingFileTransferException) t).getErrorCode() == 503) {
+ return true;
+ }
+ return false;
+ }
+
+ public static DownloadStatus forStatus(IStatus original, URI toDownload) {
+ Throwable t = original.getException();
+ if (isForgiveableException(t) && original.getCode() == IArtifactRepository.CODE_RETRY) {
+ return new DownloadStatus(original.getSeverity(), Activator.ID, original.getCode(), original.getMessage(),
+ t);
+ }
+ return forException(t, toDownload);
+ }
+
+ public static DownloadStatus forException(Throwable t, URI toDownload) {
+ if (isForgiveableException(t)) {
+ int retry = Integer.getInteger(TIMEOUT_RETRY, 0);
+ if (retry > 0) {
+ int retryCount = SOCKET_EXCEPTION_RETRY.computeIfAbsent(toDownload, uri -> new Retry()).increment();
+ if (retryCount <= retry) {
+ return new DownloadStatus(IStatus.ERROR, Activator.ID, IArtifactRepository.CODE_RETRY, NLS.bind(
+ Messages.connection_to_0_failed_on_1_retry_attempt_2,
+ toDownload.toString(), t.getMessage(), Integer.toString(retryCount)), t);
+ }
+ }
+ }
+ if (t instanceof FileNotFoundException || (t instanceof IncomingFileTransferException
+ && ((IncomingFileTransferException) t).getErrorCode() == 404)) {
+ return new DownloadStatus(IStatus.ERROR, Activator.ID, ProvisionException.ARTIFACT_NOT_FOUND,
+ NLS.bind(Messages.artifact_not_found, toDownload), t);
+ }
+ if (t instanceof ConnectException) {
+ return new DownloadStatus(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_FAILED_READ,
+ NLS.bind(Messages.TransportErrorTranslator_UnableToConnectToRepository_0, toDownload), t);
+ }
+ if (t instanceof UnknownHostException) {
+ return new DownloadStatus(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_INVALID_LOCATION,
+ NLS.bind(Messages.TransportErrorTranslator_UnknownHost, toDownload), t);
+ }
+ if (t instanceof IDCreateException) {
+ IStatus status = ((IDCreateException) t).getStatus();
+ if (status != null && status.getException() != null) {
+ t = status.getException();
+ }
+
+ return new DownloadStatus(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_INVALID_LOCATION,
+ NLS.bind(Messages.TransportErrorTranslator_MalformedRemoteFileReference, toDownload), t);
+ }
+ int code = 0;
+
+ // default to report as read repository error
+ int provisionCode = ProvisionException.REPOSITORY_FAILED_READ;
+
+ if (t instanceof IncomingFileTransferException) {
+ code = ((IncomingFileTransferException) t).getErrorCode();
+ } else if (t instanceof BrowseFileTransferException) {
+ code = ((BrowseFileTransferException) t).getErrorCode();
+ }
+
+ // Switch on error codes in the HTTP error code range.
+ // Note that 404 uses ARTIFACT_NOT_FOUND (as opposed to REPOSITORY_NOT_FOUND,
+ // which
+ // is determined higher up in the calling chain).
+ if (code == 401) {
+ provisionCode = ProvisionException.REPOSITORY_FAILED_AUTHENTICATION;
+ } else if (code == 404) {
+ provisionCode = ProvisionException.ARTIFACT_NOT_FOUND;
+ }
+
+ // Add more specific translation here
+
+ return new DownloadStatus(IStatus.ERROR, Activator.ID, provisionCode, //
+ code == 0 ? NLS.bind(Messages.io_failedRead, toDownload) //
+ : RepositoryStatus.codeToMessage(code, toDownload.toString()),
+ t);
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/messages.properties b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/messages.properties
new file mode 100644
index 0000000000..2ee026d0ae
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/messages.properties
@@ -0,0 +1,61 @@
+###############################################################################
+# Copyright (c) 2007, 2012 IBM Corporation and others.
+#
+# This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License 2.0
+# which accompanies this distribution, and is available at
+# https://www.eclipse.org/legal/epl-2.0/
+#
+# SPDX-License-Identifier: EPL-2.0
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+# Cloudsmith Inc - additional messages
+# Sonatype Inc - ongoing implementation
+###############################################################################
+artifact_not_found=Artifact not found: {0}.
+
+io_failedRead=Unable to read repository at {0}.
+
+exception_malformedRepoURI = The repository location ({0}) must be a URI.
+
+TransportErrorTranslator_400=Bad HTTP Request: {0}
+TransportErrorTranslator_401=Authentication Failed - Unauthorized: {0}
+TransportErrorTranslator_402=HTTP Payment Required: {0}
+TransportErrorTranslator_403=HTTP Access Forbidden: {0}
+TransportErrorTranslator_404=HTTP Remote File Not Found: {0}
+TransportErrorTranslator_405=HTTP Method Not Allowed: {0}
+TransportErrorTranslator_406=HTTP Request Not Acceptable: {0}
+TransportErrorTranslator_407=HTTP Proxy Authentication Required: {0}
+TransportErrorTranslator_408=HTTP Request Timeout: {0}
+TransportErrorTranslator_409=HTTP Conflict In Request: {0}
+TransportErrorTranslator_410=HTTP Remote File Permanently Removed: {0}
+TransportErrorTranslator_411=HTTP Length Required: {0}
+TransportErrorTranslator_412=HTTP Precondition Failed: {0}
+TransportErrorTranslator_413=HTTP Requested Entity Too Large: {0}
+TransportErrorTranslator_414=HTTP Request URI Too Long: {0}
+TransportErrorTranslator_415=HTTP Unsupported Media Type: {0}
+TransportErrorTranslator_416=HTTP Requested Range Not Satisfiable: {0}
+TransportErrorTranslator_417=HTTP Expectation Failed: {0}
+TransportErrorTranslator_418=HTTP Cannot provision coffee from a tea pot: {0}
+TransportErrorTranslator_422=HTTP (WebDav) Unprocessable Entity: {0}
+TransportErrorTranslator_423=HTTP (WebDAV) Locked: {0}
+TransportErrorTranslator_424=HTTP (WebDAV) Failed Dependency: {0}
+TransportErrorTranslator_425=HTTP Unordered Collection: {0}
+TransportErrorTranslator_426=HTTP Upgrade Required: {0}
+TransportErrorTranslator_449=HTTP Retry With Response: {0}
+TransportErrorTranslator_450=HTTP Blocked By Parental Control: {0}
+TransportErrorTranslator_500=HTTP Server ''Internal Error'': {0}
+TransportErrorTranslator_501=HTTP Server ''Not Implemented'': {0}
+TransportErrorTranslator_502=HTTP Server ''Bad Gateway'' : {0}
+TransportErrorTranslator_503=HTTP Server ''Service Unavailable'': {0}
+TransportErrorTranslator_504=HTTP Server ''Gateway Timeout'': {0}
+TransportErrorTranslator_505=HTTP Server ''HTTP Version Not Supported'': {0}
+TransportErrorTranslator_506=HTTP Server ''Variant Also Negotiates'': {0}
+TransportErrorTranslator_507=HTTP (WebDAV) ''Insufficient Storage'': {0}
+TransportErrorTranslator_508=HTTP Server ''Bandwidth Limit Exceeded'': {0}
+TransportErrorTranslator_510=HTTP Server ''Not Extended'': {0}
+TransportErrorTranslator_MalformedRemoteFileReference=Malformed reference to remote file: {0}
+TransportErrorTranslator_UnableToConnectToRepository_0=Unable to connect to repository {0}
+TransportErrorTranslator_UnknownErrorCode=HTTP Server Unknown HTTP Response Code ({0}):{1}
+TransportErrorTranslator_UnknownHost=Unknown Host: {0}
From 618846776f74f4393fdde0fdd45471b75969a81a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 13 Dec 2025 16:00:27 +0000
Subject: [PATCH 3/4] Copy ECF source code into native transport bundle
Co-authored-by: laeubi <1331477+laeubi@users.noreply.github.com>
---
.../META-INF/MANIFEST.MF | 34 +-
.../eclipse/ecf/core/AbstractContainer.java | 100 ++
.../core/AbstractContainerAdapterFactory.java | 56 +
.../org/eclipse/ecf/core/BaseContainer.java | 136 +++
.../ContainerAuthenticationException.java | 39 +
.../ecf/core/ContainerConnectException.java | 46 +
.../ecf/core/ContainerCreateException.java | 44 +
.../eclipse/ecf/core/ContainerFactory.java | 606 +++++++++++
.../ecf/core/ContainerTypeDescription.java | 289 +++++
.../src/org/eclipse/ecf/core/IContainer.java | 214 ++++
.../eclipse/ecf/core/IContainerFactory.java | 336 ++++++
.../eclipse/ecf/core/IContainerListener.java | 49 +
.../eclipse/ecf/core/IContainerManager.java | 131 +++
.../ecf/core/IContainerManagerListener.java | 42 +
.../eclipse/ecf/core/IReliableContainer.java | 35 +
.../core/events/ContainerConnectedEvent.java | 55 +
.../core/events/ContainerConnectingEvent.java | 62 ++
.../events/ContainerDisconnectedEvent.java | 68 ++
.../events/ContainerDisconnectingEvent.java | 55 +
.../core/events/ContainerDisposeEvent.java | 43 +
.../core/events/ContainerEjectedEvent.java | 55 +
.../core/events/IContainerConnectedEvent.java | 27 +
.../events/IContainerConnectingEvent.java | 34 +
.../events/IContainerDisconnectedEvent.java | 28 +
.../events/IContainerDisconnectingEvent.java | 28 +
.../core/events/IContainerDisposeEvent.java | 20 +
.../core/events/IContainerEjectedEvent.java | 37 +
.../ecf/core/events/IContainerEvent.java | 28 +
.../org/eclipse/ecf/core/identity/BaseID.java | 164 +++
.../org/eclipse/ecf/core/identity/GUID.java | 164 +++
.../src/org/eclipse/ecf/core/identity/ID.java | 66 ++
.../ecf/core/identity/IDCreateException.java | 39 +
.../eclipse/ecf/core/identity/IDFactory.java | 306 ++++++
.../eclipse/ecf/core/identity/IIDFactory.java | 288 +++++
.../ecf/core/identity/IIdentifiable.java | 26 +
.../ecf/core/identity/IResourceID.java | 34 +
.../org/eclipse/ecf/core/identity/LongID.java | 108 ++
.../eclipse/ecf/core/identity/Namespace.java | 328 ++++++
.../core/identity/NamespacePermission.java | 55 +
.../eclipse/ecf/core/identity/StringID.java | 144 +++
.../org/eclipse/ecf/core/identity/URIID.java | 131 +++
.../org/eclipse/ecf/core/identity/UuID.java | 114 ++
.../eclipse/ecf/core/jobs/JobsExecutor.java | 99 ++
.../provider/BaseContainerInstantiator.java | 244 +++++
...aseRemoteServiceContainerInstantiator.java | 38 +
.../provider/ContainerInstantiatorUtils.java | 136 +++
.../provider/ContainerIntentException.java | 46 +
.../core/provider/IContainerInstantiator.java | 114 ++
.../IRemoteServiceContainerInstantiator.java | 85 ++
.../ecf/core/security/BooleanCallback.java | 112 ++
.../eclipse/ecf/core/security/Callback.java | 16 +
.../ecf/core/security/CallbackHandler.java | 18 +
.../core/security/ConnectContextFactory.java | 106 ++
.../core/security/ECFSSLContextFactory.java | 111 ++
.../ecf/core/security/IConnectContext.java | 33 +
.../core/security/IConnectHandlerPolicy.java | 40 +
.../security/IConnectInitiatorPolicy.java | 38 +
.../ecf/core/security/IContainerPolicy.java | 20 +
.../ecf/core/security/NameCallback.java | 116 ++
.../ecf/core/security/ObjectCallback.java | 36 +
.../ecf/core/security/PassphraseCallback.java | 116 ++
.../ecf/core/security/PasswordCallback.java | 116 ++
.../ecf/core/security/SSLContextFactory.java | 44 +
.../UnsupportedCallbackException.java | 64 ++
.../eclipse/ecf/core/start/ECFStartJob.java | 35 +
.../org/eclipse/ecf/core/start/IECFStart.java | 30 +
.../core/status/SerializableMultiStatus.java | 165 +++
.../ecf/core/status/SerializableStatus.java | 289 +++++
.../src/org/eclipse/ecf/core/user/IUser.java | 46 +
.../src/org/eclipse/ecf/core/user/User.java | 111 ++
.../ecf/core/util/AbstractFactory.java | 37 +
.../ecf/core/util/AdapterContainerFilter.java | 43 +
.../ecf/core/util/AdapterManagerTracker.java | 43 +
.../src/org/eclipse/ecf/core/util/Base64.java | 219 ++++
.../ecf/core/util/BundleClassResolver.java | 48 +
.../eclipse/ecf/core/util/BundleStarter.java | 30 +
.../util/ClassResolverObjectInputStream.java | 109 ++
.../core/util/ConnectedContainerFilter.java | 41 +
.../core/util/ContainerFactoryTracker.java | 33 +
.../core/util/ContainerManagerTracker.java | 33 +
.../eclipse/ecf/core/util/ECFException.java | 57 +
.../ecf/core/util/ECFRuntimeException.java | 87 ++
.../src/org/eclipse/ecf/core/util/Event.java | 21 +
.../core/util/ExtensionRegistryRunnable.java | 74 ++
.../eclipse/ecf/core/util/IClassResolver.java | 24 +
.../ecf/core/util/IContainerFilter.java | 33 +
.../ecf/core/util/IDFactoryTracker.java | 38 +
.../ecf/core/util/IEventProcessor.java | 32 +
.../ecf/core/util/IExceptionHandler.java | 27 +
.../org/eclipse/ecf/core/util/LogHelper.java | 58 +
.../ecf/core/util/OSGIObjectInputStream.java | 446 ++++++++
.../ecf/core/util/OSGIObjectOutputStream.java | 446 ++++++++
.../core/util/OSGIObjectStreamConstants.java | 55 +
.../eclipse/ecf/core/util/PlatformHelper.java | 109 ++
.../src/org/eclipse/ecf/core/util/Proxy.java | 149 +++
.../eclipse/ecf/core/util/ProxyAddress.java | 71 ++
.../src/org/eclipse/ecf/core/util/SerDTO.java | 79 ++
.../org/eclipse/ecf/core/util/SerVersion.java | 31 +
.../eclipse/ecf/core/util/StringUtils.java | 310 ++++++
.../ecf/core/util/SystemLogService.java | 125 +++
.../src/org/eclipse/ecf/core/util/Trace.java | 538 ++++++++++
.../ecf/core/util/reflection/ClassUtil.java | 130 +++
.../BrowseFileTransferException.java | 70 ++
.../ecf/filetransfer/FileTransferInfo.java | 115 ++
.../ecf/filetransfer/FileTransferJob.java | 85 ++
.../filetransfer/IFileRangeSpecification.java | 74 ++
.../ecf/filetransfer/IFileTransfer.java | 97 ++
.../ecf/filetransfer/IFileTransferInfo.java | 64 ++
.../filetransfer/IFileTransferListener.java | 51 +
.../filetransfer/IFileTransferPausable.java | 57 +
.../IFileTransferRateControl.java | 51 +
.../filetransfer/IFileTransferRunnable.java | 33 +
.../filetransfer/IIncomingFileTransfer.java | 68 ++
.../IIncomingFileTransferRequestListener.java | 32 +
.../filetransfer/IOutgoingFileTransfer.java | 29 +
.../eclipse/ecf/filetransfer/IRemoteFile.java | 37 +
.../filetransfer/IRemoteFileAttributes.java | 52 +
.../ecf/filetransfer/IRemoteFileInfo.java | 95 ++
...moteFileSystemBrowserContainerAdapter.java | 75 ++
.../IRemoteFileSystemListener.java | 49 +
.../IRemoteFileSystemRequest.java | 40 +
...IRetrieveFileTransferContainerAdapter.java | 218 ++++
.../IRetrieveFileTransferOptions.java | 47 +
.../ISendFileTransferContainerAdapter.java | 188 ++++
.../ISendFileTransferOptions.java | 22 +
.../IncomingFileTransferException.java | 117 +++
...nvalidFileRangeSpecificationException.java | 76 ++
.../RemoteFileSystemException.java | 62 ++
.../SendFileTransferException.java | 70 ++
.../filetransfer/UserCancelledException.java | 45 +
.../IFileTransferConnectStartEvent.java | 95 ++
.../events/IFileTransferEvent.java | 22 +
.../events/IFileTransferRequestEvent.java | 102 ++
.../events/IIncomingFileTransferEvent.java | 28 +
...IIncomingFileTransferReceiveDataEvent.java | 24 +
...IIncomingFileTransferReceiveDoneEvent.java | 39 +
...ncomingFileTransferReceivePausedEvent.java | 21 +
...comingFileTransferReceiveResumedEvent.java | 155 +++
...IncomingFileTransferReceiveStartEvent.java | 143 +++
.../events/IOutgoingFileTransferEvent.java | 28 +
.../IOutgoingFileTransferResponseEvent.java | 40 +
.../IOutgoingFileTransferSendDataEvent.java | 24 +
.../IOutgoingFileTransferSendDoneEvent.java | 25 +
.../IOutgoingFileTransferSendPausedEvent.java | 21 +
...IOutgoingFileTransferSendResumedEvent.java | 22 +
.../events/IRemoteFileSystemBrowseEvent.java | 41 +
.../events/IRemoteFileSystemEvent.java | 27 +
.../events/socket/ISocketClosedEvent.java | 37 +
.../events/socket/ISocketConnectedEvent.java | 42 +
.../events/socket/ISocketCreatedEvent.java | 30 +
.../events/socket/ISocketEvent.java | 58 +
.../events/socket/ISocketEventSource.java | 25 +
.../events/socket/ISocketListener.java | 18 +
.../INonconnectedSocketFactory.java | 22 +
.../identity/FileCreateException.java | 46 +
.../filetransfer/identity/FileIDFactory.java | 129 +++
.../ecf/filetransfer/identity/IFileID.java | 49 +
.../filetransfer/identity/IFileIDFactory.java | 92 ++
.../service/IRemoteFileSystemBrowser.java | 23 +
.../IRemoteFileSystemBrowserFactory.java | 29 +
.../service/IRetrieveFileTransfer.java | 21 +
.../service/IRetrieveFileTransferFactory.java | 29 +
.../service/ISendFileTransfer.java | 21 +
.../service/ISendFileTransferFactory.java | 30 +
.../ecf/internal/core/ECFDebugOptions.java | 27 +
.../eclipse/ecf/internal/core/ECFPlugin.java | 583 +++++++++++
.../ecf/internal/core/IDisposable.java | 16 +
.../ecf/internal/core/identity/Activator.java | 315 ++++++
.../ecf/internal/filetransfer/Activator.java | 133 +++
.../FileTransferDebugOptions.java | 26 +
.../ProxyURLStreamHandlerService.java | 89 ++
.../provider/filetransfer/Activator.java | 923 ++++++++++++++++
.../provider/filetransfer/DebugOptions.java | 26 +
.../filetransfer/IURLConnectionModifier.java | 29 +
.../provider/filetransfer/Messages.java | 81 ++
.../provider/filetransfer/messages.properties | 59 ++
.../IFileTransferProtocolToFactoryMapper.java | 230 ++++
.../browse/AbstractFileSystemBrowser.java | 267 +++++
.../browse/LocalFileSystemBrowser.java | 65 ++
.../filetransfer/browse/LocalRemoteFile.java | 120 +++
.../browse/LocalRemoteFileAttributes.java | 86 ++
...MultiProtocolFileSystemBrowserAdapter.java | 112 ++
...otocolFileSystemBrowserAdapterFactory.java | 47 +
.../browse/URLFileSystemBrowser.java | 209 ++++
.../filetransfer/browse/URLRemoteFile.java | 135 +++
.../browse/URLRemoteFileAttributes.java | 77 ++
.../events/socket/AbstractSocketEvent.java | 68 ++
.../events/socket/AbstractSocketWrapper.java | 217 ++++
.../events/socket/SocketClosedEvent.java | 29 +
.../events/socket/SocketConnectedEvent.java | 33 +
.../events/socket/SocketCreatedEvent.java | 29 +
.../events/socket/SocketEventCreateUtil.java | 75 ++
.../events/socket/SocketEventSource.java | 53 +
.../filetransfer/identity/FileTransferID.java | 101 ++
.../identity/FileTransferNamespace.java | 102 ++
.../AbstractOutgoingFileTransfer.java | 468 +++++++++
...ractUrlConnectionOutgoingFileTransfer.java | 146 +++
.../LocalFileOutgoingFileTransfer.java | 71 ++
.../MultiProtocolOutgoingAdapter.java | 165 +++
.../MultiProtocolOutgoingAdapterFactory.java | 47 +
.../AbstractRetrieveFileTransfer.java | 991 ++++++++++++++++++
.../filetransfer/retrieve/HttpHelper.java | 41 +
.../MultiProtocolRetrieveAdapter.java | 164 +++
.../MultiProtocolRetrieveAdapterFactory.java | 47 +
.../UrlConnectionRetrieveFileTransfer.java | 574 ++++++++++
.../filetransfer/util/JREProxyHelper.java | 92 ++
.../filetransfer/util/PollingInputStream.java | 276 +++++
.../filetransfer/util/ProxySetupHelper.java | 105 ++
.../filetransfer/util/TimeoutInputStream.java | 378 +++++++
209 files changed, 22165 insertions(+), 3 deletions(-)
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/AbstractContainer.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/AbstractContainerAdapterFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/BaseContainer.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerAuthenticationException.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerConnectException.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerCreateException.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerTypeDescription.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainer.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainerFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainerListener.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainerManager.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainerManagerListener.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IReliableContainer.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerConnectedEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerConnectingEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerDisconnectedEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerDisconnectingEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerDisposeEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerEjectedEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerConnectedEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerConnectingEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerDisconnectedEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerDisconnectingEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerDisposeEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerEjectedEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/BaseID.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/GUID.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/ID.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/IDCreateException.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/IDFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/IIDFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/IIdentifiable.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/IResourceID.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/LongID.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/Namespace.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/NamespacePermission.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/StringID.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/URIID.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/UuID.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/jobs/JobsExecutor.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/BaseContainerInstantiator.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/BaseRemoteServiceContainerInstantiator.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/ContainerInstantiatorUtils.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/ContainerIntentException.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/IContainerInstantiator.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/IRemoteServiceContainerInstantiator.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/BooleanCallback.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/Callback.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/CallbackHandler.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/ConnectContextFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/ECFSSLContextFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/IConnectContext.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/IConnectHandlerPolicy.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/IConnectInitiatorPolicy.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/IContainerPolicy.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/NameCallback.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/ObjectCallback.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/PassphraseCallback.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/PasswordCallback.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/SSLContextFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/UnsupportedCallbackException.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/start/ECFStartJob.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/start/IECFStart.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/status/SerializableMultiStatus.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/status/SerializableStatus.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/user/IUser.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/user/User.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/AbstractFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/AdapterContainerFilter.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/AdapterManagerTracker.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/Base64.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/BundleClassResolver.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/BundleStarter.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/ClassResolverObjectInputStream.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/ConnectedContainerFilter.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/ContainerFactoryTracker.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/ContainerManagerTracker.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/ECFException.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/ECFRuntimeException.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/Event.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/ExtensionRegistryRunnable.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/IClassResolver.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/IContainerFilter.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/IDFactoryTracker.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/IEventProcessor.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/IExceptionHandler.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/LogHelper.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/OSGIObjectInputStream.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/OSGIObjectOutputStream.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/OSGIObjectStreamConstants.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/PlatformHelper.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/Proxy.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/ProxyAddress.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/SerDTO.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/SerVersion.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/StringUtils.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/SystemLogService.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/Trace.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/reflection/ClassUtil.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/BrowseFileTransferException.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/FileTransferInfo.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/FileTransferJob.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileRangeSpecification.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransfer.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferInfo.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferListener.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferPausable.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferRateControl.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferRunnable.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IIncomingFileTransfer.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IIncomingFileTransferRequestListener.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IOutgoingFileTransfer.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFile.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileAttributes.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileInfo.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileSystemBrowserContainerAdapter.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileSystemListener.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileSystemRequest.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRetrieveFileTransferContainerAdapter.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRetrieveFileTransferOptions.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/ISendFileTransferContainerAdapter.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/ISendFileTransferOptions.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IncomingFileTransferException.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/InvalidFileRangeSpecificationException.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/RemoteFileSystemException.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/SendFileTransferException.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/UserCancelledException.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IFileTransferConnectStartEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IFileTransferEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IFileTransferRequestEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceiveDataEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceiveDoneEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceivePausedEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceiveResumedEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceiveStartEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferResponseEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferSendDataEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferSendDoneEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferSendPausedEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferSendResumedEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IRemoteFileSystemBrowseEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IRemoteFileSystemEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/socket/ISocketClosedEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/socket/ISocketConnectedEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/socket/ISocketCreatedEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/socket/ISocketEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/socket/ISocketEventSource.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/socket/ISocketListener.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/socketfactory/INonconnectedSocketFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/identity/FileCreateException.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/identity/FileIDFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/identity/IFileID.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/identity/IFileIDFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/IRemoteFileSystemBrowser.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/IRemoteFileSystemBrowserFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/IRetrieveFileTransfer.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/IRetrieveFileTransferFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/ISendFileTransfer.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/ISendFileTransferFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/core/ECFDebugOptions.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/core/ECFPlugin.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/core/IDisposable.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/core/identity/Activator.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/filetransfer/Activator.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/filetransfer/FileTransferDebugOptions.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/filetransfer/ProxyURLStreamHandlerService.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/provider/filetransfer/Activator.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/provider/filetransfer/DebugOptions.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/provider/filetransfer/IURLConnectionModifier.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/provider/filetransfer/Messages.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/provider/filetransfer/messages.properties
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/IFileTransferProtocolToFactoryMapper.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/AbstractFileSystemBrowser.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/LocalFileSystemBrowser.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/LocalRemoteFile.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/LocalRemoteFileAttributes.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/MultiProtocolFileSystemBrowserAdapter.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/MultiProtocolFileSystemBrowserAdapterFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/URLFileSystemBrowser.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/URLRemoteFile.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/URLRemoteFileAttributes.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/events/socket/AbstractSocketEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/events/socket/AbstractSocketWrapper.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/events/socket/SocketClosedEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/events/socket/SocketConnectedEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/events/socket/SocketCreatedEvent.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/events/socket/SocketEventCreateUtil.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/events/socket/SocketEventSource.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/identity/FileTransferID.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/identity/FileTransferNamespace.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/outgoing/AbstractOutgoingFileTransfer.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/outgoing/AbstractUrlConnectionOutgoingFileTransfer.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/outgoing/LocalFileOutgoingFileTransfer.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/outgoing/MultiProtocolOutgoingAdapter.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/outgoing/MultiProtocolOutgoingAdapterFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/retrieve/AbstractRetrieveFileTransfer.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/retrieve/HttpHelper.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/retrieve/MultiProtocolRetrieveAdapter.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/retrieve/MultiProtocolRetrieveAdapterFactory.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/retrieve/UrlConnectionRetrieveFileTransfer.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/util/JREProxyHelper.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/util/PollingInputStream.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/util/ProxySetupHelper.java
create mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/util/TimeoutInputStream.java
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.transport.native/META-INF/MANIFEST.MF
index dc35b20534..caf3b4ec3f 100644
--- a/bundles/org.eclipse.equinox.p2.transport.native/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.transport.native/META-INF/MANIFEST.MF
@@ -7,14 +7,42 @@ Bundle-RequiredExecutionEnvironment: JavaSE-17
Require-Bundle: org.eclipse.equinox.p2.core;bundle-version="2.0.100",
org.eclipse.equinox.p2.repository;bundle-version="2.1.0",
org.eclipse.equinox.common;bundle-version="3.6.0",
- org.eclipse.core.jobs;bundle-version="3.5.100"
+ org.eclipse.core.jobs;bundle-version="3.5.100",
+ org.eclipse.equinox.registry;bundle-version="3.0.0";resolution:=optional
Service-Component: OSGI-INF/nativeTransport.xml
Bundle-Activator: org.eclipse.equinox.internal.p2.transport.ecf.Activator
Bundle-ActivationPolicy: lazy
-Export-Package: org.eclipse.equinox.internal.p2.transport.ecf;x-friends:="org.eclipse.equinox.p2.discovery.compatibility,org.eclipse.equinox.p2.installer"
+Export-Package: org.eclipse.ecf.core;version="3.0.0",
+ org.eclipse.ecf.core.events;version="3.1.0",
+ org.eclipse.ecf.core.jobs;version="1.1.0",
+ org.eclipse.ecf.core.provider;version="3.3.0",
+ org.eclipse.ecf.core.security;version="3.2.0",
+ org.eclipse.ecf.core.start;version="3.1.0",
+ org.eclipse.ecf.core.status;version="1.1.0",
+ org.eclipse.ecf.core.user;version="3.1.0",
+ org.eclipse.ecf.core.util;version="3.6.0",
+ org.eclipse.ecf.core.util.reflection;version="2.3.0",
+ org.eclipse.ecf.filetransfer;version="5.0.0",
+ org.eclipse.ecf.filetransfer.events;version="5.0.0",
+ org.eclipse.ecf.filetransfer.events.socketfactory;version="5.0.0",
+ org.eclipse.ecf.filetransfer.identity;version="5.0.0",
+ org.eclipse.ecf.filetransfer.service;version="5.0.0",
+ org.eclipse.ecf.provider.filetransfer;version="3.2.0",
+ org.eclipse.ecf.provider.filetransfer.browse;version="3.2.0",
+ org.eclipse.ecf.provider.filetransfer.identity;version="3.2.0",
+ org.eclipse.ecf.provider.filetransfer.outgoing;version="3.2.0",
+ org.eclipse.ecf.provider.filetransfer.retrieve;version="3.2.0",
+ org.eclipse.ecf.provider.filetransfer.util;version="3.2.0",
+ org.eclipse.equinox.internal.p2.transport.ecf;x-friends:="org.eclipse.equinox.p2.discovery.compatibility,org.eclipse.equinox.p2.installer"
Bundle-Vendor: %providerName
Bundle-Localization: plugin
-Import-Package: org.eclipse.osgi.util;version="1.1.0",
+Import-Package: org.eclipse.core.net.proxy;resolution:=optional,
+ org.eclipse.core.runtime.jobs,
+ org.eclipse.equinox.concurrent.future;version="[1.0.0,2.0.0)";resolution:=optional,
+ org.eclipse.osgi.util;version="1.1.0",
org.osgi.framework;version="1.6.0",
+ org.osgi.service.log;version="[1.3.0,2.0.0)",
+ org.osgi.service.url;version="[1.0.0,2.0.0)",
org.osgi.util.tracker;version="1.5.0"
Automatic-Module-Name: org.eclipse.equinox.p2.transport.native
+DynamicImport-Package: *
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/AbstractContainer.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/AbstractContainer.java
new file mode 100644
index 0000000000..21e06d2bbd
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/AbstractContainer.java
@@ -0,0 +1,100 @@
+/****************************************************************************
+ * Copyright (c) 2006 IBM, Inc and Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Chris Aniszczyk null.
+ * @param adapterType the type (interface) of the adapter on the given container. Will not be null
+ * @return Object the container adapter instance. May be null.
+ */
+ protected abstract Object getContainerAdapter(IContainer container, Class adapterType);
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IAdapterFactory#getAdapterList()
+ */
+ public abstract Class>[] getAdapterList();
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/BaseContainer.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/BaseContainer.java
new file mode 100644
index 0000000000..81215d4138
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/BaseContainer.java
@@ -0,0 +1,136 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.ecf.core.identity.*;
+import org.eclipse.ecf.core.provider.BaseContainerInstantiator;
+import org.eclipse.ecf.core.security.IConnectContext;
+
+/**
+ * Base implementation of IContainer. Subclasses may be created to fill out the
+ * behavior of this base implementation. Also, adapter factories may be created
+ * via adapterFactory extension point to allow adapters to be added to this
+ * BaseContainer implementation without the need to create a separate IContainer
+ * implementation class.
+ */
+public class BaseContainer extends AbstractContainer {
+
+ public static class Instantiator extends BaseContainerInstantiator {
+
+ /**
+ * @since 3.4
+ */
+ public static final String NAME = "ecf.base"; //$NON-NLS-1$
+
+ private static long nextBaseContainerID = 0L;
+
+ public IContainer createInstance(ContainerTypeDescription description, Object[] parameters) throws ContainerCreateException {
+ try {
+ if (parameters != null && parameters.length > 0) {
+ if (parameters[0] instanceof ID)
+ return new BaseContainer((ID) parameters[0]);
+ if (parameters[0] instanceof String)
+ return new BaseContainer(IDFactory.getDefault().createStringID((String) parameters[0]));
+ }
+ } catch (IDCreateException e) {
+ throw new ContainerCreateException("Could not create ID for basecontainer"); //$NON-NLS-1$
+ }
+ return new BaseContainer(nextBaseContainerID++);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.provider.IContainerInstantiator#getSupportedAdapterTypes(org.eclipse.ecf.core.ContainerTypeDescription)
+ */
+ public String[] getSupportedAdapterTypes(ContainerTypeDescription description) {
+ return getInterfacesAndAdaptersForClass(BaseContainer.class);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.core.provider.BaseContainerInstantiator#getSupportedParameterTypes(org.eclipse.ecf.core.ContainerTypeDescription)
+ */
+ public Class[][] getSupportedParameterTypes(ContainerTypeDescription description) {
+ return new Class[][] { {}, {ID.class}, {String.class}};
+ }
+
+ }
+
+ private ID id = null;
+
+ protected BaseContainer(long idl) throws ContainerCreateException {
+ try {
+ this.id = IDFactory.getDefault().createLongID(idl);
+ } catch (IDCreateException e) {
+ throw new ContainerCreateException("Could not create ID for basecontainer", e); //$NON-NLS-1$
+ }
+ }
+
+ protected BaseContainer(ID id) {
+ Assert.isNotNull(id);
+ this.id = id;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainer#connect(org.eclipse.ecf.core.identity.ID,
+ * org.eclipse.ecf.core.security.IConnectContext)
+ */
+ public void connect(ID targetID, IConnectContext connectContext) throws ContainerConnectException {
+ throw new ContainerConnectException("Connect not supported"); //$NON-NLS-1$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainer#disconnect()
+ */
+ public void disconnect() {
+ // Nothing to disconnect
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainer#getConnectNamespace()
+ */
+ public Namespace getConnectNamespace() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainer#getConnectedID()
+ */
+ public ID getConnectedID() {
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.identity.IIdentifiable#getID()
+ */
+ public ID getID() {
+ return id;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer("BaseContainer["); //$NON-NLS-1$
+ sb.append("id=").append(getID()).append("]"); //$NON-NLS-1$ //$NON-NLS-2$
+ return sb.toString();
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerAuthenticationException.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerAuthenticationException.java
new file mode 100644
index 0000000000..8563a6a8d4
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerAuthenticationException.java
@@ -0,0 +1,39 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core;
+
+/**
+ * Exception class to be thrown upon authentication failure during connect
+ *
+ * @see IContainer#connect(org.eclipse.ecf.core.identity.ID,
+ * org.eclipse.ecf.core.security.IConnectContext)
+ */
+public class ContainerAuthenticationException extends ContainerConnectException {
+ private static final long serialVersionUID = 7038962779623213444L;
+
+ public ContainerAuthenticationException() {
+ super();
+ }
+
+ public ContainerAuthenticationException(String message) {
+ super(message);
+ }
+
+ public ContainerAuthenticationException(Throwable cause) {
+ super(cause);
+ }
+
+ public ContainerAuthenticationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerConnectException.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerConnectException.java
new file mode 100644
index 0000000000..230bfe09be
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerConnectException.java
@@ -0,0 +1,46 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.ecf.core.util.ECFException;
+
+/**
+ * Exception class to be thrown upon connection failure.
+ *
+ * @see IContainer#connect(org.eclipse.ecf.core.identity.ID,
+ * org.eclipse.ecf.core.security.IConnectContext)
+ *
+ */
+public class ContainerConnectException extends ECFException {
+ private static final long serialVersionUID = 4078658849424746859L;
+
+ public ContainerConnectException() {
+ super();
+ }
+
+ public ContainerConnectException(String message) {
+ super(message);
+ }
+
+ public ContainerConnectException(Throwable cause) {
+ super(cause);
+ }
+
+ public ContainerConnectException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ContainerConnectException(IStatus status) {
+ super(status);
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerCreateException.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerCreateException.java
new file mode 100644
index 0000000000..13c1a6e5b9
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerCreateException.java
@@ -0,0 +1,44 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.ecf.core.util.ECFException;
+
+/**
+ * Exception thrown during container creation
+ *
+ * @see ContainerFactory#createContainer(ContainerTypeDescription, Object[])
+ */
+public class ContainerCreateException extends ECFException {
+ private static final long serialVersionUID = -6979687717421003065L;
+
+ public ContainerCreateException(IStatus status) {
+ super(status);
+ }
+
+ public ContainerCreateException() {
+ super();
+ }
+
+ public ContainerCreateException(String message) {
+ super(message);
+ }
+
+ public ContainerCreateException(Throwable cause) {
+ super(cause);
+ }
+
+ public ContainerCreateException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerFactory.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerFactory.java
new file mode 100644
index 0000000000..68f18cc862
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerFactory.java
@@ -0,0 +1,606 @@
+/****************************************************************************
+ * Copyright (c) 2004, 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core;
+
+import java.util.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.ecf.core.identity.ID;
+import org.eclipse.ecf.core.provider.IContainerInstantiator;
+import org.eclipse.ecf.core.util.Trace;
+import org.eclipse.ecf.internal.core.*;
+
+/**
+ * Factory for creating {@link IContainer} instances. This class provides ECF
+ * clients an entry point to constructing {@link IContainer} instances.
+ * IContainer container =
+ * ContainerFactory.getDefault().createContainer("ecf.generic.client");
+ *
+ * ...further use of container here...
+ * For more details on the creation
+ * and lifecycle of IContainer instances created via this factory see
+ * {@link IContainer}.
+ *
+ * @see IContainer
+ * @see IContainerFactory
+ * @since 3.1
+ */
+public class ContainerFactory implements IContainerFactory, IContainerManager {
+
+ public static final String BASE_CONTAINER_NAME = "ecf.base"; //$NON-NLS-1$
+
+ static final Map containerdescriptions = new HashMap();
+
+ static final Map containers = new HashMap();
+
+ static final List managerListeners = new ArrayList();
+
+ private static IContainerFactory instance = null;
+
+ private volatile static boolean init = false;
+
+ static {
+ instance = new ContainerFactory();
+ }
+
+ class ContainerEntry {
+ private final IContainer container;
+ private final ContainerTypeDescription typeDescription;
+
+ public ContainerEntry(IContainer container, ContainerTypeDescription typeDescription) {
+ this.container = container;
+ this.typeDescription = typeDescription;
+ }
+
+ public IContainer getContainer() {
+ return this.container;
+ }
+
+ public ContainerTypeDescription getContainerTypeDescription() {
+ return this.typeDescription;
+ }
+ }
+
+ public synchronized static IContainerFactory getDefault() {
+ if (init == false) {
+ // first mark the extension initalized because it initializeExtensions()
+ // eventually calls this method again
+ init = true;
+ ECFPlugin.getDefault().initializeExtensions();
+ }
+ return instance;
+ }
+
+ protected ContainerFactory() {
+ ECFPlugin.getDefault().addDisposable(new IDisposable() {
+ public void dispose() {
+ synchronized (containers) {
+ for (Iterator i = containers.keySet().iterator(); i.hasNext();) {
+ ContainerEntry entry = (ContainerEntry) containers.get(i.next());
+ if (entry != null) {
+ IContainer c = entry.getContainer();
+ try {
+ c.dispose();
+ } catch (Throwable e) {
+ // Log exception
+ ECFPlugin.getDefault().log(new Status(IStatus.ERROR, ECFPlugin.getDefault().getBundle().getSymbolicName(), IStatus.ERROR, "container dispose error", e)); //$NON-NLS-1$
+ Trace.catching(ECFPlugin.PLUGIN_ID, ECFDebugOptions.EXCEPTIONS_CATCHING, ContainerFactory.class, "doDispose", e); //$NON-NLS-1$
+ }
+ }
+ }
+ containers.clear();
+ }
+ containerdescriptions.clear();
+ managerListeners.clear();
+ }
+ });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainerFactory#addDescription(org.eclipse.ecf.core.ContainerTypeDescription)
+ */
+ public ContainerTypeDescription addDescription(ContainerTypeDescription containerTypeDescription) {
+ return addDescription0(containerTypeDescription);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainerFactory#getDescriptions()
+ */
+ public List getDescriptions() {
+ return getDescriptions0();
+ }
+
+ protected List getDescriptions0() {
+ synchronized (containerdescriptions) {
+ return new ArrayList(containerdescriptions.values());
+ }
+ }
+
+ protected ContainerTypeDescription addDescription0(ContainerTypeDescription containerTypeDescription) {
+ if (containerTypeDescription == null)
+ return null;
+ synchronized (containerdescriptions) {
+ return (ContainerTypeDescription) containerdescriptions.put(containerTypeDescription.getName(), containerTypeDescription);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainerFactory#containsDescription(org.eclipse.ecf.core.ContainerTypeDescription)
+ */
+ public boolean containsDescription(ContainerTypeDescription containerTypeDescription) {
+ return containsDescription0(containerTypeDescription);
+ }
+
+ protected boolean containsDescription0(ContainerTypeDescription containerTypeDescription) {
+ if (containerTypeDescription == null)
+ return false;
+ synchronized (containerdescriptions) {
+ return containerdescriptions.containsKey(containerTypeDescription.getName());
+ }
+ }
+
+ protected ContainerTypeDescription getDescription0(ContainerTypeDescription containerTypeDescription) {
+ if (containerTypeDescription == null)
+ return null;
+ synchronized (containerdescriptions) {
+ return (ContainerTypeDescription) containerdescriptions.get(containerTypeDescription.getName());
+ }
+ }
+
+ protected ContainerTypeDescription getDescription0(String containerTypeDescriptionName) {
+ if (containerTypeDescriptionName == null)
+ return null;
+ synchronized (containerdescriptions) {
+ return (ContainerTypeDescription) containerdescriptions.get(containerTypeDescriptionName);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainerFactory#getDescriptionByName(java.lang.String)
+ */
+ public ContainerTypeDescription getDescriptionByName(String containerTypeDescriptionName) {
+ return getDescription0(containerTypeDescriptionName);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainerFactory#removeDescription(org.eclipse.ecf.core.ContainerTypeDescription)
+ */
+ public ContainerTypeDescription removeDescription(ContainerTypeDescription containerTypeDescription) {
+ return removeDescription0(containerTypeDescription);
+
+ }
+
+ protected ContainerTypeDescription removeDescription0(ContainerTypeDescription containerTypeDescription) {
+ if (containerTypeDescription == null)
+ return null;
+ synchronized (containerdescriptions) {
+ return (ContainerTypeDescription) containerdescriptions.remove(containerTypeDescription.getName());
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainerFactory#getDescriptionsForContainerAdapter(java.lang.Class)
+ */
+ public ContainerTypeDescription[] getDescriptionsForContainerAdapter(Class containerAdapter) {
+ if (containerAdapter == null)
+ throw new NullPointerException("containerAdapter cannot be null"); //$NON-NLS-1$
+ List result = new ArrayList();
+ List descriptions = getDescriptions();
+ for (Iterator i = descriptions.iterator(); i.hasNext();) {
+ ContainerTypeDescription description = (ContainerTypeDescription) i.next();
+ String[] supportedAdapters = description.getSupportedAdapterTypes();
+ if (supportedAdapters != null) {
+ for (int j = 0; j < supportedAdapters.length; j++) {
+ if (supportedAdapters[j].equals(containerAdapter.getName()))
+ result.add(description);
+ }
+ }
+ }
+ return (ContainerTypeDescription[]) result.toArray(new ContainerTypeDescription[] {});
+ }
+
+ protected void throwContainerCreateException(String message, Throwable cause, String method) throws ContainerCreateException {
+ ContainerCreateException except = (cause == null) ? new ContainerCreateException(message) : new ContainerCreateException(message, cause);
+ Trace.throwing(ECFPlugin.PLUGIN_ID, ECFDebugOptions.EXCEPTIONS_THROWING, ContainerFactory.class, method, except);
+ throw except;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainerFactory#createContainer()
+ */
+ public IContainer createContainer() throws ContainerCreateException {
+ return createContainer(BASE_CONTAINER_NAME);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.core.IContainerFactory#createContainer(org.eclipse.ecf.core.identity.ID)
+ */
+ public IContainer createContainer(ID containerID) throws ContainerCreateException {
+ if (containerID == null)
+ return createContainer();
+ return createContainer(BASE_CONTAINER_NAME, new Object[] {containerID});
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.core.IContainerFactory#createContainer(org.eclipse.ecf.core.ContainerTypeDescription)
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription) throws ContainerCreateException {
+ return createContainer(containerTypeDescription, (Object[]) null);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainerFactory#createContainer(java.lang.String)
+ */
+ public IContainer createContainer(String containerTypeDescriptionName) throws ContainerCreateException {
+ return createContainer(getDescriptionByNameWithException(containerTypeDescriptionName), (Object[]) null);
+ }
+
+ private ContainerTypeDescription getDescriptionByNameWithException(String containerTypeDescriptionName) throws ContainerCreateException {
+ ContainerTypeDescription typeDescription = getDescriptionByName(containerTypeDescriptionName);
+ if (typeDescription == null)
+ throw new ContainerCreateException("Container type description with name=" + containerTypeDescriptionName + " not found. This may indicate that the desired provider is not available or not startable within runtime."); //$NON-NLS-1$ //$NON-NLS-2$
+ return typeDescription;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainerFactory#createContainer(org.eclipse.ecf.core.ContainerTypeDescription,
+ * java.lang.Object[])
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, Object[] parameters) throws ContainerCreateException {
+ String method = "createContainer"; //$NON-NLS-1$
+ Trace.entering(ECFPlugin.PLUGIN_ID, ECFDebugOptions.METHODS_ENTERING, ContainerFactory.class, method, new Object[] {containerTypeDescription, Trace.getArgumentsString(parameters)});
+ if (containerTypeDescription == null)
+ throwContainerCreateException("ContainerTypeDescription cannot be null", null, method); //$NON-NLS-1$
+ ContainerTypeDescription cd = getDescription0(containerTypeDescription);
+ if (cd == null)
+ throwContainerCreateException("ContainerTypeDescription '" //$NON-NLS-1$
+ + containerTypeDescription.getName() + "' not found", null, method); //$NON-NLS-1$
+ IContainerInstantiator instantiator = null;
+ try {
+ instantiator = cd.getInstantiator();
+ } catch (Exception e) {
+ throwContainerCreateException("createContainer cannot get IContainerInstantiator for description : " //$NON-NLS-1$
+ + containerTypeDescription, e, method);
+ }
+ // Ask instantiator to actually create instance
+ IContainer container = instantiator.createInstance(containerTypeDescription, parameters);
+ if (container == null)
+ throwContainerCreateException("Instantiator returned null for '" //$NON-NLS-1$
+ + cd.getName() + "'", null, method); //$NON-NLS-1$
+ // Add to containers map if container.getID() provides a valid value.
+ ID containerID = container.getID();
+ if (containerID != null)
+ addContainer(container, cd);
+ Trace.exiting(ECFPlugin.PLUGIN_ID, ECFDebugOptions.METHODS_EXITING, ContainerFactory.class, method, container);
+ return container;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainerFactory#createContainer(java.lang.String,
+ * java.lang.Object[])
+ */
+ public IContainer createContainer(String containerTypeDescriptionName, Object[] parameters) throws ContainerCreateException {
+ return createContainer(getDescriptionByNameWithException(containerTypeDescriptionName), parameters);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.core.IContainerFactory#createContainer(org.eclipse.ecf.core.ContainerTypeDescription, org.eclipse.ecf.core.identity.ID, java.lang.Object[])
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, ID containerID, Object[] parameters) throws ContainerCreateException {
+ if (containerID == null)
+ return createContainer(containerTypeDescription, parameters);
+ Object[] params = (parameters == null || parameters.length == 0) ? new Object[1] : new Object[parameters.length + 1];
+ params[0] = containerID;
+ if (parameters != null && parameters.length != 0)
+ System.arraycopy(parameters, 0, params, 1, parameters.length);
+ return createContainer(containerTypeDescription, params);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.core.IContainerFactory#createContainer(java.lang.String, org.eclipse.ecf.core.identity.ID, java.lang.Object[])
+ */
+ public IContainer createContainer(String containerTypeDescriptionName, ID containerID, Object[] parameters) throws ContainerCreateException {
+ if (containerID == null)
+ return createContainer(containerTypeDescriptionName, parameters);
+ return createContainer(getDescriptionByNameWithException(containerTypeDescriptionName), containerID, parameters);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.core.IContainerFactory#createContainer(org.eclipse.ecf.core.ContainerTypeDescription, org.eclipse.ecf.core.identity.ID)
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, ID containerID) throws ContainerCreateException {
+ if (containerID == null)
+ return createContainer(containerTypeDescription);
+ return createContainer(containerTypeDescription, new Object[] {containerID});
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.core.IContainerFactory#createContainer(java.lang.String, org.eclipse.ecf.core.identity.ID)
+ */
+ public IContainer createContainer(String containerTypeDescriptionName, ID containerID) throws ContainerCreateException {
+ return createContainer(getDescriptionByNameWithException(containerTypeDescriptionName), new Object[] {containerID});
+ }
+
+ /**
+ * @since 3.1
+ */
+ public IContainer createContainer(String containerTypeDescriptionName, String containerId) throws ContainerCreateException {
+ return createContainer(getDescriptionByNameWithException(containerTypeDescriptionName), containerId);
+ }
+
+ /**
+ * @since 3.1
+ */
+ public IContainer createContainer(String containerTypeDescriptionName, String containerId, Object[] parameters) throws ContainerCreateException {
+ return createContainer(getDescriptionByNameWithException(containerTypeDescriptionName), containerId, parameters);
+ }
+
+ /**
+ * @since 3.1
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, String containerId) throws ContainerCreateException {
+ return createContainer(containerTypeDescription, containerId, (Object[]) null);
+ }
+
+ /**
+ * @since 3.1
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, String containerId, Object[] parameters) throws ContainerCreateException {
+ if (containerId == null)
+ return createContainer(containerTypeDescription, parameters);
+ Object[] params = (parameters == null || parameters.length == 0) ? new Object[1] : new Object[parameters.length + 1];
+ params[0] = containerId;
+ if (parameters != null && parameters.length != 0)
+ System.arraycopy(parameters, 0, params, 1, parameters.length);
+ return createContainer(containerTypeDescription, params);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainerManager#getAllContainers()
+ */
+ public IContainer[] getAllContainers() {
+ List containerValues = new ArrayList();
+ synchronized (containers) {
+ Collection containerEntrys = containers.values();
+ for (Iterator i = containerEntrys.iterator(); i.hasNext();) {
+ ContainerEntry entry = (ContainerEntry) i.next();
+ containerValues.add(entry.getContainer());
+ }
+ }
+ return (IContainer[]) containerValues.toArray(new IContainer[] {});
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainerManager#getContainer(org.eclipse.ecf.core.identity.ID)
+ */
+ public IContainer getContainer(ID containerID) {
+ if (containerID == null)
+ return null;
+ synchronized (containers) {
+ ContainerEntry entry = (ContainerEntry) containers.get(containerID);
+ if (entry == null)
+ return null;
+ return entry.getContainer();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainerManager#hasContainer(org.eclipse.ecf.core.identity.ID)
+ */
+ public boolean hasContainer(ID containerID) {
+ Assert.isNotNull(containerID);
+ synchronized (containers) {
+ return containers.containsKey(containerID);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.core.IContainerManager#addListener(org.eclipse.ecf.core.IContainerManagerListener)
+ */
+ public boolean addListener(IContainerManagerListener listener) {
+ Assert.isNotNull(listener);
+ synchronized (managerListeners) {
+ return managerListeners.add(listener);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.core.IContainerManager#removeListener(org.eclipse.ecf.core.IContainerManagerListener)
+ */
+ public boolean removeListener(IContainerManagerListener listener) {
+ Assert.isNotNull(listener);
+ synchronized (managerListeners) {
+ return managerListeners.remove(listener);
+ }
+ }
+
+ public IContainer addContainer(IContainer container, ContainerTypeDescription typeDescription) {
+ Assert.isNotNull(container);
+ Assert.isNotNull(typeDescription);
+ ID containerID = container.getID();
+ Assert.isNotNull(containerID, "Container ID cannot be null"); //$NON-NLS-1$
+ ContainerEntry result = null;
+ synchronized (containers) {
+ result = (ContainerEntry) containers.put(containerID, new ContainerEntry(container, typeDescription));
+ }
+ if (result == null)
+ fireContainerAdded(container);
+ return container;
+ }
+
+ /**
+ * @param result
+ */
+ private void fireContainerAdded(IContainer result) {
+ List toNotify = null;
+ synchronized (managerListeners) {
+ toNotify = new ArrayList(managerListeners);
+ }
+ for (Iterator i = toNotify.iterator(); i.hasNext();) {
+ IContainerManagerListener cml = (IContainerManagerListener) i.next();
+ cml.containerAdded(result);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IContainerManager#removeContainer(org.eclipse.ecf.core.IContainer)
+ */
+ public IContainer removeContainer(IContainer container) {
+ Assert.isNotNull(container);
+ ID containerID = container.getID();
+ if (containerID == null)
+ return null;
+ return removeContainer(containerID);
+ }
+
+ public IContainer removeContainer(ID containerID) {
+ Assert.isNotNull(containerID);
+ ContainerEntry result = null;
+ synchronized (containers) {
+ result = (ContainerEntry) containers.remove(containerID);
+ }
+ IContainer resultContainer = null;
+ if (result != null) {
+ resultContainer = result.getContainer();
+ fireContainerRemoved(resultContainer);
+ }
+ return resultContainer;
+ }
+
+ /**
+ * @param result
+ */
+ private void fireContainerRemoved(IContainer result) {
+ List toNotify = null;
+ synchronized (managerListeners) {
+ toNotify = new ArrayList(managerListeners);
+ }
+ for (Iterator i = toNotify.iterator(); i.hasNext();) {
+ IContainerManagerListener cml = (IContainerManagerListener) i.next();
+ cml.containerRemoved(result);
+ }
+ }
+
+ public ContainerTypeDescription getContainerTypeDescription(ID containerID) {
+ if (containerID == null)
+ return null;
+ synchronized (containers) {
+ ContainerEntry entry = (ContainerEntry) containers.get(containerID);
+ if (entry == null)
+ return null;
+ return entry.getContainerTypeDescription();
+ }
+ }
+
+ public IContainerFactory getContainerFactory() {
+ return this;
+ }
+
+ public void removeAllContainers() {
+ synchronized (containers) {
+ for (Iterator i = containers.keySet().iterator(); i.hasNext();) {
+ ID key = (ID) i.next();
+ ContainerEntry entry = (ContainerEntry) containers.get(key);
+ i.remove();
+ fireContainerRemoved(entry.getContainer());
+ }
+ }
+ }
+
+ /**
+ * @since 3.1
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, ID containerID, Map parameters) throws ContainerCreateException {
+ if (containerID == null)
+ return createContainer(containerTypeDescription, parameters);
+ if (parameters == null)
+ return createContainer(containerTypeDescription, containerID);
+ return createContainer(containerTypeDescription, new Object[] {containerID, parameters});
+ }
+
+ /**
+ * @since 3.1
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, String containerId, Map parameters) throws ContainerCreateException {
+ if (containerId == null)
+ return createContainer(containerTypeDescription, parameters);
+ if (parameters == null)
+ return createContainer(containerTypeDescription, containerId);
+ return createContainer(containerTypeDescription, new Object[] {containerId, parameters});
+ }
+
+ /**
+ * @since 3.1
+ */
+ public IContainer createContainer(String containerTypeDescriptionName, ID containerID, Map parameters) throws ContainerCreateException {
+ return createContainer(getDescriptionByNameWithException(containerTypeDescriptionName), containerID, parameters);
+ }
+
+ /**
+ * @since 3.1
+ */
+ public IContainer createContainer(String containerTypeDescriptionName, String containerId, Map parameters) throws ContainerCreateException {
+ return createContainer(getDescriptionByNameWithException(containerTypeDescriptionName), containerId, parameters);
+ }
+
+ /**
+ * @since 3.1
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, Map parameters) throws ContainerCreateException {
+ if (parameters == null)
+ return createContainer(containerTypeDescription);
+ return createContainer(containerTypeDescription, new Object[] {parameters});
+ }
+
+ /**
+ * @since 3.1
+ */
+ public IContainer createContainer(String containerTypeDescriptionName, Map parameters) throws ContainerCreateException {
+ if (parameters == null)
+ return createContainer(containerTypeDescriptionName);
+ return createContainer(containerTypeDescriptionName, new Object[] {parameters});
+ }
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerTypeDescription.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerTypeDescription.java
new file mode 100644
index 0000000000..fb7d278dd8
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/ContainerTypeDescription.java
@@ -0,0 +1,289 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.ecf.core.provider.IContainerInstantiator;
+import org.eclipse.ecf.core.provider.IRemoteServiceContainerInstantiator;
+import org.eclipse.ecf.core.util.Trace;
+import org.eclipse.ecf.internal.core.ECFDebugOptions;
+import org.eclipse.ecf.internal.core.ECFPlugin;
+
+/**
+ * Description of an {@link IContainer} type. Instances of this class are used to represent {@link IContainerInstantiator}s
+ * in the {@link ContainerFactory}
+ *
+ * @see ContainerFactory IContainerInstantiator
+ */
+public class ContainerTypeDescription {
+
+ protected String name = null;
+
+ protected String instantiatorClass = null;
+
+ protected IContainerInstantiator instantiator = null;
+
+ protected String description = null;
+
+ protected int hashCode = 0;
+
+ protected boolean server;
+
+ protected boolean hidden;
+
+ public ContainerTypeDescription(String name, String instantiatorClass, String description) {
+ this(name, instantiatorClass, description, false, false);
+ }
+
+ public ContainerTypeDescription(String name, String instantiatorClass, String description, boolean server, boolean hidden) {
+ Assert.isNotNull(name, "ContainerTypeDescriptionnull result. In other words, even if the
+ * class name is in the returned array, subsequent calls to
+ * {@link IContainer#getAdapter(Class)} may still return null.
+ *
+ * @return String[] of supported adapters. The entries in the returned array
+ * will be the fully qualified class names of adapters supported by
+ * the given description. An empty string array (String[0]) will be
+ * returned if no adapters are supported.
+ */
+ public String[] getSupportedAdapterTypes() {
+ String[] result = new String[0];
+ try {
+ String[] r = getInstantiator().getSupportedAdapterTypes(this);
+ if (r != null)
+ result = r;
+ } catch (Exception e) {
+ traceAndLogException(IStatus.ERROR, "getSupportedAdapterTypes", e); //$NON-NLS-1$
+ }
+ List resultList = new ArrayList();
+ resultList.addAll(Arrays.asList(result));
+ if (!resultList.contains(IContainer.class.getName()))
+ resultList.add(IContainer.class.getName());
+ return (String[]) resultList.toArray(new String[] {});
+ }
+
+ protected void traceAndLogException(int code, String method, Throwable e) {
+ Trace.catching(ECFPlugin.PLUGIN_ID, ECFDebugOptions.EXCEPTIONS_CATCHING, this.getClass(), method, e);
+ ECFPlugin.getDefault().log(new Status(IStatus.ERROR, ECFPlugin.PLUGIN_ID, code, method, e));
+ }
+
+ /**
+ * Get array of parameter types for this ContainerTypeDescription. Each of
+ * the rows of the returned array specifies a Class[] of parameter types.
+ * These parameter types correspond to the types of Objects that can be
+ * passed into the second parameter of
+ * {@link IContainerInstantiator#createInstance(ContainerTypeDescription, Object[])}.
+ * For example, if this method returns a Class [] = {{ String.class,
+ * String.class }, { String.class }} this indicates that a call to
+ * createInstance(description,new String[] { "hello", "there" }) and a call
+ * to createInstance(description,new String[] { "hello" }) will be
+ * understood by the underlying provider implementation.
+ *
+ * @return Class[][] array of Class arrays. Each row corresponds to a
+ * Class[] that describes the types of Objects for second parameter
+ * to
+ * {@link IContainerInstantiator#createInstance(ContainerTypeDescription, Object[])}.
+ * If no parameter types are understood as arguments, a Class[0][0]
+ * array will be returned
+ */
+ public Class[][] getSupportedParameterTypes() {
+ Class[][] result = {{}};
+ try {
+ Class[][] r = getInstantiator().getSupportedParameterTypes(this);
+ if (r != null)
+ result = r;
+ } catch (Exception e) {
+ traceAndLogException(IStatus.ERROR, "getSupportedParameterTypes", e); //$NON-NLS-1$
+ }
+ return result;
+ }
+
+ /**
+ * @return String[] of container's intents.
+ *
+ * @since 3.0
+ */
+ public String[] getSupportedIntents() {
+ try {
+ IContainerInstantiator ci = getInstantiator();
+ return (ci instanceof IRemoteServiceContainerInstantiator) ? ((IRemoteServiceContainerInstantiator) ci).getSupportedIntents(this) : null;
+ } catch (Exception e) {
+ traceAndLogException(IStatus.ERROR, "getSupportedIntents", e); //$NON-NLS-1$
+ return null;
+ }
+ }
+
+ /**
+ * @return String[] supported configs
+ * @since 3.1
+ */
+ public String[] getSupportedConfigs() {
+ try {
+ IContainerInstantiator ci = getInstantiator();
+ return (ci instanceof IRemoteServiceContainerInstantiator) ? ((IRemoteServiceContainerInstantiator) ci).getSupportedConfigs(this) : null;
+ } catch (Exception e) {
+ traceAndLogException(IStatus.ERROR, "getSupportedConfigs", e); //$NON-NLS-1$
+ return null;
+ }
+ }
+
+ /**
+ * @param exporterSupportedConfigs exporter supported configs
+ * @return String[] imported configs
+ * @since 3.1
+ */
+ public String[] getImportedConfigs(String[] exporterSupportedConfigs) {
+ if (exporterSupportedConfigs == null)
+ return null;
+ try {
+ IContainerInstantiator ci = getInstantiator();
+ return (ci instanceof IRemoteServiceContainerInstantiator) ? ((IRemoteServiceContainerInstantiator) ci).getImportedConfigs(this, exporterSupportedConfigs) : null;
+ } catch (Exception e) {
+ traceAndLogException(IStatus.ERROR, "getImportedConfigs", e); //$NON-NLS-1$
+ return null;
+ }
+ }
+
+ /**
+ * @param importedConfigs imported configs
+ * @param exportedProperties exported properties
+ * @return Dictionary dictionary of properties for imported configs
+ * @since 3.1
+ */
+ public Dictionary getPropertiesForImportedConfigs(String[] importedConfigs, Dictionary exportedProperties) {
+ if (importedConfigs == null)
+ return null;
+ try {
+ IContainerInstantiator ci = getInstantiator();
+ return (ci instanceof IRemoteServiceContainerInstantiator) ? ((IRemoteServiceContainerInstantiator) ci).getPropertiesForImportedConfigs(this, importedConfigs, exportedProperties) : null;
+ } catch (Exception e) {
+ traceAndLogException(IStatus.ERROR, "getPropertiesForImportedConfigs", e); //$NON-NLS-1$
+ return null;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainer.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainer.java
new file mode 100644
index 0000000000..5b5618a465
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainer.java
@@ -0,0 +1,214 @@
+/****************************************************************************
+ * Copyright (c) 2004, 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.ecf.core.identity.*;
+import org.eclipse.ecf.core.security.IConnectContext;
+
+/**
+ * Contract for ECF communications container+ * // Create container instance via factory + * IContainer container = ContainerFactory.getDefault().createContainer( + * "ecf.generic.client"); + * + * // Get presence protocol adapter + * IPresenceContainerAdapter presence = (IPresenceContainerAdapter) container + * .getAdapter(IPresenceContainerAdapter.class); + * // ... setup presence listeners and local input here using presence + * + * // Connect + * container.connect(target, targetConnectContext); + * + * // Engage in appropriate communications here using protocol adapter(s) + * // Manage protocol adapters as needed when finished + * + * // Disconnect + * container.disconnect(); + *+ * + */ +public interface IContainer extends IAdaptable, IIdentifiable { + + /** + * Connect to a target remote process or process group. The target + * identified by the first parameter (targetID) is connected the + * implementation class. If authentication information is required, the + * required information is given via via the second parameter + * (connectContext). + * + * Callers note that depending upon the provider implementation this method + * may block. It is suggested that callers use a separate thread to call + * this method. + * + * This method provides an implementation independent way for container + * implementations to connect, authenticate, and communicate with a remote + * service or group of services. Providers are responsible for implementing + * this operation in a way appropriate to the given remote service (or + * group) via expected protocol. + * + * @param targetID + * the ID of the remote server or group to connect to. See + * {@link #getConnectNamespace()} for a explanation of the + * constraints upon this parameter. + * @param connectContext + * any required context to allow this container to authenticate. + * May be
null if underlying provider does not
+ * have any authentication requirements for connection.
+ * @exception ContainerConnectException
+ * thrown if communication cannot be established with remote
+ * service. Causes can include network connection failure,
+ * authentication failure, server error, or if container is
+ * already connected.
+ */
+ public void connect(ID targetID, IConnectContext connectContext) throws ContainerConnectException;
+
+ /**
+ * Get the target ID that this container instance has connected to. Returns
+ * null if not connected.
+ *
+ * @return ID of the target we are connected to. Returns null
+ * if container not connected.
+ */
+ public ID getConnectedID();
+
+ /**
+ * Get the Namespace for creating a targetID suitable for use as the first
+ * parameter in subsequent calls to {@link #connect(ID, IConnectContext)}.
+ * If this method returns null, then it means that
+ * null is expected as a valid parameter in subsequent calls
+ * to {@link #connect(ID, IConnectContext)}. If this method returns a non-null
+ * Namespace, then the targetID parameter in
+ * {@link #connect(ID, IConnectContext)} must be non-null
+ * instance created of the returned Namespace.
+ *
+ * @return Namespace the namespace associated with subsequent calls to
+ * {@link #connect(ID, IConnectContext)}. If null,
+ * then the targetID instances passed to
+ * {@link #connect(ID, IConnectContext)} may be null.
+ * If not null, then targetID
+ * instances passed to {@link #connect(ID, IConnectContext)} must be
+ * instances of the returned Namespace.
+ */
+ public Namespace getConnectNamespace();
+
+ /**
+ * Disconnect. This operation will disconnect the local container instance
+ * from any previously joined target or group. Subsequent calls to
+ * getConnectedID() will return null.
+ */
+ public void disconnect();
+
+ /**
+ * This specialization of IAdaptable.getAdapter() returns additional
+ * services supported by this container. A container that supports
+ * additional services over and above the methods on IContainer
+ * should return them using this method. It is recommended that clients use
+ * this method rather than instanceof checks and downcasts to find out about
+ * the capabilities of a specific container.
+ * + * Typically, after obtaining an IContainer, a client would use this method + * as a means to obtain a more meaningful interface to the container. This + * interface may or may not extend IContainer. For example, a client could + * use the following code to obtain an instance of ISharedObjectContainer: + *
+ * + *+ * IContainer newContainer = ContainerFactory.createContainer(type); + * ISharedObjectContainer soContainer = (ISharedObjectContainer) newContainer + * .getAdapter(ISharedObjectContainer.class); + * if (soContainer == null) + * throw new ContainerCreateException(message); + *+ * + *
+ * Implementations of this method should delegate to
+ * IAdapterManager.loadAdapter() if the service
+ * cannot be provided directly to ensure extensibility by third-party
+ * plug-ins.
+ *
null if this container does not support the given
+ * service
+ */
+ public | container action | + *Event | + *
| connect start | + *IContainerConnectingEvent | + *
| connect complete | + *IContainerConnectedEvent | + *
| disconnect start | + *IContainerDisconnectingEvent | + *
| disconnect complete | + *IContainerDisconnectedEvent | + *
null.
+ * @return ContainerTypeDescription the old description of the same name,
+ * null if none found
+ */
+ public ContainerTypeDescription addDescription(ContainerTypeDescription containerTypeDescription);
+
+ /**
+ * Get a collection of the ContainerDescriptions currently known to this
+ * factory. This allows clients to query the factory to determine what if
+ * any other ContainerDescriptions are currently registered with the
+ * factory, and if so, what they are.
+ *
+ * @return List of ContainerTypeDescription instances
+ */
+ public List /* ContainerTypeDescription */ getDescriptions();
+
+ /**
+ * Check to see if a given named description is already contained by this
+ * factory
+ *
+ * @param containerTypeDescription
+ * the ContainerTypeDescription to look for
+ * @return true if description is already known to factory, false otherwise
+ */
+ public boolean containsDescription(ContainerTypeDescription containerTypeDescription);
+
+ /**
+ * Get the known ContainerTypeDescription given it's name.
+ *
+ * @param containerTypeDescriptionName
+ * the name to use as key to find ContainerTypeDescription. Must not be null.
+ * @return ContainerTypeDescription found. Null if not found.
+ */
+ public ContainerTypeDescription getDescriptionByName(String containerTypeDescriptionName);
+
+ /**
+ * Remove given description from set known to this factory.
+ *
+ * @param containerTypeDescription
+ * the ContainerTypeDescription to remove
+ * @return the removed ContainerTypeDescription, null if nothing removed
+ */
+ public ContainerTypeDescription removeDescription(ContainerTypeDescription containerTypeDescription);
+
+ /**
+ * Get container type descriptions that support the given containerAdapter
+ *
+ * @param containerAdapter the container adapter. Must not be null.
+ * @return ContainerTypeDescription[] of descriptions that support the given container adapter. If no
+ * ContainerTypeDescriptions found that support the given adapter, an empty array will be returned.
+ */
+ public ContainerTypeDescription[] getDescriptionsForContainerAdapter(Class containerAdapter);
+
+ /**
+ * Make a base IContainer instance.
+ *
+ * @return IContainer instance. A non-null instance will be returned.
+ * @throws ContainerCreateException if some problem creating the instance.
+ */
+ public IContainer createContainer() throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerID the container's new ID. Must not be null.
+ * @return IContainer instance. A non-null. instance will be returned.
+ * @throws ContainerCreateException if some problem creating a base IContainer instance.
+ */
+ public IContainer createContainer(ID containerID) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescription
+ * the ContainerTypeDescription to use. Must not be null.
+ * @return a valid instance of IContainer. Will not be null.
+ * @throws ContainerCreateException if some problem creating the instance.
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescriptionName
+ * the ContainerTypeDescription name to lookup. Must not be null.
+ * @return a valid instance of IContainer. Will not be null.
+ * @throws ContainerCreateException if cannot create container of given name
+ */
+ public IContainer createContainer(String containerTypeDescriptionName) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescription
+ * the ContainerTypeDescription to use to create the instance. Must not be null.
+ * @param parameters
+ * an Object [] of parameters passed to the createInstance method
+ * of the IContainerInstantiator. May be null.
+ * @return a valid instance of IContainer. A non-null instance will be returned.
+ * @throws ContainerCreateException if some problem creating the instance.
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, Object[] parameters) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescriptionName
+ * the ContainerTypeDescription name to lookup. Must not be null.
+ * @param parameters
+ * the Object [] of parameters passed to the
+ * IContainerInstantiator.createInstance method. May be null.
+ * @return a valid instance of IContainer. Will not be null.
+ * @throws ContainerCreateException if some problem creating the instance.
+ */
+ public IContainer createContainer(String containerTypeDescriptionName, Object[] parameters) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescriptionName
+ * the ContainerTypeDescription name to use to create the instance. Must not be null.
+ * @param containerId the container's new ID. May be null.
+ * @return a valid instance of IContainer
+ * @throws ContainerCreateException if some problem creating the instance.
+ * @since 3.1
+ */
+ public IContainer createContainer(String containerTypeDescriptionName, String containerId) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescriptionName
+ * the ContainerTypeDescription name to use to create the instance. Must not be null.
+ * @param containerId the container's new ID. May be null.
+ * @param parameters
+ * an Object [] of parameters passed to the createInstance method
+ * of the IContainerInstantiator. May be null.
+ * @return a valid instance of IContainer
+ * @throws ContainerCreateException if some problem creating the instance.
+ * @since 3.1
+ */
+ public IContainer createContainer(String containerTypeDescriptionName, String containerId, Object[] parameters) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescription
+ * the ContainerTypeDescription to use to create the instance. Must not be null.
+ * @param containerId the container's new ID. May be null.
+ * @return a valid instance of IContainer
+ * @throws ContainerCreateException if some problem creating the instance.
+ * @since 3.1
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, String containerId) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescription
+ * the ContainerTypeDescription to use to create the instance. Must not be null.
+ * @param containerId the container's new ID. May be null.
+ * @param parameters
+ * an Object [] of parameters passed to the createInstance method
+ * of the IContainerInstantiator. May be null.
+ * @return a valid instance of IContainer
+ * @throws ContainerCreateException if some problem creating the instance.
+ * @since 3.1
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, String containerId, Object[] parameters) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescription
+ * the ContainerTypeDescription to use to create the instance. Must not be null.
+ * @param containerID the container's new ID. May be null.
+ * @param parameters
+ * an Object [] of parameters passed to the createInstance method
+ * of the IContainerInstantiator. May be null.
+ * @return a valid instance of IContainer
+ * @throws ContainerCreateException if some problem creating the instance.
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, ID containerID, Object[] parameters) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescriptionName
+ * the ContainerTypeDescription name to lookup. Must not be null.
+ * @param containerID the new container's id. May be null.
+ * @param parameters
+ * the Object [] of parameters passed to the
+ * IContainerInstantiator.createInstance method. May be null.
+ * @return a valid instance of IContainer. Will not be null.
+ * @throws ContainerCreateException if some problem creating the instance.
+ */
+ public IContainer createContainer(String containerTypeDescriptionName, ID containerID, Object[] parameters) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescription
+ * the ContainerTypeDescription to lookup. Must not be null.
+ * @param containerID the new container's id. May be null.
+ * @return a valid instance of IContainer. Will not be null.
+ * @throws ContainerCreateException if some problem creating the instance.
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, ID containerID) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescriptionName
+ * the ContainerTypeDescription name to lookup. Must not be null.
+ * @param containerID the new container's id. May be null.
+ * @return a valid instance of IContainer. Will not be null.
+ * @throws ContainerCreateException if some problem creating the instance.
+ */
+ public IContainer createContainer(String containerTypeDescriptionName, ID containerID) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescription
+ * the ContainerTypeDescription to use to create the instance. Must not be null.
+ * @param containerID the container's new ID. Must not be null.
+ * @param parameters
+ * a Map of parameters (name/value pairs) passed to the createInstance method
+ * of the IContainerInstantiator. May be null.
+ * @return a valid instance of IContainer
+ * @throws ContainerCreateException if some problem creating the instance.
+ * @since 3.1
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, ID containerID, Map parameters) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescription
+ * the ContainerTypeDescription to use to create the instance. Must not be null.
+ * @param containerId the container's new ID. May be null.
+ * @param parameters
+ * a Map of parameters (name/value pairs) passed to the createInstance method
+ * of the IContainerInstantiator. May be null.
+ * @return a valid instance of IContainer
+ * @throws ContainerCreateException if some problem creating the instance.
+ * @since 3.1
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, String containerId, Map parameters) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescriptionName
+ * the ContainerTypeDescription name to lookup. Must not be null.
+ * @param containerID the container's new ID. May be null.
+ * @param parameters
+ * a Map of parameters (name/value pairs) passed to the createInstance method
+ * of the IContainerInstantiator. May be null.
+ * @return a valid instance of IContainer
+ * @throws ContainerCreateException if some problem creating the instance.
+ * @since 3.1
+ */
+ public IContainer createContainer(String containerTypeDescriptionName, ID containerID, Map parameters) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescriptionName
+ * the ContainerTypeDescription name to lookup. Must not be null.
+ * @param containerId the container's new ID. May be null.
+ * @param parameters
+ * a Map of parameters (name/value pairs) passed to the createInstance method
+ * of the IContainerInstantiator. May be null.
+ * @return a valid instance of IContainer
+ * @throws ContainerCreateException if some problem creating the instance.
+ * @since 3.1
+ */
+ public IContainer createContainer(String containerTypeDescriptionName, String containerId, Map parameters) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescription
+ * the ContainerTypeDescription to use to create the instance. Must not be null.
+ * @param parameters
+ * a Map of parameters (name/value pairs) passed to the createInstance method
+ * of the IContainerInstantiator. May be null.
+ * @return a valid instance of IContainer
+ * @throws ContainerCreateException if some problem creating the instance.
+ * @since 3.1
+ */
+ public IContainer createContainer(ContainerTypeDescription containerTypeDescription, Map parameters) throws ContainerCreateException;
+
+ /**
+ * Create a new container.
+ *
+ * @param containerTypeDescriptionName
+ * the ContainerTypeDescription name to lookup. Must not be null.
+ * @param parameters
+ * a Map of parameters (name/value pairs) passed to the createInstance method
+ * of the IContainerInstantiator. May be null.
+ * @return a valid instance of IContainer
+ * @throws ContainerCreateException if some problem creating the instance.
+ * @since 3.1
+ */
+ public IContainer createContainer(String containerTypeDescriptionName, Map parameters) throws ContainerCreateException;
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainerListener.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainerListener.java
new file mode 100644
index 0000000000..40b179afb4
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainerListener.java
@@ -0,0 +1,49 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core;
+
+import org.eclipse.ecf.core.events.IContainerEvent;
+
+/**
+ * Listener for objects that wish to receive events from an IContainer
+ * instances.
+ *
+ * @see IContainer#addListener(IContainerListener)
+ * + * Note these methods will be called asynchronously when notifications of remote + * changes are received by the provider implementation code. The provider is + * free to call the methods below with an arbitrary thread, so the + * implementation of these methods must be appropriately prepared. + *
+ * For example, if the code implementing any of these methods must interact with + * user interface code, then it should use code such as the following to execute + * on the SWT UI thread: + * + *
+ * Display.getDefault().asyncExec(new Runnable() {
+ * public void run() {
+ * ... UI code here
+ * }
+ * });
+ *
+ *
+ * Further, the code in the implementations of these methods should not block via
+ * I/O operations or blocking UI calls.
+ */
+public interface IContainerListener {
+ /**
+ * Handle event from IContainer
+ *
+ * @param event the event to handle
+ */
+ public void handleEvent(IContainerEvent event);
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainerManager.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainerManager.java
new file mode 100644
index 0000000000..a8cd2f170b
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainerManager.java
@@ -0,0 +1,131 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.core;
+
+import org.eclipse.ecf.core.identity.ID;
+
+/**
+ * Container manager for getting access to existing container instances
+ * previously created via {@link IContainerFactory}.
+ */
+public interface IContainerManager {
+
+ /**
+ * Get container factory associated with this container manager.
+ * @return IContainerFactory. Will not return null.
+ *
+ * @since 3.0
+ */
+ public IContainerFactory getContainerFactory();
+
+ /**
+ * Get container for given ID. If containerID is
+ * null then null will be returned. If
+ * active container with given containerID, is not known to this container manager,
+ * then null will also be returned.
+ * @param containerID the ID of the container instance to retrieve from this manager. If null
+ * null will be returned.
+ * @return IContainer instance with given containerID. Will be null if there
+ * is no container with given ID known to this container manager.
+ */
+ public IContainer getContainer(ID containerID);
+
+ /**
+ * Get the container type description used to create the container with the given ID.
+ *
+ * @param containerID the ID of the container to get the description for.
+ * @return ContainerTypeDescription for the container with the given ID. Will return null
+ * if no container with the given containerID exists under this manager.
+ */
+ public ContainerTypeDescription getContainerTypeDescription(ID containerID);
+
+ /**
+ * Get all containers known to this container manager.
+ *
+ * @return IContainer[] of active container instances known to this
+ * container manager. Will not return null, but may
+ * return empty IContainer[].
+ */
+ public IContainer[] getAllContainers();
+
+ /**
+ * Return true if this container manager has the given container under
+ * management, false otherwise.
+ *
+ * @param containerID
+ * the ID of the container to find. If null this
+ * method returns false.
+ *
+ * @return true if this container manager has the given container under
+ * management, false otherwise.
+ */
+ public boolean hasContainer(ID containerID);
+
+ /**
+ * Add given container to manager.
+ *
+ * @param container
+ * to add. Must not be null. Also
+ * container.getID() must return a non-null
+ * value. If container.getID() returns
+ * null then this method will throw a
+ * {@link NullPointerException}.
+ * @param typeDescription the container type description used to create the given container. Must not be null.
+ * @return IContainer previously added (with same ID).
+ */
+ public IContainer addContainer(IContainer container, ContainerTypeDescription typeDescription);
+
+ /**
+ * Remove given container from manager.
+ * @param container the container to remove. Must not be null.
+ *
+ * @return IContainer instance removed. If no instance with same ID is found
+ * then null will be returned.
+ */
+ public IContainer removeContainer(IContainer container);
+
+ /**
+ * Remove given container from manager.
+ * @param containerID the ID of the container to remove. Must not be null.
+ *
+ * @return IContainer instance removed. If no instance with same ID is found
+ * then null will be returned.
+ *
+ * @since 3.0
+ */
+ public IContainer removeContainer(ID containerID);
+
+ /**
+ * Add listener to this {@link IContainerManager}.
+ *
+ * @param listener the listener to add. Must not be null.
+ * @return true if listener successfully added
+ */
+ public boolean addListener(IContainerManagerListener listener);
+
+ /**
+ * Remove listener from this {@link IContainerManager}.
+ *
+ * @param listener the listener to remove. Must not be null.
+ * @return true if listener successfully removed
+ */
+ public boolean removeListener(IContainerManagerListener listener);
+
+ /**
+ * Remove all containers from this manager
+ *
+ * @since 3.0
+ */
+ public void removeAllContainers();
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainerManagerListener.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainerManagerListener.java
new file mode 100644
index 0000000000..5cfa6f0e18
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IContainerManagerListener.java
@@ -0,0 +1,42 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.core;
+
+/**
+ * Container manager listener. Instances of this interface may be registered via
+ * calls to {@link IContainerManager#addListener(IContainerManagerListener)}.
+ * When subsequent additions to the {@link IContainerManager} occur, the
+ * {@link #containerAdded(IContainer)} method will be called. When container
+ * removals occur, {@link #containerRemoved(IContainer)}. Note that these
+ * methods will be called by arbitrary threads.
+ *
+ */
+public interface IContainerManagerListener {
+
+ /**
+ * Container added to the implementing IContainerManager.
+ *
+ * @param container
+ * the {@link IContainer} added. Will not be null.
+ */
+ public void containerAdded(IContainer container);
+
+ /**
+ * Container removed from the implementing IContainerManager.
+ *
+ * @param container
+ * the {@link IContainer} removed. Will not be null.
+ */
+ public void containerRemoved(IContainer container);
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IReliableContainer.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IReliableContainer.java
new file mode 100644
index 0000000000..4ca8b66d2c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/IReliableContainer.java
@@ -0,0 +1,35 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core;
+
+import org.eclipse.ecf.core.identity.ID;
+
+/**
+ * Contract for reliable container. Extends IContainer
+ *
+ * @see IContainer
+ */
+public interface IReliableContainer extends IContainer {
+ /**
+ * Get the current membership of the joined group. This method will
+ * accurately report the current group membership of the connected group.
+ *
+ * @return ID[] the IDs of the current group membership
+ */
+ public ID[] getGroupMemberIDs();
+
+ /**
+ * @return true if this IReliableContainer instance is in the 'manager' role
+ * for the group, false otherwise.
+ */
+ public boolean isGroupManager();
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerConnectedEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerConnectedEvent.java
new file mode 100644
index 0000000000..2c6db38e8f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerConnectedEvent.java
@@ -0,0 +1,55 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.events;
+
+import org.eclipse.ecf.core.identity.ID;
+
+/**
+ * Container connected event
+ *
+ */
+public class ContainerConnectedEvent implements IContainerConnectedEvent {
+ private final ID joinedContainerID;
+
+ private final ID localContainerID;
+
+ public ContainerConnectedEvent(ID localContainerID, ID targetID) {
+ super();
+ this.localContainerID = localContainerID;
+ this.joinedContainerID = targetID;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.events.IContainerConnectedEvent#getTargetID()
+ */
+ public ID getTargetID() {
+ return joinedContainerID;
+ }
+
+ public ID getLocalContainerID() {
+ return localContainerID;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer("ContainerConnectedEvent["); //$NON-NLS-1$
+ buf.append(getLocalContainerID()).append("]"); //$NON-NLS-1$
+ buf.append(getTargetID()).append(";"); //$NON-NLS-1$
+ return buf.toString();
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerConnectingEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerConnectingEvent.java
new file mode 100644
index 0000000000..3bb0e29427
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerConnectingEvent.java
@@ -0,0 +1,62 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.events;
+
+import org.eclipse.ecf.core.identity.ID;
+
+public class ContainerConnectingEvent implements IContainerConnectingEvent {
+ ID localContainerID;
+
+ ID targetID;
+
+ Object data;
+
+ public ContainerConnectingEvent(ID localContainerID, ID targetID, Object data) {
+ this.localContainerID = localContainerID;
+ this.targetID = targetID;
+ this.data = data;
+ }
+
+ public ContainerConnectingEvent(ID localContainerID, ID targetID) {
+ this(localContainerID, targetID, null);
+ }
+
+ public ID getTargetID() {
+ return targetID;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.events.IContainerConnectingEvent#getData()
+ */
+ public Object getData() {
+ return data;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.events.IContainerEvent#getLocalContainerID()
+ */
+ public ID getLocalContainerID() {
+ return localContainerID;
+ }
+
+ public String toString() {
+ StringBuffer buf = new StringBuffer("ContainerConnectingEvent["); //$NON-NLS-1$
+ buf.append(getLocalContainerID()).append(";"); //$NON-NLS-1$
+ buf.append(getTargetID()).append(";"); //$NON-NLS-1$
+ buf.append(getData()).append("]"); //$NON-NLS-1$
+ return buf.toString();
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerDisconnectedEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerDisconnectedEvent.java
new file mode 100644
index 0000000000..8b96f157f9
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerDisconnectedEvent.java
@@ -0,0 +1,68 @@
+/****************************************************************************
+ * Copyright (c) 2004, 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.events;
+
+import org.eclipse.ecf.core.identity.ID;
+
+/**
+ * Container disconnected event.
+ */
+public class ContainerDisconnectedEvent implements IContainerDisconnectedEvent {
+ private final ID departedContainerID;
+
+ private final ID localContainerID;
+
+ /**
+ * Creates a new ContainerDisconnectedEvent to indicate that the container
+ * has now completely disconnected from its target host.
+ *
+ * @param localContainerID
+ * the ID of the local container
+ * @param targetID
+ * the ID of the target
+ */
+ public ContainerDisconnectedEvent(ID localContainerID, ID targetID) {
+ this.localContainerID = localContainerID;
+ this.departedContainerID = targetID;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.events.IContainerDisconnectedEvent#getTargetID()
+ */
+ public ID getTargetID() {
+ return departedContainerID;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.events.IContainerEvent#getLocalContainerID()
+ */
+ public ID getLocalContainerID() {
+ return localContainerID;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer("ContainerDisconnectedEvent["); //$NON-NLS-1$
+ buf.append(getLocalContainerID()).append(";").append("]"); //$NON-NLS-1$ //$NON-NLS-2$
+ buf.append(getTargetID()).append(";"); //$NON-NLS-1$
+ return buf.toString();
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerDisconnectingEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerDisconnectingEvent.java
new file mode 100644
index 0000000000..7211c71ac8
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerDisconnectingEvent.java
@@ -0,0 +1,55 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.events;
+
+import org.eclipse.ecf.core.identity.ID;
+
+public class ContainerDisconnectingEvent implements IContainerDisconnectingEvent {
+ ID localContainerID;
+
+ ID groupID;
+
+ public ContainerDisconnectingEvent(ID localContainerID, ID targetID) {
+ this.localContainerID = localContainerID;
+ this.groupID = targetID;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.events.IContainerEvent#getLocalContainerID()
+ */
+ public ID getLocalContainerID() {
+ return localContainerID;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.events.IContainerDisconnectingEvent#getTargetID()
+ */
+ public ID getTargetID() {
+ return groupID;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer("ContainerDisconnectingEvent["); //$NON-NLS-1$
+ buf.append(getLocalContainerID()).append(";"); //$NON-NLS-1$
+ buf.append(getTargetID()).append("]"); //$NON-NLS-1$
+ return buf.toString();
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerDisposeEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerDisposeEvent.java
new file mode 100644
index 0000000000..f968e9fe09
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerDisposeEvent.java
@@ -0,0 +1,43 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.events;
+
+import org.eclipse.ecf.core.identity.ID;
+
+public class ContainerDisposeEvent implements IContainerDisposeEvent {
+ private final ID localContainerID;
+
+ public ContainerDisposeEvent(ID localContainerID) {
+ super();
+ this.localContainerID = localContainerID;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.events.IContainerEvent#getLocalContainerID()
+ */
+ public ID getLocalContainerID() {
+ return localContainerID;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer("ContainerDisposeEvent["); //$NON-NLS-1$
+ buf.append(getLocalContainerID()).append("]"); //$NON-NLS-1$
+ return buf.toString();
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerEjectedEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerEjectedEvent.java
new file mode 100644
index 0000000000..49c8b54ac6
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/ContainerEjectedEvent.java
@@ -0,0 +1,55 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.events;
+
+import java.io.Serializable;
+import org.eclipse.ecf.core.identity.ID;
+
+public class ContainerEjectedEvent implements IContainerEjectedEvent {
+ private final ID localContainerID;
+
+ private final ID groupID;
+
+ private final Serializable reason;
+
+ public ContainerEjectedEvent(ID localContainerID, ID targetID, Serializable reason) {
+ super();
+ this.localContainerID = localContainerID;
+ this.groupID = targetID;
+ this.reason = reason;
+ }
+
+ public ID getTargetID() {
+ return groupID;
+ }
+
+ public ID getLocalContainerID() {
+ return localContainerID;
+ }
+
+ public Serializable getReason() {
+ return reason;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer("ContainerEjectedEvent["); //$NON-NLS-1$
+ buf.append(getLocalContainerID()).append(";"); //$NON-NLS-1$
+ buf.append(getTargetID()).append(";"); //$NON-NLS-1$
+ buf.append(getReason()).append("]"); //$NON-NLS-1$
+ return buf.toString();
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerConnectedEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerConnectedEvent.java
new file mode 100644
index 0000000000..766ee7a7f8
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerConnectedEvent.java
@@ -0,0 +1,27 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.events;
+
+import org.eclipse.ecf.core.identity.ID;
+
+/**
+ * Container connected event interface
+ *
+ */
+public interface IContainerConnectedEvent extends IContainerEvent {
+ /**
+ * Get ID of container target (the container we are now connected to)
+ *
+ * @return ID the ID of the container we connected to. Will not be null.
+ */
+ public ID getTargetID();
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerConnectingEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerConnectingEvent.java
new file mode 100644
index 0000000000..ee5f840989
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerConnectingEvent.java
@@ -0,0 +1,34 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.events;
+
+import org.eclipse.ecf.core.identity.ID;
+
+/**
+ * Container connecting event
+ *
+ */
+public interface IContainerConnectingEvent extends IContainerEvent {
+ /**
+ * Get ID of container target (the container we are connecting to)
+ *
+ * @return ID the ID of the container we connecting to. Will not be null.
+ */
+ public ID getTargetID();
+
+ /**
+ * Get data associated with connecting
+ *
+ * @return Object the object data for connect. May be null
+ */
+ public Object getData();
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerDisconnectedEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerDisconnectedEvent.java
new file mode 100644
index 0000000000..f78bd017e1
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerDisconnectedEvent.java
@@ -0,0 +1,28 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.events;
+
+import org.eclipse.ecf.core.identity.ID;
+
+/**
+ * Container disconnected event
+ *
+ */
+public interface IContainerDisconnectedEvent extends IContainerEvent {
+ /**
+ * Get ID of container target (the container we were disconnected from)
+ *
+ * @return ID the ID of the container were disconnected from. Will not be
+ * null.
+ */
+ public ID getTargetID();
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerDisconnectingEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerDisconnectingEvent.java
new file mode 100644
index 0000000000..d5a4a2a09c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerDisconnectingEvent.java
@@ -0,0 +1,28 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.events;
+
+import org.eclipse.ecf.core.identity.ID;
+
+/**
+ * Container disconnecting event
+ *
+ */
+public interface IContainerDisconnectingEvent extends IContainerEvent {
+ /**
+ * Get ID of container target (the container we are disconnecting from)
+ *
+ * @return ID the ID of the container we are disconnecting from. Will not be
+ * null.
+ */
+ public ID getTargetID();
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerDisposeEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerDisposeEvent.java
new file mode 100644
index 0000000000..0d72aa38fc
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerDisposeEvent.java
@@ -0,0 +1,20 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.events;
+
+/**
+ * Event sent to listeners when a container is disposed
+ *
+ */
+public interface IContainerDisposeEvent extends IContainerEvent {
+ // No methods
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerEjectedEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerEjectedEvent.java
new file mode 100644
index 0000000000..3789f2251b
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerEjectedEvent.java
@@ -0,0 +1,37 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.events;
+
+import java.io.Serializable;
+import org.eclipse.ecf.core.identity.ID;
+
+/**
+ * Container ejected event. This event is received when a local container has
+ * been ejected from a remote group
+ *
+ */
+public interface IContainerEjectedEvent extends IContainerEvent {
+ /**
+ * Get ID of container target (the container we were ejected from)
+ *
+ * @return ID the ID of the container we were ejected from. Will not be
+ * null.
+ */
+ public ID getTargetID();
+
+ /**
+ * Get reason for ejection
+ *
+ * @return Serializable reason for ejection. May be null.
+ */
+ public Serializable getReason();
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerEvent.java
new file mode 100644
index 0000000000..e0e8048f54
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/events/IContainerEvent.java
@@ -0,0 +1,28 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.events;
+
+import org.eclipse.ecf.core.identity.ID;
+import org.eclipse.ecf.core.util.Event;
+
+/**
+ * An event received by a container
+ *
+ */
+public interface IContainerEvent extends Event {
+ /**
+ * Get ID of local discovery container (the discovery container receiving this event).
+ *
+ * @return ID for local container. Will not return null.
+ */
+ public ID getLocalContainerID();
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/BaseID.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/BaseID.java
new file mode 100644
index 0000000000..c7b5ce56f4
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/BaseID.java
@@ -0,0 +1,164 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.identity;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IAdapterManager;
+import org.eclipse.ecf.internal.core.identity.Activator;
+
+/**
+ * Base class for ID implementation classes
+ *
+ * Extensions for the org.eclipse.ecf.namespace extension point that
+ * expose new Namespace subclasses and their own ID implementations are
+ * recommended (but not required) to use this class as a superclass.
+ *
+ */
+public abstract class BaseID implements ID {
+
+ private static final long serialVersionUID = -6242599410460002514L;
+
+ protected Namespace namespace;
+
+ /**
+ * @since 3.9
+ */
+ public BaseID() {
+ //
+ }
+
+ protected BaseID(Namespace namespace) {
+ Assert.isNotNull(namespace, "namespace cannot be null"); //$NON-NLS-1$
+ this.namespace = namespace;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Comparable#compareTo(T)
+ */
+ public int compareTo(Object o) {
+ Assert.isTrue(o != null && o instanceof BaseID, "incompatible types for compare"); //$NON-NLS-1$
+ return namespace.getCompareToForObject(this, (BaseID) o);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || !(o instanceof BaseID)) {
+ return false;
+ }
+ return namespace.testIDEquals(this, (BaseID) o);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.identity.ID#getName()
+ */
+ public String getName() {
+ return namespace.getNameForID(this);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.identity.ID#getNamespace()
+ */
+ public Namespace getNamespace() {
+ return namespace;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return namespace.getHashCodeForID(this);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.identity.ID#toExternalForm()
+ */
+ public String toExternalForm() {
+ return namespace.toExternalForm(this);
+ }
+
+ /**
+ * Called by {@link Namespace#getCompareToForObject(BaseID, BaseID)}.
+ *
+ * @param o
+ * the other ID to compare to. Will not be null.
+ * @return the appropriate value as per {@link Comparable} contract.
+ */
+ protected abstract int namespaceCompareTo(BaseID o);
+
+ /**
+ * Called by {@link Namespace#testIDEquals(BaseID, BaseID)}.
+ *
+ * @param o
+ * the other ID to test against. May be null.
+ * @return true if this ID is equal to the given ID.
+ * false otherwise.
+ */
+ protected abstract boolean namespaceEquals(BaseID o);
+
+ /**
+ * Called by {@link Namespace#getNameForID(BaseID)}.
+ *
+ * @return String name for this ID. Must not be null. Value
+ * returned should be unique within this Namespace.
+ */
+ protected abstract String namespaceGetName();
+
+ /**
+ * Called by {@link Namespace#getHashCodeForID(BaseID)}.
+ *
+ * @return int hashCode for this ID. Returned value must be unique within this
+ * process.
+ */
+ protected abstract int namespaceHashCode();
+
+ /**
+ * Called by {@link Namespace#toExternalForm(BaseID)}.
+ *
+ * @return String that represents this ID. Default implementation is to return
+ *
+ * + * namespace.getScheme() + Namespace.SCHEME_SEPARATOR + namespaceGetName(); + *+ */ + protected String namespaceToExternalForm() { + return namespace.getScheme() + Namespace.SCHEME_SEPARATOR + namespaceGetName(); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) + */ + @SuppressWarnings("unchecked") + public Object getAdapter(@SuppressWarnings("rawtypes") Class clazz) { + IAdapterManager adapterManager = Activator.getDefault().getAdapterManager(); + if (adapterManager == null) + return null; + return adapterManager.getAdapter(this, clazz.getName()); + } +} \ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/GUID.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/GUID.java new file mode 100644 index 0000000000..ea91de6065 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/GUID.java @@ -0,0 +1,164 @@ +/**************************************************************************** + * Copyright (c) 2004 Composent, Inc. and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * Contributors: Composent, Inc. - initial API and implementation + * + * SPDX-License-Identifier: EPL-2.0 + *****************************************************************************/ +package org.eclipse.ecf.core.identity; + +import java.security.SecureRandom; +import org.eclipse.ecf.core.util.Base64; + +/** + * Globally unique ID implementation class. Uses + * {@link java.security.SecureRandom} to create a unique number of given byte + * length. Default byte length for secure number is 20 bytes. Default algorithm + * used for creating a SecureRandom instance is SHA1PRNG. + */ +public class GUID extends StringID { + private static final long serialVersionUID = 3545794369039972407L; + + public static class GUIDNamespace extends Namespace { + private static final long serialVersionUID = -8546568877571886386L; + + public GUIDNamespace() { + super(GUID.class.getName(), "GUID Namespace. Default based upon 20-byte SecureRandom in Base64 format"); //$NON-NLS-1$ + } + + public ID createInstance(Object[] args) throws IDCreateException { + try { + String init = getInitStringFromExternalForm(args); + if (init != null) + return new GUID(this, init); + if (args == null || args.length <= 0) + return new GUID(this); + else if (args.length == 1 && args[0] instanceof Integer) + return new GUID(this, ((Integer) args[0]).intValue()); + else if (args.length == 1 && args[0] instanceof String) + return new GUID(this, ((String) args[0])); + else + return new GUID(this); + } catch (Exception e) { + throw new IDCreateException(getName() + " createInstance()", e); //$NON-NLS-1$ + } + } + + public String getScheme() { + return GUID.class.getName(); + } + + /* + * (non-Javadoc) + * + * @seeorg.eclipse.ecf.core.identity.Namespace# + * getSupportedParameterTypesForCreateInstance() + */ + public Class>[][] getSupportedParameterTypes() { + return new Class[][] { {}, { Integer.class }, { String.class } }; + } + + } + + public static final String SR_DEFAULT_ALGO = null; + + public static final String SR_DEFAULT_PROVIDER = null; + + public static final int DEFAULT_BYTE_LENGTH = 20; + + // Class specific SecureRandom instance + protected static transient SecureRandom random; + + /** + * @since 3.9 + */ + public GUID() { + + } + + /** + * Protected constructor for factory-based construction + * + * @param n + * the Namespace this identity will belong to + * @param provider + * the name of the algorithm to use. See {@link SecureRandom} + * @param byteLength + * the length of the target number (in bytes) + */ + protected GUID(Namespace n, String algo, String provider, int byteLength) throws IDCreateException { + super(n, ""); //$NON-NLS-1$ + // Get SecureRandom instance for class + try { + getRandom(algo, provider); + } catch (Exception e) { + throw new IDCreateException("GUID creation failure: " + e.getMessage()); //$NON-NLS-1$ + } + // make sure we have reasonable byteLength + if (byteLength <= 0) + byteLength = 1; + byte[] newBytes = new byte[byteLength]; + // Fill up random bytes + random.nextBytes(newBytes); + // Set value + value = Base64.encode(newBytes); + } + + protected GUID(Namespace n, String value) { + super(n, value); + } + + protected GUID(Namespace n, int byteLength) throws IDCreateException { + this(n, SR_DEFAULT_ALGO, SR_DEFAULT_PROVIDER, byteLength); + } + + protected GUID(Namespace n) throws IDCreateException { + this(n, DEFAULT_BYTE_LENGTH); + } + + /** + * Get SecureRandom instance for creation of random number. + * + * @param algo + * the String algorithm specification (e.g. "SHA1PRNG") for creation + * of the SecureRandom instance + * @param provider + * the provider of the implementation of the given algorighm (e.g. + * "SUN") + * @return SecureRandom + * @exception Exception + * thrown if SecureRandom instance cannot be created/accessed + */ + protected static synchronized SecureRandom getRandom(String algo, String provider) throws Exception { + // Given algo and provider, get SecureRandom instance + if (random == null) { + initializeRandom(algo, provider); + } + return random; + } + + protected static synchronized void initializeRandom(String algo, String provider) throws Exception { + if (provider == null) { + if (algo == null) { + try { + random = SecureRandom.getInstance("IBMSECURERANDOM"); //$NON-NLS-1$ + } catch (Exception e) { + random = SecureRandom.getInstance("SHA1PRNG"); //$NON-NLS-1$ + } + } else + random = SecureRandom.getInstance(algo); + } else { + random = SecureRandom.getInstance(algo, provider); + } + } + + public String toString() { + StringBuilder sb = new StringBuilder("GUID["); //$NON-NLS-1$ + sb.append(value).append("]"); //$NON-NLS-1$ + return sb.toString(); + } +} \ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/ID.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/ID.java new file mode 100644 index 0000000000..d23fcba4e5 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/ID.java @@ -0,0 +1,66 @@ +/**************************************************************************** + * Copyright (c) 2004 Composent, Inc. and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * Contributors: Composent, Inc. - initial API and implementation + * + * SPDX-License-Identifier: EPL-2.0 + *****************************************************************************/ +package org.eclipse.ecf.core.identity; + +import org.eclipse.core.runtime.IAdaptable; + +/** + * Contract for ECF identity + *
+ * ECF IDs are immutable once constructed, and unique within the containing + * {@link Namespace}. + *
+ * ID instances are created via the Namespace.createInstance(...) method. This + * method is called by the IDFactory.createID(...) methods for the given + * Namespace. So, for example, to create an ID instance with the name "slewis": + * + *
+ * ID id = IDFactory.getDefault().createID(namespace, "slewis"); + *+ * + *
+ *
+ * @see Namespace
+ *
+ */
+@SuppressWarnings("rawtypes")
+public interface ID extends java.io.Serializable, java.lang.Comparable,
+ java.security.Principal, IAdaptable {
+
+ public boolean equals(Object obj);
+
+ public int hashCode();
+
+ /**
+ * Get the unique name of this identity.
+ *
+ * @return String unique name for this identity. Will not be null, and must
+ * be a unique String within the Namespace returned by
+ * getNamespace()
+ */
+ public String getName();
+
+ /**
+ * Get the Namespace instance associated with this identity
+ *
+ * @return Namespace the Namespace corresponding to this identity. Will not
+ * return null.
+ */
+ public Namespace getNamespace();
+
+ /**
+ * Get this ID instance in String form. Will not return null.
+ *
+ * @return String that is external representation of this ID
+ */
+ public String toExternalForm();
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/IDCreateException.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/IDCreateException.java
new file mode 100644
index 0000000000..60979f6386
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/IDCreateException.java
@@ -0,0 +1,39 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.identity;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.ecf.core.util.ECFRuntimeException;
+
+public class IDCreateException extends ECFRuntimeException {
+ private static final long serialVersionUID = 3258416140119323960L;
+
+ public IDCreateException() {
+ super();
+ }
+
+ public IDCreateException(IStatus status) {
+ super(status);
+ }
+
+ public IDCreateException(String message) {
+ super(message);
+ }
+
+ public IDCreateException(Throwable cause) {
+ super(cause);
+ }
+
+ public IDCreateException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/IDFactory.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/IDFactory.java
new file mode 100644
index 0000000000..d4eb482c33
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/IDFactory.java
@@ -0,0 +1,306 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.identity;
+
+import java.net.URI;
+import java.util.*;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ecf.internal.core.identity.Activator;
+
+/**
+ * A factory class for creating ID instances. This is the factory for plugins to
+ * manufacture ID instances.
+ *
+ */
+public class IDFactory implements IIDFactory {
+ public static final String SECURITY_PROPERTY = IDFactory.class.getName() + ".security"; //$NON-NLS-1$
+
+ private static Hashtable
+ * This class and subclasses define a namespace for the creation and management
+ * of ID instances. Creation of ID instances is accomplished via the
+ * {@link #createInstance(Object[])} method, implemented by subclasses of this
+ * Namespace superclass.
+ *
+ * All Namespace instances must have a unique name passed to the Namespace upon
+ * construction.
+ *
+ * Typically Namespace instances are created via plugins that define extensions
+ * of the org.eclipse.ecf.namespace extension point. For example, to define a
+ * new Namespace subclass XMPPNamespace with name "ecf.xmpp" and add it to the
+ * ECF extension registry:
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * ContainerFactory.getDefault().createContainer("foocontainer",new
+ * Object { "hello" });
+ *
+ * @param description
+ * the ContainerTypeDescription associated with the registered
+ * container provider implementation
+ * @param parameters
+ * parameters specified by the caller. May be null if no
+ * parameters are passed in by caller to
+ * ContainerFactory.getDefault().createContainer(...)
+ * @return IContainer instance. The provider implementation must return a
+ * valid object implementing IContainer OR throw a
+ * ContainerCreateException. Null will not be returned.
+ * @throws ContainerCreateException thrown if instance cannot be created
+ */
+ public IContainer createInstance(ContainerTypeDescription description, Object[] parameters) throws ContainerCreateException;
+
+ /**
+ * Get array of supported adapters for the given container type description.
+ * Providers implement this method to allow clients to inspect the adapter
+ * types exposed by the container described by the given description.
+ *
+ * The returned array entries will be the fully qualified names of the
+ * adapter classes.
+ *
+ * Note that the returned types do not guarantee that a subsequent call to
+ * {@link IContainer#getAdapter(Class)} with the same type name as a
+ * returned value will return a non-
+ * Each of the rows of the returned array specifies a Class[] of parameter
+ * types. These parameter types correspond to the types of Object[] that can
+ * be passed into the second parameter of
+ * {@link #createInstance(ContainerTypeDescription, Object[])}.
+ *
+ * Consider the following example:
+ *
+ * @param description
+ * the ContainerTypeDescription to return parameter types for
+ * @return Class[][] array of Class[]s. Each row in the table corresponds to
+ * a Class[] that describes the types of Objects in Object[] for
+ * second parameter to
+ * {@link #createInstance(ContainerTypeDescription, Object[])}.
+ * Get the imported config types for a given ContainerTypeDescription for the given exporter supported config types. This
+ * method will be called to determine what the local container imported configs are for the given description and
+ * exporterSupportedConfigTypes. The local provider can decide which (if any) imported config types should be
+ * returned and return them.
+ *
+ * As an example, consider the config types for the ECF generic provider. A generic server has a config type
+ * of 'ecf.generic.server', and the client has 'ecf.generic.server'. If the generic server exports a given
+ * service, the exportersSupportedConfigTypes will be '[ecf.generic.server]'. When this method is called
+ * with the ecf.generic.client description (i.e. the container type description named 'ecf.generic.client'), it
+ * should respond with a non-null, non-empty array...e.g.: [ecf.generic.client]. This indicates that the
+ * ecf.generic.client can serve as an importer for the given exporter config type. All, other descriptions
+ * should return
+ *
+ * @param prompt
+ * the prompt used to request the boolean value.
+ *
+ * @exception IllegalArgumentException
+ * if
+ *
+ * @param prompt
+ * the prompt used to request the information.
+ *
+ *
+ * @param defaultValue
+ * the value to be used as the default value displayed with the
+ * prompt.
+ *
+ * @exception IllegalArgumentException
+ * if
+ *
+ * @param prompt
+ * the prompt used to request the information.
+ *
+ *
+ * @param defaultName
+ * the name to be used as the default name displayed with the
+ * prompt.
+ *
+ * @exception IllegalArgumentException
+ * if
+ *
+ * @return the prompt.
+ */
+ public String getPrompt() {
+ return prompt;
+ }
+
+ /**
+ * Get the default name.
+ *
+ *
+ *
+ * @return the default name, or null if this
+ *
+ * @param name
+ * the retrieved name (which may be null).
+ *
+ * @see #getName
+ */
+ public void setName(String name) {
+ this.inputName = name;
+ }
+
+ /**
+ * Get the retrieved name.
+ *
+ *
+ *
+ * @return the retrieved name (which may be null)
+ *
+ * @see #setName
+ */
+ public String getName() {
+ return inputName;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/ObjectCallback.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/ObjectCallback.java
new file mode 100644
index 0000000000..ef23602720
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/ObjectCallback.java
@@ -0,0 +1,36 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.security;
+
+/**
+ * Callback that handles arbitrary Objects
+ *
+ */
+public class ObjectCallback implements Callback {
+ Object data;
+
+ public ObjectCallback() {
+ data = null;
+ }
+
+ public ObjectCallback(Object val) {
+ this.data = val;
+ }
+
+ public void setObject(Object val) {
+ this.data = val;
+ }
+
+ public Object getObject() {
+ return this.data;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/PassphraseCallback.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/PassphraseCallback.java
new file mode 100644
index 0000000000..f3c8242571
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/PassphraseCallback.java
@@ -0,0 +1,116 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.security;
+
+/**
+ * Callback that handles passphrases
+ *
+ */
+public class PassphraseCallback implements Callback, java.io.Serializable {
+
+ private static final long serialVersionUID = -6036907502015127266L;
+
+ private String prompt;
+
+ private String defaultPassphrase;
+
+ private String inputPassphrase;
+
+ /**
+ * Construct a
+ *
+ * @param prompt
+ * the prompt used to request the information.
+ *
+ *
+ * @param defaultPassphrase
+ * the name to be used as the default name displayed with the
+ * prompt.
+ *
+ * @exception IllegalArgumentException
+ * if
+ *
+ * @return the prompt.
+ */
+ public String getPrompt() {
+ return prompt;
+ }
+
+ /**
+ * Get the default passphrase.
+ *
+ *
+ *
+ * @return the default passphrase, or
+ *
+ * @param pw
+ * the passphrase (which may be null).
+ *
+ * @see #getPassphrase
+ */
+ public void setPassphrase(String pw) {
+ this.inputPassphrase = pw;
+ }
+
+ /**
+ * Get the retrieved passphrase.
+ *
+ *
+ *
+ * @return the retrieved passphrase (which may be null)
+ *
+ * @see #setPassphrase
+ */
+ public String getPassphrase() {
+ return inputPassphrase;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/PasswordCallback.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/PasswordCallback.java
new file mode 100644
index 0000000000..f0f6e78eaf
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/PasswordCallback.java
@@ -0,0 +1,116 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.security;
+
+/**
+ * Callback that handles passwords
+ *
+ */
+public class PasswordCallback implements Callback, java.io.Serializable {
+
+ private static final long serialVersionUID = 6940002988125290335L;
+
+ private String prompt;
+
+ private String defaultPassword;
+
+ private String inputPassword;
+
+ /**
+ * Construct a
+ *
+ * @param prompt
+ * the prompt used to request the information.
+ *
+ *
+ * @param defaultPassword
+ * the name to be used as the default name displayed with the
+ * prompt.
+ *
+ * @exception IllegalArgumentException
+ * if
+ *
+ * @return the prompt.
+ */
+ public String getPrompt() {
+ return prompt;
+ }
+
+ /**
+ * Get the default password.
+ *
+ *
+ *
+ * @return the default password, or
+ *
+ * @param pw
+ * the password (which may be null).
+ *
+ * @see #getPassword
+ */
+ public void setPassword(String pw) {
+ this.inputPassword = pw;
+ }
+
+ /**
+ * Get the retrieved password.
+ *
+ *
+ *
+ * @return the retrieved password (which may be null)
+ *
+ * @see #setPassword
+ */
+ public String getPassword() {
+ return inputPassword;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/SSLContextFactory.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/SSLContextFactory.java
new file mode 100644
index 0000000000..289b340461
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/SSLContextFactory.java
@@ -0,0 +1,44 @@
+/****************************************************************************
+ * Copyright (c) 2024 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.security;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import javax.net.ssl.SSLContext;
+
+/**
+ * This class exposes three legacy static methods from the {@link SSLContext} class as
+ * methods on an implementing instance. Implementing instances should be registered
+ * as OSGi services.
+ *
+ * @since 3.12
+ */
+public interface SSLContextFactory {
+
+ /**
+ * See SSLContext.getDefault()
+ *
+ * @param callback
+ * the unrecognized
+ *
+ * @param callback
+ * the unrecognized
+ *
+ * @param msg
+ * the detail message.
+ */
+ public UnsupportedCallbackException(Callback callback, String msg) {
+ super(msg);
+ this.callback = callback;
+ }
+
+ /**
+ * Get the unrecognized
+ *
+ * @return the unrecognized
+ * IMPORTANT:
+ * The StringUtils class provides static methods that helps make string
+ * manipulation easy. The primary functionality it is meant to provide is the
+ * ability to split a string into a string array based on a given delimiter.
+ * This functionality is meant to take the place of the split(String) and
+ * split(String, int) method that was introduced in J2SE-1.4. Please note,
+ * however, that the splitting performed by this class simply splits the string
+ * based on the delimiter and does not perform any regular expression matching
+ * like the split methods provided in J2SE-1.4.
+ *
+ * If the the file transfer was canceled by the user, then the exception
+ * returned will be an instance of {@link UserCancelledException}.
+ *
+ * @return Exception associated with this file transfer.
+ * Note these methods will be called asynchronously when notifications of remote
+ * changes are received by the provider implementation code. The provider is
+ * free to call the methods below with an arbitrary thread, so the
+ * implementation of these methods must be appropriately prepared.
+ *
+ * For example, if the code implementing any of these methods must interact with
+ * user interface code, then it should use code such as the following to execute
+ * on the SWT UI thread:
+ *
+ *
+ * The time is represented as the number of Universal Time (UT)
+ * milliseconds since the epoch (00:00:00 GMT, January 1, 1970).
+ *
+ * Note this method will be called asynchronously when notifications of remote
+ * changes are received by the provider implementation code. The provider is
+ * free to call the methods below with an arbitrary thread, so the
+ * implementation of these methods must be appropriately prepared.
+ *
+ * For example, if the code implementing any of these methods must interact with
+ * user interface code, then it should use code such as the following to execute
+ * on the SWT UI thread:
+ *
+ *
+ * For example, to retrieve a remote file and store it in a local file:
+ *
+ *
+ * NOTE: if this method completes successfully, the given transferListener
+ * will be asynchronously notified via an IIncomingFileTransferReceiveDoneEvent
+ * (along with other possible events). All implementations are required to
+ * issue this event whether successful or failed. Listeners
+ * can consult {@link IIncomingFileTransferReceiveDoneEvent#getException()} to
+ * determine whether the transfer operation completed successfully.
+ *
+ * NOTE: if this method completes successfully, the given transferListener
+ * will be asynchronously notified via an IIncomingFileTransferReceiveDoneEvent
+ * (along with other possible events). All implementations are required to
+ * issue this event whether successful or failed. Listeners
+ * can consult {@link IIncomingFileTransferReceiveDoneEvent#getException()} to
+ * determine whether the transfer operation completed successfully.
+ *
+ * When proxy is
+ * If no information is available via
+ * To request and initiate sending a local file to a remote user:
+ *
+ *
+ * The event is send before the first request is send to the server.
+ * It allows the caller to get a handle to the transfer so that it can be
+ * canceled.
+ * A transfer may have to send several requests to one (or more
+ * servers) until the retrieved or send data itself is send or received.
+ * The entire phase before this is referred here as connect phase.
+ *
+ * If {@link #connectUsingJob(FileTransferJob)} is called then the connect
+ * phase is performed in a job. If not the caller may implement their own thread
+ * in which it can cancel the request. The expectation is that the
+ * cancellation will react with little delay, typically in less than 1 second.
+ *
+ * Not all providers support this event.
+ *
+ * As a result the connect job will be tied to the transfer. Only if the
+ * returned job is passed into
+ * {@link #connectUsingJob(FileTransferJob)} will it actually be scheduled to
+ * run.
+ *
+ * The passed in connectJob must have been prepared using
+ * {@link #prepareConnectJob(FileTransferJob)}.
+ * The job may be scheduled after the caller returns from handling of
+ * the {@link IFileTransferConnectStartEvent}. As this is provider
+ * implementation specific it must not relied on.
+ *
+ * If the the file transfer was canceled by the user, then the exception
+ * returned will be an instance of {@link UserCancelledException}.
+ *
+ * @return Exception associated with this file transfer.
+ * This event is fired even if the browse failed or has been canceled. In this case
+ * the cause is provided via {@link #getException()}.
+ *
+ * The associated source returned by {@link #getSource()} is
+ * the same as for the prior {@link ISocketCreatedEvent} and
+ * {@link ISocketConnectedEvent} with the same
+ * {@link #getFactorySocket()}. It may not reflect the source
+ * currently using or most recently using the socket.
+ *
+ * EXPERIMENTAL. This class or interface has been added as
+ * part of a work in progress. There is no guarantee that this API will
+ * work or that it will remain the same. Please do not use this API without
+ * consulting with the ECF team.
+ *
+ * Can be used to wrap a socket by calling {@link #setSocket(Socket)}.
+ *
+ * EXPERIMENTAL. This class or interface has been added as
+ * part of a work in progress. There is no guarantee that this API will
+ * work or that it will remain the same. Please do not use this API without
+ * consulting with the ECF team.
+ *
+ * If this method is not called {@link #getFactorySocket()} and
+ * {@link #getSocket()} will be the same.
+ * Otherwise {@link #getSocket()} will return the passed in socket.
+ *
+ * EXPERIMENTAL. This class or interface has been added as
+ * part of a work in progress. There is no guarantee that this API will
+ * work or that it will remain the same. Please do not use this API without
+ * consulting with the ECF team.
+ *
+ * Beware that the associated source may not be instance currently
+ * using the socket. For example a socket may be put into a
+ * connection pool after it is used. It is then typically reused
+ * by another source.
+ * When a socket is closed this is attributed to the source which
+ * created it, not which currently or most recently used it.
+ * This limits the usefulness of these events to cases
+ * where the caller can make broader assumptions for example
+ * because it wants to close or monitor all sockets in the
+ * entire application.
+ * The events are also useful for implementing unit tests.
+ *
+ * The {@link ISocketConnectedEvent} allows an
+ * {@link ISocketListener} to wrap the socket.
+ *
+ * EXPERIMENTAL. This class or interface has been added as
+ * part of a work in progress. There is no guarantee that this API will
+ * work or that it will remain the same. Please do not use this API without
+ * consulting with the ECF team.
+ *
+ * For the given protocol, set the given factory to be used for retrieve file transfer. If successful, subsequent retrieve
+ * requests for the given protocol will use the given factory. For this method to be successful the protocol has to be
+ * non-null, the id has to be non-null and unique (should probably be set to the bundle symbolic name of the bundle calling this
+ * method), the factory must be non-null, and the priority must be higher (a *smaller number*) than any existing factory for the
+ * given protocol. The default priority is 100, and the highest priority is 0.
+ *
+ * For the given protocol, set the given factory to be used for retrieve file transfer. If successful, subsequent retrieve
+ * requests for the given protocol will use the given factory. For this method to be successful the protocol has to be
+ * non-null, the id has to be non-null and unique (should probably be set to the bundle symbolic name of the bundle calling this
+ * method), the factory must be non-null, and the priority must be higher (a *smaller number*) than any existing factory for the
+ * given protocol. The default priority is 100, and the highest priority is 0.
+ *
+ * For the given protocol, set the given factory to be used for retrieve file transfer. If successful, subsequent retrieve
+ * requests for the given protocol will use the given factory. For this method to be successful the protocol has to be
+ * non-null, the id has to be non-null and unique (should probably be set to the bundle symbolic name of the bundle calling this
+ * method), the factory must be non-null, and the priority must be higher (a *smaller number*) than any existing factory for the
+ * given protocol. The default priority is 100, and the highest priority is 0.
+ *
+ * For the given protocol, set the given factory to be used for retrieve file transfer. If successful, subsequent retrieve
+ * requests for the given protocol will use the given factory. For this method to be successful the protocol has to be
+ * non-null, the id has to be non-null and unique (should probably be set to the bundle symbolic name of the bundle calling this
+ * method), the factory must be non-null, and the priority must be higher (a *smaller number*) than any existing factory for the
+ * given protocol. The default priority is 100, and the highest priority is 0.
+ *
+ * For the given protocol, set the given factory to be used for retrieve file transfer. If successful, subsequent retrieve
+ * requests for the given protocol will use the given factory. For this method to be successful the protocol has to be
+ * non-null, the id has to be non-null and unique (should probably be set to the bundle symbolic name of the bundle calling this
+ * method), the factory must be non-null, and the priority must be higher (a *smaller number*) than any existing factory for the
+ * given protocol. The default priority is 100, and the highest priority is 0.
+ *
+ * For the given protocol, set the given factory to be used for retrieve file transfer. If successful, subsequent retrieve
+ * requests for the given protocol will use the given factory. For this method to be successful the protocol has to be
+ * non-null, the id has to be non-null and unique (should probably be set to the bundle symbolic name of the bundle calling this
+ * method), the factory must be non-null, and the priority must be higher (a *smaller number*) than any existing factory for the
+ * given protocol. The default priority is 100, and the highest priority is 0.
+ * null.
+ *
+ * @return the ID for this identifiable object. May return null.
+ */
+ public ID getID();
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/IResourceID.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/IResourceID.java
new file mode 100644
index 0000000000..0f5d6ac619
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/IResourceID.java
@@ -0,0 +1,34 @@
+/****************************************************************************
+ * Copyright (c) 2009 EclipseSource and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * EclipseSource - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.identity;
+
+import java.net.URI;
+
+/**
+ * Resource id. ID instances that implement this interface are expected to be
+ * resources (files, directories, URLs, etc) and so can be identified via a
+ * {@link URI}.
+ *
+ * @since 3.0
+ *
+ */
+public interface IResourceID extends ID {
+
+ /**
+ * Convert this resource ID to a {@link URI}.
+ *
+ * @return URI for this resource ID
+ */
+ public URI toURI();
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/LongID.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/LongID.java
new file mode 100644
index 0000000000..08c078a4ea
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/LongID.java
@@ -0,0 +1,108 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.identity;
+
+/**
+ * A unique ID class based upon Long/long
+ *
+ */
+public class LongID extends BaseID {
+ private static final long serialVersionUID = 4049072748317914423L;
+
+ Long value = null;
+
+ public static class LongNamespace extends Namespace {
+ private static final long serialVersionUID = -1580533392719331665L;
+
+ public LongNamespace() {
+ super(LongID.class.getName(), "LongID Namespace"); //$NON-NLS-1$
+ }
+
+ /**
+ * @param args must not be null>
+ * @return ID created. Will not be null.
+ * @throws IDCreateException never thrown
+ */
+ public ID createInstance(Object[] args) throws IDCreateException {
+ try {
+ String init = getInitStringFromExternalForm(args);
+ if (init != null)
+ return new LongID(this, Long.decode(init));
+ return new LongID(this, (Long) args[0]);
+ } catch (Exception e) {
+ throw new IDCreateException(getName() + " createInstance()", e); //$NON-NLS-1$
+ }
+ }
+
+ public String getScheme() {
+ return LongID.class.getName();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.ecf.core.identity.Namespace#
+ * getSupportedParameterTypesForCreateInstance()
+ */
+ public Class>[][] getSupportedParameterTypes() {
+ return new Class[][] { { Long.class }, { String.class } };
+ }
+ }
+
+ /**
+ * @since 3.9
+ */
+ public LongID() {
+
+ }
+
+ protected LongID(Namespace n, Long v) {
+ super(n);
+ value = v;
+ }
+
+ protected LongID(Namespace n, long v) {
+ super(n);
+ value = Long.valueOf(v);
+ }
+
+ protected int namespaceCompareTo(BaseID o) {
+ Long ovalue = ((LongID) o).value;
+ return value.compareTo(ovalue);
+ }
+
+ protected boolean namespaceEquals(BaseID o) {
+ if (!(o instanceof LongID))
+ return false;
+ LongID obj = (LongID) o;
+ return value.equals(obj.value);
+ }
+
+ protected String namespaceGetName() {
+ return value.toString();
+ }
+
+ protected int namespaceHashCode() {
+ return value.hashCode();
+ }
+
+ public long longValue() {
+ return value.longValue();
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder("LongID["); //$NON-NLS-1$
+ sb.append(value).append("]"); //$NON-NLS-1$
+ return sb.toString();
+
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/Namespace.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/Namespace.java
new file mode 100644
index 0000000000..71221c75b3
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/Namespace.java
@@ -0,0 +1,328 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.identity;
+
+import java.io.Serializable;
+import org.eclipse.core.runtime.*;
+import org.eclipse.ecf.internal.core.identity.Activator;
+
+/**
+ * Namespace base class.
+ *
+ * <extension
+ * point="org.eclipse.ecf.namespace">
+ * <namespace
+ * class="XMPPNamespace"
+ * name="ecf.xmpp"/>
+ * </extension>
+ *
+ *
+ * @see ID
+ */
+public abstract class Namespace implements Serializable, IAdaptable {
+
+ private static final long serialVersionUID = 3976740272094720312L;
+
+ public static final String SCHEME_SEPARATOR = ":"; //$NON-NLS-1$
+
+ private String name;
+
+ private String description;
+
+ private transient int hashCode;
+
+ private transient boolean isInitialized = false;
+
+ public Namespace() {
+ // public null constructor
+ }
+
+ public final boolean initialize(String n, String desc) {
+ Assert.isNotNull(n, "Namespacenull.
+ * @param second
+ * the second ID. Must not be null.
+ * @return true if this ID is equal to the given ID.
+ * false otherwise.
+ */
+ protected boolean testIDEquals(BaseID first, BaseID second) {
+ // First check that namespaces are the same and non-null
+ Namespace sn = second.getNamespace();
+ if (sn == null || !this.equals(sn))
+ return false;
+ return first.namespaceEquals(second);
+ }
+
+ /**
+ * The default implementation of this method is to call id.namespaceGetName().
+ * Subclasses may override.
+ *
+ * @param id
+ * the ID to get the name for. Must not be null.
+ * @return String that is the unique name for the given id within this
+ * Namespace.
+ */
+ protected String getNameForID(BaseID id) {
+ return id.namespaceGetName();
+ }
+
+ /**
+ * The default implementation of this method is to call
+ * first.namespaceCompareTo(second). Subclasses may override.
+ *
+ * @param first
+ * the first id to compare. Must not be null.
+ * @param second
+ * the second id to compare. Must not be null.
+ * @return int as specified by {@link Comparable}.
+ */
+ protected int getCompareToForObject(BaseID first, BaseID second) {
+ return first.namespaceCompareTo(second);
+ }
+
+ /**
+ * The default implementation of this method is to call id.namespaceHashCode().
+ * Subclasses may override.
+ *
+ * @param id
+ * the id in this Namespace to get the hashcode for. Must not be
+ * null.
+ * @return the hashcode for the given id. Returned value must be unique within
+ * this process.
+ */
+ protected int getHashCodeForID(BaseID id) {
+ return id.namespaceHashCode();
+ }
+
+ /**
+ * The default implementation of this method is to call
+ * id.namespaceToExternalForm(). Subclasses may override.
+ *
+ * @param id
+ * the id in this Namespace to convert to external form.
+ * @return String that represents the given id in an external form. Note that
+ * this external form may at some later time be passed to
+ * {@link #createInstance(Object[])} as a single String parameter, and
+ * should result in a valid ID instance of the appropriate Namespace.
+ */
+ protected String toExternalForm(BaseID id) {
+ return id.namespaceToExternalForm();
+ }
+
+ /**
+ * Get the name of this namespace. Must not return null.
+ *
+ * @return String name of Namespace instance. Must not return null,
+ * and the returned value should be a globally unique name for this
+ * Namespace subclass.
+ *
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Get the description, associated with this Namespace. The returned value may
+ * be null.
+ *
+ * @return the description associated with this Namespace. May be
+ * null.
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Make an instance of this namespace. Namespace subclasses, provided by plugins
+ * must implement this method to construct ID instances for the given namespace.
+ * null scheme
+ * identifier. Note that the returned scheme should not contain the
+ * Namespace.SCHEME_SEPARATOR (\":\").
+ *
+ * @return a String scheme identifier. Must not be null.
+ */
+ public abstract String getScheme();
+
+ /**
+ * Get an array of schemes supported by this Namespace instance. Subclasses may
+ * override to support multiple schemes.
+ *
+ * @return String[] of schemes supported by this Namespace. Will not be
+ * null, but returned array may be of length 0.
+ */
+ public String[] getSupportedSchemes() {
+ return new String[0];
+ }
+
+ /**
+ * Get the supported parameter types for IDs created via subsequent calls to
+ * {@link #createInstance(Object[])}. Callers may use this method to determine
+ * the available parameter types, and then create and pass in conforming Object
+ * arrays to to {@link #createInstance(Object[])}.
+ *
+ * public Class[][] getSupportedParameterTypes() {
+ * return new Class[][] { { String.class }, { String.class, String.class } };
+ * }
+ *
+ *
+ * The above means that there are two acceptable values for the Object [] passed
+ * into {@link #createInstance(Object[])}: 1) a single String, and 2) two
+ * Strings. These would therefore be acceptable as input to createInstance:
+ *
+ *
+ * ID newID1 = namespace.createInstance(new Object[] { "Hello" });
+ * ID newID2 = namespace.createInstance(new Object[] { "Hello", "There"}};
+ *
+ *
+ * @return Class [][] an array of class []s. Rows of the returned
+ * two-dimensional array define the acceptable parameter types for a
+ * single call to {@link #createInstance(Object[])}. If zero-length
+ * Class arrays are returned (i.e. Class[0][0]), then Object []
+ * parameters to {@link #createInstance(Object[])} will be ignored.
+ */
+ public Class>[][] getSupportedParameterTypes() {
+ return new Class[][] { {} };
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+ */
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ if (adapter.isInstance(this)) {
+ return this;
+ }
+ IAdapterManager manager = Activator.getDefault().getAdapterManager();
+ if (manager == null)
+ return null;
+ return manager.loadAdapter(this, adapter.getName());
+ }
+
+ /**
+ * @since 3.1
+ */
+ protected String getInitStringFromExternalForm(Object[] args) {
+ if (args == null || args.length < 1 || args[0] == null)
+ return null;
+ if (args[0] instanceof String) {
+ final String arg = (String) args[0];
+ if (arg.startsWith(getScheme() + SCHEME_SEPARATOR)) {
+ final int index = arg.indexOf(SCHEME_SEPARATOR);
+ if (index >= arg.length())
+ return null;
+ return arg.substring(index + 1);
+ }
+ }
+ return null;
+ }
+
+ public String toString() {
+ StringBuilder b = new StringBuilder("Namespace["); //$NON-NLS-1$
+ b.append("name=").append(name).append(";"); //$NON-NLS-1$ //$NON-NLS-2$
+ b.append("scheme=").append(getScheme()).append(";"); //$NON-NLS-1$ //$NON-NLS-2$
+ b.append("description=").append("]"); //$NON-NLS-1$ //$NON-NLS-2$
+ return b.toString();
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/NamespacePermission.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/NamespacePermission.java
new file mode 100644
index 0000000000..e2f4d6f82e
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/NamespacePermission.java
@@ -0,0 +1,55 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.identity;
+
+import java.security.BasicPermission;
+import java.security.Permission;
+
+public class NamespacePermission extends BasicPermission {
+ private static final long serialVersionUID = 3257004371500806969L;
+
+ public static final String ADD_NAMESPACE = "add"; //$NON-NLS-1$
+
+ public static final String ALL_NAMESPACE = "all"; //$NON-NLS-1$
+
+ public static final String CONTAINS_NAMESPACE = "contains"; //$NON-NLS-1$
+
+ public static final String GET_NAMESPACE = "get"; //$NON-NLS-1$
+
+ public static final String REMOVE_NAMESPACE = "remove"; //$NON-NLS-1$
+
+ protected String actions;
+
+ /**
+ * @since 3.9
+ */
+ public NamespacePermission() {
+ super("", "");
+ }
+
+ public NamespacePermission(String s) {
+ super(s);
+ }
+
+ public NamespacePermission(String s, String s1) {
+ super(s, s1);
+ actions = s1;
+ }
+
+ public String getActions() {
+ return actions;
+ }
+
+ public boolean implies(Permission p) {
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/StringID.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/StringID.java
new file mode 100644
index 0000000000..3996a55168
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/StringID.java
@@ -0,0 +1,144 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.identity;
+
+/**
+ * A string-based identity
+ *
+ */
+public class StringID extends BaseID {
+ private static final long serialVersionUID = 3256437019155446068L;
+
+ public static class StringIDNamespace extends Namespace {
+ private static final long serialVersionUID = 7924280015192029963L;
+
+ public StringIDNamespace(String name, String desc) {
+ super(name, desc);
+ }
+
+ public StringIDNamespace() {
+ super(StringID.class.getName(), "StringID Namespace"); //$NON-NLS-1$
+ }
+
+ public ID createInstance(Object[] parameters) throws IDCreateException {
+ try {
+ String init = getInitStringFromExternalForm(parameters);
+ if (init != null)
+ return new StringID(this, init);
+ return new StringID(this, (String) parameters[0]);
+ } catch (Exception e) {
+ throw new IDCreateException(StringIDNamespace.this.getName() + " createInstance()", e); //$NON-NLS-1$
+ }
+ }
+
+ public String getScheme() {
+ return StringID.class.getName();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.ecf.core.identity.Namespace#
+ * getSupportedParameterTypesForCreateInstance()
+ */
+ public Class>[][] getSupportedParameterTypes() {
+ return new Class[][] { { String.class } };
+ }
+ }
+
+ protected String value;
+
+ /**
+ * @since 3.9
+ */
+ public StringID() {
+
+ }
+
+ /**
+ * Protected constructor for factory-based construction
+ *
+ * @param n
+ * the Namespace this identity will belong to
+ * @param s
+ * the String defining this StringID
+ */
+ protected StringID(Namespace n, String s) {
+ super(n);
+ value = s;
+ setEmptyNamespace();
+ }
+
+ public int compareTo(Object o) {
+ setEmptyNamespace();
+ return super.compareTo(o);
+ }
+
+ public boolean equals(Object o) {
+ setEmptyNamespace();
+ return super.equals(o);
+ }
+
+ public String getName() {
+ setEmptyNamespace();
+ return super.getName();
+ }
+
+ public int hashCode() {
+ setEmptyNamespace();
+ return super.hashCode();
+ }
+
+ public Namespace getNamespace() {
+ setEmptyNamespace();
+ return namespace;
+ }
+
+ public String toExternalForm() {
+ setEmptyNamespace();
+ return super.toExternalForm();
+ }
+
+ public String toString() {
+ setEmptyNamespace();
+ int strlen = value.length();
+ StringBuilder sb = new StringBuilder(strlen + 10);
+ sb.insert(0, "StringID[").insert(9, value).insert(strlen + 9, ']'); //$NON-NLS-1$
+ return sb.toString();
+ }
+
+ protected int namespaceCompareTo(BaseID obj) {
+ return getName().compareTo(obj.getName());
+ }
+
+ protected boolean namespaceEquals(BaseID obj) {
+ if (!(obj instanceof StringID))
+ return false;
+ StringID o = (StringID) obj;
+ return value.equals(o.getName());
+ }
+
+ protected String namespaceGetName() {
+ return value;
+ }
+
+ protected int namespaceHashCode() {
+ return value.hashCode() ^ getClass().hashCode();
+ }
+
+ protected synchronized void setEmptyNamespace() {
+ if (namespace == null) {
+ namespace = IDFactory.getDefault().getNamespaceByName(StringID.class.getName());
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/URIID.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/URIID.java
new file mode 100644
index 0000000000..7acda187c5
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/URIID.java
@@ -0,0 +1,131 @@
+/****************************************************************************
+ * Copyright (c) 2011 Composent and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * EclipseSource - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.identity;
+
+import java.net.URI;
+import java.util.UUID;
+import org.eclipse.core.runtime.Assert;
+
+/**
+ * URI ID class.
+ *
+ * @since 3.0
+ */
+public class URIID extends BaseID implements IResourceID {
+
+ /**
+ * @since 3.7
+ */
+ public static class URIIDNamespace extends Namespace {
+
+ private static final long serialVersionUID = 115165512542491014L;
+
+ /**
+ * @since 3.8
+ */
+ public static final String UUID_PROTOCOL = "uuid";
+
+ public URIIDNamespace(String name, String desc) {
+ super(name, desc);
+ }
+
+ public URIIDNamespace() {
+ super(URIID.class.getName(), "URIID Namespace"); //$NON-NLS-1$
+ }
+
+ public ID createInstance(Object[] parameters) throws IDCreateException {
+ try {
+ String init = getInitStringFromExternalForm(parameters);
+ if (init != null)
+ return new URIID(this, new URI(init));
+ if (parameters[0] instanceof URI)
+ return new URIID(this, (URI) parameters[0]);
+ if (parameters[0] instanceof String)
+ return new URIID(this, new URI((String) parameters[0]));
+ throw new IDCreateException("Cannot create URIID");
+ } catch (Exception e) {
+ throw new IDCreateException(URIIDNamespace.this.getName() + " createInstance()", e); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * @since 3.8
+ */
+ public ID createRandomUUID() throws IDCreateException {
+ return createInstance(new Object[] { UUID_PROTOCOL + ":" + UUID.randomUUID().toString() });
+ }
+
+ public String getScheme() {
+ return "uri";
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.ecf.core.identity.Namespace#
+ * getSupportedParameterTypesForCreateInstance()
+ */
+ public Class>[][] getSupportedParameterTypes() {
+ return new Class[][] { { String.class }, { URI.class } };
+ }
+ }
+
+ private static final long serialVersionUID = 7328962407044918278L;
+ private URI uri;
+
+ /**
+ * @since 3.9
+ */
+ public URIID() {
+
+ }
+
+ public URIID(Namespace namespace, URI uri) {
+ super(namespace);
+ Assert.isNotNull(uri);
+ this.uri = uri;
+ }
+
+ protected int namespaceCompareTo(BaseID o) {
+ if (this == o)
+ return 0;
+ if (!this.getClass().equals(o.getClass()))
+ return Integer.MIN_VALUE;
+ return this.uri.compareTo(((URIID) o).uri);
+ }
+
+ protected boolean namespaceEquals(BaseID o) {
+ if (this == o)
+ return true;
+ if (!this.getClass().equals(o.getClass()))
+ return false;
+ return this.uri.toString().equals((((URIID) o).uri).toString());
+ }
+
+ protected String namespaceGetName() {
+ return uri.toString();
+ }
+
+ protected int namespaceHashCode() {
+ return uri.toString().hashCode() ^ getClass().hashCode();
+ }
+
+ public URI toURI() {
+ return uri;
+ }
+
+ public String toString() {
+ return "URIID [uri=" + uri + "]";
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/UuID.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/UuID.java
new file mode 100644
index 0000000000..26fefee157
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/identity/UuID.java
@@ -0,0 +1,114 @@
+/****************************************************************************
+ * Copyright (c) 2015 Composent and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Scott Lewis - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.identity;
+
+import java.net.URI;
+import java.util.UUID;
+import org.eclipse.core.runtime.Assert;
+
+/**
+ * @since 3.5
+ */
+public class UuID extends BaseID {
+
+ private static final long serialVersionUID = -2586540125532542205L;
+
+ public static class UuIDNamespace extends Namespace {
+
+ private static final long serialVersionUID = -7708511830843215943L;
+ public static final String SCHEME = "uuid";
+
+ public UuIDNamespace() {
+ this(UuID.class.getName(), "UuID Namespace");
+ }
+
+ public UuIDNamespace(String name, String description) {
+ super(name, description);
+ }
+
+ @Override
+ public ID createInstance(Object[] parameters) throws IDCreateException {
+ try {
+ String init = getInitStringFromExternalForm(parameters);
+ if (init != null)
+ return new UuID(this, UUID.fromString(init));
+ if (parameters != null && parameters.length > 0) {
+ if (parameters[0] instanceof String)
+ return new UuID(this, UUID.fromString((String) parameters[0]));
+ else if (parameters[0] instanceof URI)
+ return new UuID(this, UUID.fromString(((URI) parameters[0]).getSchemeSpecificPart()));
+ else if (parameters[0] instanceof UUID)
+ return new UuID(this, (UUID) parameters[0]);
+ }
+ // If we get here, then use random
+ return new UuID(this, UUID.randomUUID());
+ } catch (Exception e) {
+ throw new IDCreateException(UuIDNamespace.this.getName() + " createInstance()", e); //$NON-NLS-1$
+ }
+ }
+
+ @Override
+ public String getScheme() {
+ return SCHEME;
+ }
+
+ @Override
+ public Class>[][] getSupportedParameterTypes() {
+ return new Class[][] { { String.class }, { UUID.class }, { URI.class } };
+ }
+ }
+
+ protected UUID uuid;
+
+ /**
+ * @since 3.9
+ */
+ public UuID() {
+
+ }
+
+ protected UuID(UuIDNamespace ns, UUID uuid) {
+ super(ns);
+ Assert.isNotNull(uuid);
+ this.uuid = uuid;
+ }
+
+ protected int namespaceCompareTo(BaseID obj) {
+ return getName().compareTo(obj.getName());
+ }
+
+ protected boolean namespaceEquals(BaseID obj) {
+ if (!(obj instanceof UuID))
+ return false;
+ UuID o = (UuID) obj;
+ return uuid.equals(o.uuid);
+ }
+
+ protected String namespaceGetName() {
+ return uuid.toString();
+ }
+
+ protected int namespaceHashCode() {
+ return uuid.hashCode() ^ getClass().hashCode();
+ }
+
+ public UUID getUUID() {
+ return uuid;
+ }
+
+ @Override
+ public String toString() {
+ return "UuID[uuid=" + uuid + "]";
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/jobs/JobsExecutor.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/jobs/JobsExecutor.java
new file mode 100644
index 0000000000..7ca01f8c06
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/jobs/JobsExecutor.java
@@ -0,0 +1,99 @@
+/****************************************************************************
+ * Copyright (c) 2008 EclipseSource, IBM, and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * EclipseSource - initial API and implementation
+ * IBM Corporation - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.jobs;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.equinox.concurrent.future.*;
+
+/**
+ * @since 3.2
+ */
+public class JobsExecutor extends AbstractExecutor {
+
+ protected int fJobCounter = 1;
+ protected String fExecutorName;
+ protected boolean fSystem;
+ protected ISchedulingRule fSchedulingRule;
+ protected long delay;
+
+ public JobsExecutor(String executorName) {
+ this(executorName, false);
+ }
+
+ public JobsExecutor(String executorName, boolean system) {
+ this(executorName, system, null);
+ }
+
+ public JobsExecutor(String executorName, boolean system, ISchedulingRule schedulingRule) {
+ this(executorName, system, schedulingRule, 0L);
+ }
+
+ public JobsExecutor(String executorName, boolean system, ISchedulingRule schedulingRule, long delay) {
+ this.fExecutorName = executorName;
+ this.fSystem = system;
+ this.fSchedulingRule = schedulingRule;
+ this.delay = delay;
+ }
+
+ protected void setChildProgressMonitor(IProgressMonitor parent, IProgressMonitor child) {
+ if (parent instanceof FutureProgressMonitor) {
+ ((FutureProgressMonitor) parent).setChildProgressMonitor(child);
+ }
+ }
+
+ protected void safeRun(ISafeProgressRunner runner, IProgressRunnable progressRunnable) {
+ runner.runWithProgress(progressRunnable);
+ }
+
+ protected String createJobName(String executorName, int jobCounter, IProgressRunnable runnable) {
+ return "JobsExecutor(" + executorName + ")." + jobCounter; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ protected AbstractFuture createFuture(IProgressMonitor progressMonitor) {
+ return new SingleOperationFuture(progressMonitor);
+ }
+
+ public IFuture execute(final IProgressRunnable runnable, final IProgressMonitor clientProgressMonitor) {
+ Assert.isNotNull(runnable);
+ final AbstractFuture sof = createFuture(clientProgressMonitor);
+ Job job = new Job(createJobName(fExecutorName, fJobCounter++, runnable)) {
+ {
+ setSystem(fSystem);
+ setRule(fSchedulingRule);
+ }
+
+ protected IStatus run(IProgressMonitor monitor) {
+ // First check to make sure things haven't been canceled
+ if (sof.isCanceled())
+ return sof.getStatus();
+ // Now add progress monitor as child of future progress monitor
+ setChildProgressMonitor(sof.getProgressMonitor(), monitor);
+ // Now run safely
+ safeRun(sof, runnable);
+ return sof.getStatus();
+ }
+ };
+ // Configure job before scheduling
+ configureJobForExecution(job);
+ job.schedule(delay);
+ return sof;
+ }
+
+ protected void configureJobForExecution(Job job) {
+ // do nothing by default
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/BaseContainerInstantiator.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/BaseContainerInstantiator.java
new file mode 100644
index 0000000000..42f57616b0
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/BaseContainerInstantiator.java
@@ -0,0 +1,244 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.core.provider;
+
+import java.util.*;
+import org.eclipse.core.runtime.IAdapterManager;
+import org.eclipse.ecf.core.*;
+import org.eclipse.ecf.core.identity.ID;
+import org.eclipse.ecf.core.identity.Namespace;
+import org.eclipse.ecf.internal.core.ECFPlugin;
+
+/**
+ * Default implementation of {@link IContainerInstantiator}. ECF provider implementers
+ * may subclass as desired.
+ */
+public class BaseContainerInstantiator implements IContainerInstantiator {
+
+ protected static String[] NO_ADAPTERS_ARRAY = new String[] {IContainer.class.getName()};
+ protected static String[] EMPTY_STRING_ARRAY = new String[] {};
+ protected static Class[][] EMPTY_CLASS_ARRAY = new Class[][] {{}};
+
+ /**
+ * @param arg object to get Integer from
+ * @return Integer created from Object arg
+ * @since 3.6
+ */
+ protected Integer getIntegerFromArg(Object arg) {
+ if (arg == null)
+ return null;
+ if (arg instanceof Integer)
+ return (Integer) arg;
+ else if (arg instanceof String) {
+ return Integer.valueOf((String) arg);
+ } else
+ throw new IllegalArgumentException("arg=" + arg + " is not of integer type"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * @param arg object to get String from
+ * @return String created from Object arg
+ * @since 3.6
+ */
+ protected String getStringFromArg(Object arg) {
+ if (arg == null)
+ return null;
+ if (arg instanceof String) {
+ return (String) arg;
+ }
+ throw new IllegalArgumentException("arg=" + arg + " is not of String type"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ protected Set getAdaptersForClass(Class clazz) {
+ Set result = new HashSet();
+ IAdapterManager adapterManager = ECFPlugin.getDefault().getAdapterManager();
+ if (adapterManager != null)
+ result.addAll(Arrays.asList(adapterManager.computeAdapterTypes(clazz)));
+ return result;
+ }
+
+ protected Set getInterfacesForClass(Set s, Class clazz) {
+ if (clazz.equals(Object.class))
+ return s;
+ s.addAll(getInterfacesForClass(s, clazz.getSuperclass()));
+ s.addAll(Arrays.asList(clazz.getInterfaces()));
+ return s;
+ }
+
+ protected Set getInterfacesForClass(Class clazz) {
+ Set clazzes = getInterfacesForClass(new HashSet(), clazz);
+ Set result = new HashSet();
+ for (Iterator i = clazzes.iterator(); i.hasNext();)
+ result.add(((Class) i.next()).getName());
+ return result;
+ }
+
+ protected String[] getInterfacesAndAdaptersForClass(Class clazz) {
+ Set result = getAdaptersForClass(clazz);
+ result.addAll(getInterfacesForClass(clazz));
+ return (String[]) result.toArray(new String[] {});
+ }
+
+ /**
+ * @param parameters parameters to get Map from
+ * @return Map from first of parameters that is instance of Map
+ * @since 3.6
+ */
+ protected Mapnull
+ * @param null
+ * @return String value from parameters with key
+ * @since 3.6
+ */
+ protected String getParameterValue(Mapnull
+ * @param parameters Map parameters to get value from
+ * @param key the key to use to get value from parameters
+ * @param type the expected type of the value from parameters
+ * @param def a default value to use if value from parameters is null
+ * @param null
+ * @param parameters Map parameters to get value from
+ * @param key the key to use to get value from parameters
+ * @param def a default String value to use if value from parameters is null
+ * @return ID the created ID
+ * @since 3.8
+ */
+ protected ID getIDParameterValue(Namespace ns, Mapnull
+ * @param parameters Map parameters to get value from
+ * @param key the key to use to get value from parameters
+ * @return ID the created ID
+ * @since 3.8
+ */
+ protected ID getIDParameterValue(Namespace ns, Mapnull
+ * @param null
+ * @return Sting the parameter value with key from Map
+ * @since 3.6
+ */
+ protected String getMapParameterString(Object[] parameters, String key, String def) {
+ return getParameterValue(parameters, key, String.class, def);
+ }
+
+ /**
+ * @param parameters parameters assumed to contain a Map
+ * @param key key to use to get parameter value from Map
+ * @return Sting the parameter value with key from Map
+ * @since 3.6
+ */
+ protected String getMapParameterString(Object[] parameters, String key) {
+ return getParameterValue(parameters, key, String.class, null);
+ }
+
+ public IContainer createInstance(ContainerTypeDescription description, Object[] parameters) throws ContainerCreateException {
+ throw new ContainerCreateException("createInstance not supported"); //$NON-NLS-1$
+ }
+
+ public String[] getSupportedAdapterTypes(ContainerTypeDescription description) {
+ return NO_ADAPTERS_ARRAY;
+ }
+
+ public Class[][] getSupportedParameterTypes(ContainerTypeDescription description) {
+ return EMPTY_CLASS_ARRAY;
+ }
+
+ public String[] getSupportedIntents(ContainerTypeDescription description) {
+ return null;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/BaseRemoteServiceContainerInstantiator.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/BaseRemoteServiceContainerInstantiator.java
new file mode 100644
index 0000000000..65b5b012f2
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/BaseRemoteServiceContainerInstantiator.java
@@ -0,0 +1,38 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.core.provider;
+
+import java.util.Dictionary;
+import org.eclipse.ecf.core.ContainerTypeDescription;
+
+/**
+ * Default implementation of {@link IRemoteServiceContainerInstantiator}. ECF provider implementers
+ * may subclass as desired.
+ * @since 3.1
+ */
+public class BaseRemoteServiceContainerInstantiator extends BaseContainerInstantiator implements IRemoteServiceContainerInstantiator {
+
+ public String[] getSupportedConfigs(ContainerTypeDescription description) {
+ return new String[] {description.getName()};
+ }
+
+ public String[] getImportedConfigs(ContainerTypeDescription description, String[] exporterSupportedConfigs) {
+ return new String[] {description.getName()};
+ }
+
+ public Dictionary getPropertiesForImportedConfigs(ContainerTypeDescription description, String[] importedConfigTypes, Dictionary exportedProperties) {
+ return null;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/ContainerInstantiatorUtils.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/ContainerInstantiatorUtils.java
new file mode 100644
index 0000000000..77853c6950
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/ContainerInstantiatorUtils.java
@@ -0,0 +1,136 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.core.provider;
+
+import java.net.*;
+import java.util.*;
+import org.eclipse.ecf.core.identity.ID;
+import org.osgi.framework.Constants;
+
+/**
+ * @since 3.9
+ */
+public class ContainerInstantiatorUtils {
+
+ public static final String PRIVATE_INTENT = "osgi.private"; //$NON-NLS-1$
+
+ /**
+ * @since 3.9
+ */
+ public static String[] getContainerIntents(Mapnull result. In other
+ * words, even if the class name is in the returned array, subsequent calls
+ * to {@link IContainer#getAdapter(Class)} may still return
+ * null.
+ *
+ * @param description
+ * the ContainerTypeDescription to report adapters for. Must not
+ * be null.
+ * @return String[] of supported adapters. The entries in the returned array
+ * will be the fully qualified class names of adapters supported by
+ * the given description. null may be returned by
+ * the provider if no adapters are supported for this description.
+ */
+ public String[] getSupportedAdapterTypes(ContainerTypeDescription description);
+
+ /**
+ * Get array of parameter types for given container type description.
+ * Providers implement this method to allow clients to inspect the available
+ * set of parameter types understood for calls to
+ * {@link #createInstance(ContainerTypeDescription, Object[])}.
+ *
+ * public Class[][] getSupportedParameterTypes() {
+ * return new Class[][] { { String.class }, { String.class, String.class } };
+ * }
+ *
+ *
+ * The above means that there are two acceptable values for the Object []
+ * passed into {@link #createInstance(ContainerTypeDescription, Object[])}:
+ * 1) a single String, and 2) two Strings. These would therefore be
+ * acceptable as input to createInstance:
+ *
+ *
+ * IContainer container = ContainerFactory.getDefault().createContainer(
+ * description, new Object[] { "Hello" });
+ *
+ * IContainer container2 = ContainerFactory.getDefault().createContainer(
+ * description, new Object[] { "Hello" });
+ *
+ * null returned if no parameter types supported for
+ * given description.
+ */
+ public Class[][] getSupportedParameterTypes(ContainerTypeDescription description);
+
+ public String[] getSupportedIntents(ContainerTypeDescription description);
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/IRemoteServiceContainerInstantiator.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/IRemoteServiceContainerInstantiator.java
new file mode 100644
index 0000000000..e769050537
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/provider/IRemoteServiceContainerInstantiator.java
@@ -0,0 +1,85 @@
+/****************************************************************************
+ * Copyright (c) 2009 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.provider;
+
+import java.util.Dictionary;
+import org.eclipse.ecf.core.ContainerTypeDescription;
+
+/**
+ * Interface that must be implemented by ECF remote service provider implementations.
+ * @since 3.1
+ *
+ */
+public interface IRemoteServiceContainerInstantiator {
+
+ // Remote Service Exporter
+ /**
+ * Get supported configs for the given ContainerTypeDescription. This method
+ * will be called to determine what the OSGi remote service supported config types are for the given description during
+ * the search for the service exporter provider/containers upon remote service registration.
+ *
+ * @param description the ContainerTypeDescription to return the supported configs for.
+ * Will not be null.
+ * @return String[] the supported config types. null may be returned if the
+ * given description does not support any config types.
+ */
+ public String[] getSupportedConfigs(ContainerTypeDescription description);
+
+ /**
+ * Get supported intents for the given ContainerTypeDescription. This method
+ * will be called to determine what the OSGi remote service supported intents are for the given description during
+ * the search for the service exporter provider/containers upon remote service registration.
+ *
+ * @param description the ContainerTypeDescription to return the supported intents for.
+ * Will not be null.
+ * @return String[] the supported intents. null may be returned if the
+ * given description does not support any intents.
+ */
+ public String[] getSupportedIntents(ContainerTypeDescription description);
+
+ // Remote Service Importer
+ /**
+ * null, to indicate that they cannot import a remote service exported by the given
+ * exporterSupportedConfigTypes.
+ *
+ * @param description the container type description under consideration.
+ * @param exporterSupportedConfigs the exporter supported config types under consideration.
+ * @return String[] indicating the importer's supported config types. Should be null, unless
+ * one or more of the exporterSupportedConfigTypes is recognized for the given description.
+ */
+ public String[] getImportedConfigs(ContainerTypeDescription description, String[] exporterSupportedConfigs);
+
+ /**
+ * Get the properties associated with the given description, with the given importedConfigTypes, via the given exportedProperties.
+ *
+ * @param description the container type description under consideration.
+ * @param importedConfigs the imported config types for the given properties. Will not be null, and
+ * should be the same values as returned from {@link #getImportedConfigs(ContainerTypeDescription, String[])}.
+ * @param exportedProperties the properties from the exported service. Will not be null.
+ * @return Dictionary that has all of the properties for the importedConfigTypes. May be null if
+ * no properties are associated with the given description, importedConfigTypes, exportedProperties.
+ */
+ public Dictionary getPropertiesForImportedConfigs(ContainerTypeDescription description, String[] importedConfigs, Dictionary exportedProperties);
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/BooleanCallback.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/BooleanCallback.java
new file mode 100644
index 0000000000..dc4e5f3b26
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/BooleanCallback.java
@@ -0,0 +1,112 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.security;
+
+/**
+ * Callback that handles Boolean types
+ *
+ */
+public class BooleanCallback implements Callback, java.io.Serializable {
+
+ private static final long serialVersionUID = 8660509222691671868L;
+
+ private String prompt;
+
+ private boolean defaultValue;
+
+ private boolean value;
+
+ /**
+ * Construct a BooleanCallback with a prompt.
+ *
+ * prompt is null or if prompt
+ * has a length of 0.
+ */
+ public BooleanCallback(String prompt) {
+ if (prompt == null)
+ throw new IllegalArgumentException("Prompt cannot be null"); //$NON-NLS-1$
+ this.prompt = prompt;
+ }
+
+ /**
+ * Construct a NameCallback with a prompt and default name.
+ *
+ * prompt is null.
+ */
+ public BooleanCallback(String prompt, boolean defaultValue) {
+ if (prompt == null)
+ throw new IllegalArgumentException("Prompt cannot be null"); //$NON-NLS-1$
+
+ this.prompt = prompt;
+ this.defaultValue = defaultValue;
+ }
+
+ /**
+ * Get the prompt.
+ *
+ * @return the prompt value.
+ */
+ public String getPrompt() {
+ return prompt;
+ }
+
+ /**
+ * Get the default value.
+ *
+ * @return the default value, or null if this BooleanCallback was
+ * not instantiated with a defaultValue.
+ */
+ public boolean getDefaultValue() {
+ return defaultValue;
+ }
+
+ /**
+ * Set the retrieved name.
+ *
+ * @param val
+ * the retrieved value true or false.
+ *
+ * @see #getValue
+ */
+ public void setValue(boolean val) {
+ this.value = val;
+ }
+
+ /**
+ * Get the retrieved value.
+ *
+ * @return the retrieved value true or false.
+ *
+ * @see #setValue
+ */
+ public boolean getValue() {
+ return value;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/Callback.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/Callback.java
new file mode 100644
index 0000000000..3a1fa5c84c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/Callback.java
@@ -0,0 +1,16 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.security;
+
+public interface Callback {
+ // no method defined on this interface
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/CallbackHandler.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/CallbackHandler.java
new file mode 100644
index 0000000000..b04a7c4c62
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/CallbackHandler.java
@@ -0,0 +1,18 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.security;
+
+public interface CallbackHandler {
+
+ void handle(Callback[] callbacks) throws java.io.IOException, UnsupportedCallbackException;
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/ConnectContextFactory.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/ConnectContextFactory.java
new file mode 100644
index 0000000000..053e0c2347
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/ConnectContextFactory.java
@@ -0,0 +1,106 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.security;
+
+import java.io.IOException;
+
+/**
+ * Helper class for creating instances of IConnectContext
+ *
+ */
+public class ConnectContextFactory {
+ private ConnectContextFactory() {
+ super();
+ }
+
+ /**
+ * Create username and password connect context, where username is
+ * represented as a String and password as an Object.
+ *
+ * @param username
+ * the username
+ * @param password
+ * the password
+ * @return IConnectContext for accessing the username and password
+ */
+ public static IConnectContext createUsernamePasswordConnectContext(final String username, final Object password) {
+ return new IConnectContext() {
+ public CallbackHandler getCallbackHandler() {
+ return new CallbackHandler() {
+ /**
+ * @param callbacks
+ * @throws IOException not thrown by this implementation.
+ * @throws UnsupportedCallbackException not thrown by this implementation.
+ */
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+ if (callbacks == null)
+ return;
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof NameCallback) {
+ NameCallback ncb = (NameCallback) callbacks[i];
+ ncb.setName(username);
+ } else if (callbacks[i] instanceof ObjectCallback) {
+ ObjectCallback ocb = (ObjectCallback) callbacks[i];
+ ocb.setObject(password);
+ } else if (callbacks[i] instanceof PasswordCallback && password instanceof String) {
+ PasswordCallback pc = (PasswordCallback) callbacks[i];
+ pc.setPassword((String) password);
+ } else if (callbacks[i] instanceof PassphraseCallback && password instanceof String) {
+ PassphraseCallback pc = (PassphraseCallback) callbacks[i];
+ pc.setPassphrase((String) password);
+ }
+ }
+ }
+ };
+ }
+ };
+ }
+
+ /**
+ * Create password connect context, where password is represented as a
+ * String
+ *
+ * @param password
+ * the password to use
+ * @return IConnectContext for accessing the given password
+ */
+ public static IConnectContext createPasswordConnectContext(final String password) {
+ return new IConnectContext() {
+ public CallbackHandler getCallbackHandler() {
+ return new CallbackHandler() {
+ /**
+ * @param callbacks
+ * @throws IOException not thrown by this implementation.
+ * @throws UnsupportedCallbackException not thrown by this implementation.
+ */
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+ if (callbacks == null)
+ return;
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof ObjectCallback) {
+ ObjectCallback ocb = (ObjectCallback) callbacks[i];
+ ocb.setObject(password);
+ } else if (callbacks[i] instanceof PasswordCallback) {
+ PasswordCallback pc = (PasswordCallback) callbacks[i];
+ pc.setPassword(password);
+ } else if (callbacks[i] instanceof PassphraseCallback) {
+ PassphraseCallback pc = (PassphraseCallback) callbacks[i];
+ pc.setPassphrase(password);
+ }
+ }
+ }
+ };
+ }
+ };
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/ECFSSLContextFactory.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/ECFSSLContextFactory.java
new file mode 100644
index 0000000000..608310d41d
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/ECFSSLContextFactory.java
@@ -0,0 +1,111 @@
+/****************************************************************************
+ * Copyright (c) 2024 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.security;
+
+import java.security.*;
+import java.util.Optional;
+import javax.net.ssl.SSLContext;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ecf.internal.core.identity.Activator;
+import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * @since 3.12
+ */
+public class ECFSSLContextFactory implements SSLContextFactory {
+
+ private ServiceTrackerNameCallback with a prompt.
+ *
+ * @param prompt
+ * the prompt used to request the name.
+ *
+ * @exception IllegalArgumentException
+ * if prompt is null.
+ */
+ public NameCallback(String prompt) {
+ if (prompt == null)
+ throw new IllegalArgumentException("Prompt cannot be null"); //$NON-NLS-1$
+ this.prompt = prompt;
+ }
+
+ /**
+ * Construct a NameCallback with a prompt and default name.
+ *
+ * prompt is null.
+ */
+ public NameCallback(String prompt, String defaultName) {
+ if (prompt == null)
+ throw new IllegalArgumentException("Prompt cannot be null"); //$NON-NLS-1$
+ this.prompt = prompt;
+ this.defaultName = defaultName;
+ }
+
+ /**
+ * Get the prompt.
+ *
+ * NameCallback was
+ * not instantiated with a defaultName.
+ */
+ public String getDefaultName() {
+ return defaultName;
+ }
+
+ /**
+ * Set the retrieved name.
+ *
+ * PassphraseCallback with a prompt.
+ *
+ * @param prompt
+ * the prompt used to request the passphrase.
+ *
+ * @exception IllegalArgumentException
+ * if prompt is null.
+ */
+ public PassphraseCallback(String prompt) {
+ if (prompt == null)
+ throw new IllegalArgumentException("Prompt cannot be null"); //$NON-NLS-1$
+ this.prompt = prompt;
+ }
+
+ /**
+ * Construct a PassphraseCallback with a prompt and default passphrase.
+ *
+ * prompt is null.
+ */
+ public PassphraseCallback(String prompt, String defaultPassphrase) {
+ if (prompt == null)
+ throw new IllegalArgumentException("Prompt cannot be null"); //$NON-NLS-1$
+ this.prompt = prompt;
+ this.defaultPassphrase = defaultPassphrase;
+ }
+
+ /**
+ * Get the prompt.
+ *
+ * null if this PassphraseCallback was
+ * not instantiated with a defaultPassphrase.
+ */
+ public String getDefaultPassphrase() {
+ return defaultPassphrase;
+ }
+
+ /**
+ * Set the retrieved passphrase.
+ *
+ * PasswordCallback with a prompt.
+ *
+ * @param prompt
+ * the prompt used to request the name.
+ *
+ * @exception IllegalArgumentException
+ * if prompt is null.
+ */
+ public PasswordCallback(String prompt) {
+ if (prompt == null)
+ throw new IllegalArgumentException("Prompt cannot be null"); //$NON-NLS-1$
+ this.prompt = prompt;
+ }
+
+ /**
+ * Construct a PasswordCallback with a prompt and default password.
+ *
+ * prompt is null.
+ */
+ public PasswordCallback(String prompt, String defaultPassword) {
+ if (prompt == null)
+ throw new IllegalArgumentException("Prompt cannot be null"); //$NON-NLS-1$
+ this.prompt = prompt;
+ this.defaultPassword = defaultPassword;
+ }
+
+ /**
+ * Get the prompt.
+ *
+ * null if this PasswordCallback was
+ * not instantiated with a defaultPassword.
+ */
+ public String getDefaultPassword() {
+ return defaultPassword;
+ }
+
+ /**
+ * Set the retrieved password.
+ *
+ *
+ * NOTE: Rather than the using the {@link #SSLContext.setDefault SSLContext.setDefault(SSLContext)}
+ * to set the default SSLContext as described in the SSLContext.getDefault() javadocs, the default for the implementer is set upon construction of the service instance.
+ */
+ SSLContext getDefault() throws NoSuchAlgorithmException, NoSuchProviderException;
+
+ /**
+ * See SSLContext.getInstance(String protocol)
+ */
+ SSLContext getInstance(String protocol) throws NoSuchAlgorithmException, NoSuchProviderException;
+
+ /**
+ * See SSLContext.getInstance(String protocol, String provider)
+ */
+ SSLContext getInstance(String protocol, String providerName) throws NoSuchAlgorithmException, NoSuchProviderException;
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/UnsupportedCallbackException.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/UnsupportedCallbackException.java
new file mode 100644
index 0000000000..5a2055e3cc
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/security/UnsupportedCallbackException.java
@@ -0,0 +1,64 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.security;
+
+public class UnsupportedCallbackException extends Exception {
+
+ private static final long serialVersionUID = -1821878324884011143L;
+
+ private Callback callback;
+
+ /**
+ * Constructs a UnsupportedCallbackException with no detail
+ * message.
+ *
+ * Callback.
+ */
+ public UnsupportedCallbackException(Callback callback) {
+ super();
+ this.callback = callback;
+ }
+
+ /**
+ * Constructs a UnsupportedCallbackException with the specified detail
+ * message. A detail message is a String that describes this particular
+ * exception.
+ *
+ * Callback.
+ * Callback.
+ *
+ * Callback.
+ */
+ public Callback getCallback() {
+ return callback;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/start/ECFStartJob.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/start/ECFStartJob.java
new file mode 100644
index 0000000000..a0ce785dd5
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/start/ECFStartJob.java
@@ -0,0 +1,35 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.start;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.jobs.Job;
+
+/**
+ * Start job for running extensions of the org.eclipse.ecf.start extension point
+ *
+ */
+public class ECFStartJob extends Job {
+
+ IECFStart start;
+
+ public ECFStartJob(String name, IECFStart start) {
+ super(name);
+ this.start = start;
+ }
+
+ protected IStatus run(IProgressMonitor monitor) {
+ return start.run(monitor);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/start/IECFStart.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/start/IECFStart.java
new file mode 100644
index 0000000000..8fdbc05539
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/start/IECFStart.java
@@ -0,0 +1,30 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.start;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ * Interface that must be implemented by extensions of the org.eclipse.ecf.start
+ * extension point. Such extensions will have their start method called by a new
+ * Job upon ECF startup.
+ */
+public interface IECFStart {
+ /**
+ * Run some startup task.
+ * @param monitor
+ *
+ * @return IStatus the status of the start
+ */
+ public IStatus run(IProgressMonitor monitor);
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/status/SerializableMultiStatus.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/status/SerializableMultiStatus.java
new file mode 100644
index 0000000000..f095dd8add
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/status/SerializableMultiStatus.java
@@ -0,0 +1,165 @@
+/****************************************************************************
+ * Copyright (c) 2008 EclipseSource and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * EclipseSource - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.status;
+
+import org.eclipse.core.runtime.*;
+
+/**
+ * @since 3.2
+ */
+public class SerializableMultiStatus extends SerializableStatus {
+
+ private static final long serialVersionUID = 2971900808938367039L;
+ /**
+ * List of child statuses.
+ */
+ private IStatus[] children = new IStatus[0];
+
+ public SerializableMultiStatus(IStatus status) {
+ this(status.getPlugin(), status.getCode(), status.getMessage(), status.getException());
+ IStatus[] childs = status.getChildren();
+ if (childs != null) {
+ for (int i = 0; i < childs.length; i++) {
+ if (childs[i].isMultiStatus()) {
+ add(new SerializableMultiStatus(childs[i]));
+ } else {
+ add(new SerializableStatus(childs[i]));
+ }
+ }
+ }
+ }
+
+ public SerializableMultiStatus(MultiStatus multiStatus) {
+ this(multiStatus.getPlugin(), multiStatus.getCode(), multiStatus.getMessage(), multiStatus.getException());
+ IStatus[] childs = multiStatus.getChildren();
+ if (childs != null) {
+ for (int i = 0; i < childs.length; i++) {
+ if (childs[i].isMultiStatus()) {
+ add(new SerializableMultiStatus(childs[i]));
+ } else {
+ add(new SerializableStatus(childs[i]));
+ }
+ }
+ }
+ }
+
+ public SerializableMultiStatus(String pluginId, int code, IStatus[] newChildren, String message, Throwable exception) {
+ this(pluginId, code, message, exception);
+ Assert.isLegal(newChildren != null);
+ int maxSeverity = getSeverity();
+ if (newChildren != null) {
+ for (int i = 0; i < newChildren.length; i++) {
+ Assert.isLegal(newChildren[i] != null);
+ int severity = newChildren[i].getSeverity();
+ if (severity > maxSeverity)
+ maxSeverity = severity;
+ }
+ this.children = new IStatus[newChildren.length];
+ System.arraycopy(newChildren, 0, this.children, 0, newChildren.length);
+ }
+ setSeverity(maxSeverity);
+ }
+
+ public SerializableMultiStatus(String pluginId, int code, String message, Throwable exception) {
+ super(OK, pluginId, code, message, exception);
+ }
+
+ /**
+ * Adds the given status to this multi-status.
+ *
+ * @param status
+ * the new child status
+ */
+ public void add(SerializableStatus status) {
+ Assert.isLegal(status != null);
+ IStatus[] result = new IStatus[children.length + 1];
+ System.arraycopy(children, 0, result, 0, children.length);
+ result[result.length - 1] = status;
+ children = result;
+ int newSev = status.getSeverity();
+ if (newSev > getSeverity()) {
+ setSeverity(newSev);
+ }
+ }
+
+ /**
+ * Adds all of the children of the given status to this multi-status. Does
+ * nothing if the given status has no children (which includes the case
+ * where it is not a multi-status).
+ *
+ * @param status
+ * the status whose children are to be added to this one
+ */
+ public void addAll(SerializableStatus status) {
+ Assert.isLegal(status != null);
+ SerializableStatus[] statuses = (SerializableStatus[]) status.getChildren();
+ for (int i = 0; i < statuses.length; i++) {
+ add(statuses[i]);
+ }
+ }
+
+ /*
+ * (Intentionally not javadoc'd) Implements the corresponding method on
+ * IStatus.
+ */
+ public IStatus[] getChildren() {
+ return children;
+ }
+
+ /*
+ * (Intentionally not javadoc'd) Implements the corresponding method on
+ * IStatus.
+ */
+ public boolean isMultiStatus() {
+ return true;
+ }
+
+ /**
+ * Merges the given status into this multi-status. Equivalent to
+ * add(status) if the given status is not a multi-status.
+ * Equivalent to addAll(status) if the given status is a
+ * multi-status.
+ *
+ * @param status
+ * the status to merge into this one
+ * @see #add(SerializableStatus)
+ * @see #addAll(SerializableStatus)
+ */
+ public void merge(SerializableStatus status) {
+ Assert.isLegal(status != null);
+ if (!status.isMultiStatus()) {
+ add(status);
+ } else {
+ addAll(status);
+ }
+ }
+
+ /**
+ * Returns a string representation of the status, suitable for debugging
+ * purposes only.
+ * @return String
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer(super.toString());
+ buf.append(" children=["); //$NON-NLS-1$
+ for (int i = 0; i < children.length; i++) {
+ if (i != 0) {
+ buf.append(" "); //$NON-NLS-1$
+ }
+ buf.append(children[i].toString());
+ }
+ buf.append("]"); //$NON-NLS-1$
+ return buf.toString();
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/status/SerializableStatus.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/status/SerializableStatus.java
new file mode 100644
index 0000000000..b60075d042
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/status/SerializableStatus.java
@@ -0,0 +1,289 @@
+/****************************************************************************
+ * Copyright (c) 2008 EclipseSource and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * EclipseSource - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.status;
+
+import java.io.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.ecf.internal.core.ECFPlugin;
+
+/**
+ * @since 3.2
+ */
+public class SerializableStatus implements IStatus, Serializable {
+
+ private static final long serialVersionUID = -1874392357776889683L;
+
+ public static final IStatus OK_STATUS = new SerializableStatus(OK, ECFPlugin.PLUGIN_ID, OK, "ok", null); //$NON-NLS-1$
+ public static final IStatus CANCEL_STATUS = new SerializableStatus(CANCEL, ECFPlugin.PLUGIN_ID, 1, "", null); //$NON-NLS-1$
+
+ /**
+ * The severity. One of
+ *
+ *
+ */
+ private int severity = OK;
+
+ /**
+ * Unique identifier of plug-in.
+ */
+ private String pluginId;
+
+ /**
+ * Plug-in-specific status code.
+ */
+ private int code;
+
+ /**
+ * Message, localized to the current locale.
+ */
+ private String message;
+
+ /**
+ * Wrapped exception, or CANCELERRORWARNINGINFOOK (0)null if none.
+ */
+ private Throwable exception = null;
+
+ /**
+ * Constant to avoid generating garbage.
+ */
+ private static final IStatus[] theEmptyStatusArray = new IStatus[0];
+
+ public SerializableStatus(IStatus status) {
+ setSeverity(status.getSeverity());
+ setPlugin(status.getPlugin());
+ setCode(status.getCode());
+ setMessage(status.getMessage());
+ setException(status.getException());
+ }
+
+ public SerializableStatus(int severity, String pluginId, int code, String message, Throwable exception) {
+ setSeverity(severity);
+ setPlugin(pluginId);
+ setCode(code);
+ setMessage(message);
+ setException(exception);
+ }
+
+ public SerializableStatus(int severity, String pluginId, String message, Throwable exception) {
+ setSeverity(severity);
+ setPlugin(pluginId);
+ setMessage(message);
+ setException(exception);
+ setCode(OK);
+ }
+
+ public SerializableStatus(int severity, String pluginId, String message) {
+ setSeverity(severity);
+ setPlugin(pluginId);
+ setMessage(message);
+ setCode(OK);
+ setException(null);
+ }
+
+ /*
+ * (Intentionally not javadoc'd) Implements the corresponding method on
+ * IStatus.
+ */
+ public IStatus[] getChildren() {
+ return theEmptyStatusArray;
+ }
+
+ /*
+ * (Intentionally not javadoc'd) Implements the corresponding method on
+ * IStatus.
+ */
+ public int getCode() {
+ return code;
+ }
+
+ /*
+ * (Intentionally not javadoc'd) Implements the corresponding method on
+ * IStatus.
+ */
+ public Throwable getException() {
+ return exception;
+ }
+
+ /*
+ * (Intentionally not javadoc'd) Implements the corresponding method on
+ * IStatus.
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ /*
+ * (Intentionally not javadoc'd) Implements the corresponding method on
+ * IStatus.
+ */
+ public String getPlugin() {
+ return pluginId;
+ }
+
+ /*
+ * (Intentionally not javadoc'd) Implements the corresponding method on
+ * IStatus.
+ */
+ public int getSeverity() {
+ return severity;
+ }
+
+ /*
+ * (Intentionally not javadoc'd) Implements the corresponding method on
+ * IStatus.
+ */
+ public boolean isMultiStatus() {
+ return false;
+ }
+
+ /*
+ * (Intentionally not javadoc'd) Implements the corresponding method on
+ * IStatus.
+ */
+ public boolean isOK() {
+ return severity == OK;
+ }
+
+ /*
+ * (Intentionally not javadoc'd) Implements the corresponding method on
+ * IStatus.
+ */
+ public boolean matches(int severityMask) {
+ return (severity & severityMask) != 0;
+ }
+
+ /**
+ * Sets the status code.
+ *
+ * @param code
+ * the plug-in-specific status code, or OK
+ */
+ protected void setCode(int code) {
+ this.code = code;
+ }
+
+ /**
+ * Sets the exception.
+ *
+ * @param exception
+ * a low-level exception, or null if not applicable
+ */
+ protected void setException(Throwable exception) {
+ // null is never serializable (https://bugs.eclipse.org/328772)
+ if (exception != null)
+ this.exception = checkForSerializable(exception);
+ }
+
+ private Throwable checkForSerializable(Throwable exception2) {
+ ObjectOutputStream oos = null;
+ try {
+ oos = new ObjectOutputStream(new ByteArrayOutputStream());
+ oos.writeObject(exception2);
+ } catch (IOException e) {
+ ECFPlugin.getDefault().log(new Status(IStatus.WARNING, ECFPlugin.PLUGIN_ID, IStatus.WARNING, "Exception " + exception2 + " could not be serialized for SerializableStatus", e)); //$NON-NLS-1$ //$NON-NLS-2$
+ // In this case, we'll create a new exception that can be serialized
+ return createNewExceptionFor(exception2);
+ } finally {
+ try {
+ if (oos != null)
+ oos.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ return exception2;
+ }
+
+ private Throwable createNewExceptionFor(Throwable exception2) {
+ Exception re = new Exception(exception2.getMessage());
+ // setStackTrace not in Foundation 1.1 as per
+ // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=261781
+ // re.setStackTrace(exception2.getStackTrace());
+ return re;
+ }
+
+ /**
+ * Sets the message. If null is passed, message is set to an empty string.
+ *
+ * @param message
+ * a human-readable message, localized to the current locale
+ */
+ protected void setMessage(String message) {
+ if (message == null)
+ this.message = ""; //$NON-NLS-1$
+ else
+ this.message = message;
+ }
+
+ /**
+ * Sets the plug-in id.
+ *
+ * @param pluginId
+ * the unique identifier of the relevant plug-in
+ */
+ protected void setPlugin(String pluginId) {
+ Assert.isLegal(pluginId != null && pluginId.length() > 0);
+ this.pluginId = pluginId;
+ }
+
+ /**
+ * Sets the severity.
+ *
+ * @param severity
+ * the severity; one of OK, ERROR,
+ * INFO, WARNING, or
+ * CANCEL
+ */
+ protected void setSeverity(int severity) {
+ Assert.isLegal(severity == OK || severity == ERROR || severity == WARNING || severity == INFO || severity == CANCEL);
+ this.severity = severity;
+ }
+
+ /**
+ * Returns a string representation of the status, suitable for debugging
+ * purposes only.
+ * @return String
+ */
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("SerializableStatus "); //$NON-NLS-1$
+ if (severity == OK) {
+ buf.append("OK"); //$NON-NLS-1$
+ } else if (severity == ERROR) {
+ buf.append("ERROR"); //$NON-NLS-1$
+ } else if (severity == WARNING) {
+ buf.append("WARNING"); //$NON-NLS-1$
+ } else if (severity == INFO) {
+ buf.append("INFO"); //$NON-NLS-1$
+ } else if (severity == CANCEL) {
+ buf.append("CANCEL"); //$NON-NLS-1$
+ } else {
+ buf.append("severity="); //$NON-NLS-1$
+ buf.append(severity);
+ }
+ buf.append(": "); //$NON-NLS-1$
+ buf.append(pluginId);
+ buf.append(" code="); //$NON-NLS-1$
+ buf.append(code);
+ buf.append(' ');
+ buf.append(message);
+ buf.append(' ');
+ buf.append(exception);
+ return buf.toString();
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/user/IUser.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/user/IUser.java
new file mode 100644
index 0000000000..e8aed6dd8c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/user/IUser.java
@@ -0,0 +1,46 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.user;
+
+import java.io.Serializable;
+import java.util.Map;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.ecf.core.identity.IIdentifiable;
+
+/**
+ * Interface for arbitrary ECF system user. Instances represent a user within
+ * ECF providers and/or clients.
+ */
+public interface IUser extends IIdentifiable, Serializable, IAdaptable {
+ /**
+ * Get basic name for user. Will not return null.
+ * @return String name
+ */
+ public String getName();
+
+ /**
+ * Get nick name for user.
+ *
+ * @return String the user's nickname. May be null if user
+ * has no nickname.
+ */
+ public String getNickname();
+
+ /**
+ * Get map of properties associated with this user. May be null.
+ *
+ * @return Map properties
+ */
+ public Map getProperties();
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/user/User.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/user/User.java
new file mode 100644
index 0000000000..7330432c73
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/user/User.java
@@ -0,0 +1,111 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.user;
+
+import java.util.Map;
+import org.eclipse.core.runtime.IAdapterManager;
+import org.eclipse.ecf.core.identity.ID;
+import org.eclipse.ecf.internal.core.ECFPlugin;
+
+public class User implements IUser {
+
+ private static final long serialVersionUID = 3978709484518586169L;
+
+ protected ID id;
+
+ protected String name;
+
+ protected String nickname;
+
+ protected Map properties;
+
+ public User(ID userID) {
+ this(userID, userID.getName());
+ }
+
+ public User(ID userID, String name) {
+ this(userID, name, null);
+ }
+
+ public User(ID userID, String name, Map properties) {
+ this(userID, name, null, properties);
+ }
+
+ public User(ID userID, String name, String nickname, Map properties) {
+ this.id = userID;
+ this.name = name;
+ this.nickname = nickname;
+ this.properties = properties;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.user.IUser#getProperties()
+ */
+ public Map getProperties() {
+ return properties;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.IIdentifiable#getID()
+ */
+ public ID getID() {
+ return id;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.core.user.IUser#getName()
+ */
+ public String getName() {
+ return name;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.core.user.IUser#getNickname()
+ */
+ public String getNickname() {
+ return nickname;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setNickname(String nickname) {
+ this.nickname = nickname;
+ }
+
+ public
+ * The result must NOT be used to log a CoreException (e.g.,
+ * using yourPlugin.getLog().log(status);), since that code
+ * pattern hides the original stacktrace. Instead, create a new
+ * {@link Status} with your plug-in ID and this CoreException,
+ * and log that new status.
+ * null.
+ * @return boolean true if the given containerToMatch fulfills some
+ * implementation-dependent criteria. false if not.
+ */
+ public boolean match(IContainer containerToMatch);
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/IDFactoryTracker.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/IDFactoryTracker.java
new file mode 100644
index 0000000000..333c9fa720
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/IDFactoryTracker.java
@@ -0,0 +1,38 @@
+/****************************************************************************
+ * Copyright (c) 2009 EclipseSource and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * EclipseSource - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.util;
+
+import org.eclipse.ecf.core.identity.IIDFactory;
+import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * Service tracker customized to handle tracking the ECF id factory service
+ * (singleton).
+ *
+ * @since 3.1
+ *
+ */
+@SuppressWarnings("rawtypes")
+public class IDFactoryTracker extends ServiceTracker {
+
+ @SuppressWarnings("unchecked")
+ public IDFactoryTracker(BundleContext context) {
+ super(context, IIDFactory.class.getName(), null);
+ }
+
+ public IIDFactory getIDFactory() {
+ return (IIDFactory) getService();
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/IEventProcessor.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/IEventProcessor.java
new file mode 100644
index 0000000000..fd8ba2f0d3
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/IEventProcessor.java
@@ -0,0 +1,32 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.util;
+
+/**
+ * Event processor for processing events in a sequence. If the implementer of this interface
+ * intends to prevent further processing for the given event, then it should return true
+ * to prevent further processing. It should return false to allow further processing of
+ * the given event to continue (e.g. in a chain of event processors)
+ *
+ */
+public interface IEventProcessor {
+ /**
+ * Process given Event
+ *
+ * @param event
+ * the Event to process
+ * @return true if the event has been successfully processed and no further
+ * processing should occur. False if the event should receive
+ * further processing by another event processor (e.g. in a chain)
+ */
+ public boolean processEvent(Event event);
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/IExceptionHandler.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/IExceptionHandler.java
new file mode 100644
index 0000000000..6aa6ce102b
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/IExceptionHandler.java
@@ -0,0 +1,27 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.util;
+
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ * Contract for general exception handler
+ */
+public interface IExceptionHandler {
+
+ /**
+ * Handle given exception
+ * @param exception the exception to handle. If null, no exception occurred.
+ * @return IStatus any status to return as part of asynchronous job. Should not be null.
+ */
+ public IStatus handleException(Throwable exception);
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/LogHelper.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/LogHelper.java
new file mode 100644
index 0000000000..c08b945d98
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/LogHelper.java
@@ -0,0 +1,58 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.core.util;
+
+import java.util.Arrays;
+
+import org.eclipse.core.runtime.IStatus;
+import org.osgi.service.log.LogService;
+
+public class LogHelper {
+
+ public static int getLogCode(IStatus status) {
+ switch (status.getCode()) {
+ case IStatus.CANCEL :
+ return LogService.LOG_INFO;
+ case IStatus.ERROR :
+ return LogService.LOG_ERROR;
+ case IStatus.INFO :
+ return LogService.LOG_INFO;
+ case IStatus.OK :
+ return LogService.LOG_INFO;
+ case IStatus.WARNING :
+ return LogService.LOG_WARNING;
+ default :
+ return IStatus.INFO;
+ }
+ }
+
+ /**
+ * @param status
+ * @return String the string version of the status
+ */
+ public static String getLogMessage(IStatus status) {
+ if (status == null)
+ return ""; //$NON-NLS-1$
+ StringBuilder buf = new StringBuilder(status.getClass().getName() + '[');
+ buf.append("plugin=").append(status.getPlugin()); //$NON-NLS-1$
+ buf.append(";code=").append(status.getCode()); //$NON-NLS-1$
+ buf.append(";message=").append(status.getMessage()); //$NON-NLS-1$
+ buf.append(";severity").append(status.getSeverity()); //$NON-NLS-1$
+ buf.append(";exception=").append(status.getException()); //$NON-NLS-1$
+ buf.append(";children=").append(Arrays.asList(status.getChildren())) //$NON-NLS-1$
+ .append(']');
+ return buf.toString();
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/OSGIObjectInputStream.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/OSGIObjectInputStream.java
new file mode 100644
index 0000000000..c2057b6deb
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/OSGIObjectInputStream.java
@@ -0,0 +1,446 @@
+/****************************************************************************
+ * Copyright (c) 2018, 2020 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.util;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+import org.osgi.service.log.LogService;
+
+/**
+ * @since 3.9
+ */
+public class OSGIObjectInputStream extends ObjectInputStream implements OSGIObjectStreamConstants {
+
+ protected ObjectInputStream in;
+ protected final Bundle b;
+ protected LogService logger;
+
+ /**
+ * @since 3.10
+ */
+ ClassLoader classLoader;
+
+ class ReplaceableObjectInputStream extends ObjectInputStream {
+ public ReplaceableObjectInputStream(InputStream ins) throws IOException {
+ super(ins);
+ enableResolveObject(true);
+ }
+
+ @Override
+ protected Object resolveObject(Object obj) throws IOException {
+ if (obj instanceof SerVersion) {
+ return ((SerVersion) obj).toVersion();
+ }
+ if (obj instanceof SerDTO) {
+ SerDTO serDTO = (SerDTO) obj;
+ String className = serDTO.getClassname();
+ Class> clazz = null;
+ try {
+ clazz = loadClass(className);
+ } catch (Exception e) {
+ throw new IOException("Could not load class for instance of SerDTO with className=" + className); //$NON-NLS-1$
+ }
+ return serDTO.readObject(clazz);
+ }
+ return super.resolveObject(obj);
+ }
+
+ @Override
+ protected Class> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
+ try {
+ return loadClass(desc.getName());
+ } catch (Exception e) {
+ return super.resolveClass(desc);
+ }
+ }
+ }
+
+ public OSGIObjectInputStream(Bundle b, InputStream in, LogService logger) throws IOException {
+ super();
+ this.b = b;
+ this.in = new ReplaceableObjectInputStream(in);
+ this.logger = logger;
+ }
+
+ public OSGIObjectInputStream(Bundle b, InputStream in) throws IOException {
+ this(b, in, null);
+ }
+
+ /**
+ * @since 3.10
+ */
+ public void setClassLoader(ClassLoader cl) {
+ this.classLoader = cl;
+ }
+
+ public void setLogService(LogService log) {
+ this.logger = log;
+ }
+
+ @SuppressWarnings("deprecation")
+ protected void trace(String message) {
+ LogService ls = this.logger;
+ if (ls != null) {
+ ls.log(LogService.LOG_DEBUG, message);
+ }
+ }
+
+ protected Class loadClass(String classname) throws ClassNotFoundException {
+ ClassLoader cl = this.classLoader;
+ Bundle bundle = b;
+ if (cl != null) {
+ try {
+ return Class.forName(classname, false, cl);
+ } catch (Exception e) {
+ // Try bundle loading
+ }
+ }
+ return (bundle == null) ? Class.forName(classname) : bundle.loadClass(classname);
+ }
+
+ protected Class> getClassForType(String type) throws ClassNotFoundException {
+ if (type.equals(byte.class.getName()))
+ return byte.class;
+ else if (type.equals(long.class.getName()))
+ return long.class;
+ else if (type.equals(int.class.getName()))
+ return int.class;
+ else if (type.equals(short.class.getName()))
+ return short.class;
+ else if (type.equals(char.class.getName()))
+ return char.class;
+ else if (type.equals(boolean.class.getName()))
+ return boolean.class;
+ else if (type.equals(float.class.getName()))
+ return float.class;
+ else if (type.equals(double.class.getName()))
+ return double.class;
+ else
+ return loadClass(type);
+ }
+
+ protected final Object readObjectOverride() throws IOException, ClassNotFoundException {
+ final byte type = in.readByte();
+ switch (type) {
+ case C_NULL : // null
+ return null;
+ case C_SER : // Serializable
+ return readSerializedObject();
+ case C_VER : // Version
+ return Version.parseVersion(in.readUTF());
+ case C_ARRAY : // Object[]
+ // read array length
+ int ol = in.readInt();
+ // read component type and create array for that component type
+ Class> clazz = getClassForType(in.readUTF());
+ Object oresult = Array.newInstance(clazz, ol);
+ for (int i = 0; i < ol; i++)
+ Array.set(oresult, i, readObjectOverride());
+ return oresult;
+ case C_DICT : // Dictionary
+ Class> dictClazz = loadClass(in.readUTF());
+ Dictionary dict = null;
+ Constructor cons;
+ try {
+ cons = dictClazz.getDeclaredConstructor((Class[]) null);
+ cons.setAccessible(true);
+ dict = (Dictionary) cons.newInstance((Object[]) null);
+ } catch (Exception e) {
+ throw new IOException("Could not create dictionary instance of clazz=" + dictClazz.getName()); //$NON-NLS-1$
+ }
+ int dsize = in.readInt();
+ for (int i = 0; i < dsize; i++) {
+ Object key = readObjectOverride();
+ Object val = readObjectOverride();
+ dict.put(key, val);
+ }
+ return dict;
+ case C_MAP : // Map
+ // read map length
+ int ms = in.readInt();
+ Map mr = new HashMap();
+ for (int i = 0; i < ms; i++) {
+ Object key = readObjectOverride();
+ Object val = readObjectOverride();
+ mr.put(key, val);
+ }
+ return mr;
+ case C_LIST : // List
+ int lsize = in.readInt();
+ List l = new ArrayList(lsize);
+ for (int i = 0; i < lsize; i++)
+ l.add(readObjectOverride());
+ return l;
+ case C_SET : // Set
+ int ssize = in.readInt();
+ Set s = new HashSet(ssize);
+ for (int i = 0; i < ssize; i++)
+ s.add(readObjectOverride());
+ return s;
+ case C_COLL : // Collection
+ int csize = in.readInt();
+ Collection c = new ArrayList(csize);
+ for (int i = 0; i < csize; i++)
+ c.add(readObjectOverride());
+ return c;
+ case C_ITER : // Iterable
+ int isize = in.readInt();
+ List itr = new ArrayList(isize);
+ for (int i = 0; i < isize; i++)
+ itr.add(readObjectOverride());
+ return itr;
+ case C_EXTER : // Externalizable
+ return in.readObject();
+ case C_STRING : // String
+ return in.readUTF();
+ case C_LONG :
+ case C_OLONG :
+ return in.readLong();
+ case C_INT :
+ case C_OINT :
+ return in.readInt();
+ case C_SHORT :
+ case C_OSHORT :
+ return in.readShort();
+ case C_BOOL :
+ case C_OBOOL :
+ return in.readBoolean();
+ case C_BYTE :
+ case C_OBYTE :
+ return in.readByte();
+ case C_CHAR :
+ case C_OCHAR :
+ return in.readChar();
+ case C_DOUBLE :
+ case C_ODOUBLE :
+ return in.readDouble();
+ case C_FLOAT :
+ case C_OFLOAT :
+ return in.readFloat();
+ case C_ENUM :
+ return Enum.valueOf(loadClass(in.readUTF()), in.readUTF());
+ case C_OBJECT :
+ return readNonSerializedObject();
+ default :
+ throw new IOException("Cannot deserialize object with type=" + type); //$NON-NLS-1$
+ }
+ }
+
+ protected Object readExternalizable() throws ClassNotFoundException, IOException {
+ return in.readObject();
+ }
+
+ protected Object readFields(Class> clazz, Object inst) throws IOException {
+ try {
+ int fieldCount = in.readInt();
+ while (fieldCount > -1) {
+ for (int i = 0; i < fieldCount; i++) {
+ final String fieldName = in.readUTF();
+ final Field field = clazz.getDeclaredField(fieldName);
+ final int mod = field.getModifiers();
+ if (!Modifier.isPublic(mod))
+ field.setAccessible(true);
+
+ //
+ final Object value = readObjectOverride();
+ field.set(inst, value);
+ }
+ clazz = clazz.getSuperclass();
+ fieldCount = in.readInt();
+ }
+ return inst;
+ } catch (final Exception e) {
+ IOException t = new IOException("Error while deserializing class=" + clazz.getName() + ": " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
+ t.setStackTrace(e.getStackTrace());
+ throw t;
+ }
+ }
+
+ protected Object createInstance(Class> clazz) throws IOException {
+ try {
+ return clazz.getDeclaredConstructor().newInstance();
+ } catch (Exception e) {
+ throw new IOException("Could create new instance of class=" + clazz.getName() + ". Class must have public no-arg constructor"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+ protected Object readNonSerializedObject() throws IOException, ClassNotFoundException {
+ // read object stream class
+ String className = in.readUTF();
+ trace("readNonSerializedObject " + className); //$NON-NLS-1$
+ Class> clazz = loadClass(className);
+ // create instance
+ Object instance = createInstance(clazz);
+ return readFields(clazz, instance);
+ }
+
+ protected Object readSerializedObject() throws IOException, ClassNotFoundException {
+ return in.readObject();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#read()
+ */
+ public final int read() throws IOException {
+ return in.read();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#read(byte[], int, int)
+ */
+ public final int read(final byte[] buf, final int off, final int len) throws IOException {
+ return in.read(buf, off, len);
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#available()
+ */
+ public final int available() throws IOException {
+ return in.available();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#close()
+ */
+ public final void close() throws IOException {
+ in.close();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#readBoolean()
+ */
+ public final boolean readBoolean() throws IOException {
+ return in.readBoolean();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#readByte()
+ */
+ public final byte readByte() throws IOException {
+ return in.readByte();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#readUnsignedByte()
+ */
+ public final int readUnsignedByte() throws IOException {
+ return in.readUnsignedByte();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#readChar()
+ */
+ public final char readChar() throws IOException {
+ return in.readChar();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#readShort()
+ */
+ public final short readShort() throws IOException {
+ return in.readShort();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#readUnsignedShort()
+ */
+ public final int readUnsignedShort() throws IOException {
+ return in.readUnsignedShort();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#readInt()
+ */
+ public final int readInt() throws IOException {
+ return in.readInt();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#readLong()
+ */
+ public final long readLong() throws IOException {
+ return in.readLong();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#readFloat()
+ */
+ public final float readFloat() throws IOException {
+ return in.readFloat();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#readDouble()
+ */
+ public final double readDouble() throws IOException {
+ return in.readDouble();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#readFully(byte[])
+ */
+ public final void readFully(final byte[] buf) throws IOException {
+ in.readFully(buf);
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#readFully(byte[], int, int)
+ */
+ public final void readFully(final byte[] buf, final int off, final int len) throws IOException {
+ in.readFully(buf, off, len);
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#skipBytes(int)
+ */
+ public final int skipBytes(final int len) throws IOException {
+ return in.skipBytes(len);
+ }
+
+ /**
+ * @return String
+ * @throws IOException
+ * @deprecated
+ */
+ public final String readLine() throws IOException {
+ return in.readLine();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectInputStream#readUTF()
+ */
+ public final String readUTF() throws IOException {
+ return in.readUTF();
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/OSGIObjectOutputStream.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/OSGIObjectOutputStream.java
new file mode 100644
index 0000000000..c6ab29cd74
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/OSGIObjectOutputStream.java
@@ -0,0 +1,446 @@
+/****************************************************************************
+ * Copyright (c) 2018 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.util;
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+import org.osgi.framework.Version;
+import org.osgi.service.log.LogService;
+
+/**
+ * @since 3.9
+ */
+public class OSGIObjectOutputStream extends ObjectOutputStream implements OSGIObjectStreamConstants {
+
+ protected final ObjectOutputStream out;
+ protected LogService logger;
+ protected boolean allowNonSerializable = false;
+
+ class ReplaceableObjectOutputStream extends ObjectOutputStream {
+
+ public ReplaceableObjectOutputStream(OutputStream out) throws IOException {
+ super(out);
+ enableReplaceObject(true);
+ }
+
+ @Override
+ protected Object replaceObject(Object obj) throws IOException {
+ if (obj instanceof Version) {
+ return new SerVersion(((Version) obj));
+ } else if (!(obj instanceof Serializable)) {
+ return new SerDTO(obj);
+ }
+ return super.replaceObject(obj);
+ }
+ }
+
+ public OSGIObjectOutputStream(OutputStream out, boolean allowNonSerializable, LogService log) throws IOException {
+ super();
+ this.out = new ReplaceableObjectOutputStream(out);
+ this.allowNonSerializable = allowNonSerializable;
+ this.logger = log;
+ }
+
+ public OSGIObjectOutputStream(OutputStream out, boolean allowNonSerializable) throws IOException {
+ this(out, allowNonSerializable, null);
+ }
+
+ public OSGIObjectOutputStream(OutputStream out) throws IOException {
+ this(out, false, null);
+ }
+
+ public void setAllowNonSerializable(boolean value) {
+ this.allowNonSerializable = value;
+ }
+
+ public void setLogService(LogService log) {
+ this.logger = log;
+ }
+
+ protected void writeExternalizable(Externalizable obj, Class> clazz) throws IOException {
+ out.writeObject(obj);
+ }
+
+ @SuppressWarnings("deprecation")
+ protected void trace(String message) {
+ LogService ls = this.logger;
+ if (ls != null) {
+ ls.log(LogService.LOG_DEBUG, message);
+ }
+ }
+
+ protected void writeFields(Object obj, Class> clazz) throws IOException {
+ while (clazz != Object.class) {
+ try {
+ final Field[] allFields = clazz.getDeclaredFields();
+ final int allFieldCount = allFields.length;
+ int actualFieldCount = 0;
+ for (int i = 0; i < allFieldCount; i++) {
+ final int mod = allFields[i].getModifiers();
+ if (!(Modifier.isStatic(mod) || Modifier.isTransient(mod)))
+ actualFieldCount++;
+ }
+ // write field count
+ out.writeInt(actualFieldCount);
+ for (int i = 0; i < allFieldCount; i++) {
+ final int mod = allFields[i].getModifiers();
+ if (Modifier.isStatic(mod) || Modifier.isTransient(mod))
+ continue;
+ else if (!Modifier.isPublic(mod))
+ allFields[i].setAccessible(true);
+ Object val = allFields[i].get(obj);
+ // Check to see it's not a circular ref
+ if (val != obj) {
+ // write field name
+ out.writeUTF(allFields[i].getName());
+ // field value
+ writeObjectOverride(val);
+ }
+ }
+ } catch (final Exception e) {
+ throw new NotSerializableException("Exception while serializing " + obj.toString() //$NON-NLS-1$
+ + ":\n" + e.getMessage()); //$NON-NLS-1$
+ }
+ clazz = clazz.getSuperclass();
+ }
+ // Write out a terminator so reader can detect end of object
+ out.writeInt(-1);
+ }
+
+ protected void writeNonSerializable(Object obj, Class> clazz) throws IOException {
+ // write class name
+ out.writeObject(clazz.getName());
+ writeFields(obj, clazz);
+ }
+
+ protected void writeSerializable(Object obj, Class> clazz) throws IOException {
+ out.writeObject(obj);
+ }
+
+ @Override
+ protected void writeObjectOverride(Object obj) throws IOException {
+ if (obj == null) {
+ out.writeByte(C_NULL);
+ return;
+ }
+ Class> clazz = obj.getClass();
+ if (clazz.isArray()) {
+ out.writeByte(C_ARRAY);
+ int len = Array.getLength(obj);
+ // write length
+ out.writeInt(len);
+ // write component type
+ out.writeUTF(clazz.getComponentType().getName());
+ // write out each array entry
+ for (int i = 0; i < len; i++)
+ writeObjectOverride(Array.get(obj, i));
+ return;
+ } else if (obj instanceof Long) {
+ if (clazz.isPrimitive()) {
+ out.writeByte(C_LONG);
+ } else {
+ out.writeByte(C_OLONG);
+ }
+ out.writeLong((Long) obj);
+ return;
+ } else if (obj instanceof Integer) {
+ if (clazz.isPrimitive()) {
+ out.writeByte(C_INT);
+ } else {
+ out.writeByte(C_OINT);
+ }
+ out.writeInt((Integer) obj);
+ return;
+ } else if (obj instanceof Short) {
+ if (clazz.isPrimitive()) {
+ out.writeByte(C_SHORT);
+ } else {
+ out.writeByte(C_OSHORT);
+ }
+ out.writeShort((Short) obj);
+ return;
+ } else if (obj instanceof Boolean) {
+ if (clazz.isPrimitive()) {
+ out.writeByte(C_BOOL);
+ } else {
+ out.writeByte(C_OBOOL);
+ }
+ out.writeBoolean((Boolean) obj);
+ return;
+ } else if (obj instanceof Byte) {
+ if (clazz.isPrimitive()) {
+ out.writeByte(C_BYTE);
+ } else {
+ out.writeByte(C_OBYTE);
+ }
+ out.writeByte((Byte) obj);
+ return;
+ } else if (obj instanceof Character) {
+ if (clazz.isPrimitive()) {
+ out.writeByte(C_CHAR);
+ } else {
+ out.writeByte(C_OCHAR);
+ }
+ out.writeChar((Character) obj);
+ return;
+ } else if (obj instanceof Float) {
+ if (clazz.isPrimitive()) {
+ out.writeByte(C_FLOAT);
+ } else {
+ out.writeByte(C_OFLOAT);
+ }
+ out.writeFloat((Float) obj);
+ return;
+ } else if (obj instanceof Double) {
+ if (clazz.isPrimitive()) {
+ out.writeByte(C_DOUBLE);
+ } else {
+ out.writeByte(C_ODOUBLE);
+ }
+ out.writeDouble((Double) obj);
+ return;
+ } else if (obj instanceof String) {
+ out.writeByte(C_STRING);
+ out.writeUTF((String) obj);
+ return;
+ } else if (obj instanceof Dictionary) {
+ trace("writing dictionary"); //$NON-NLS-1$
+ out.writeByte(C_DICT);
+ out.writeUTF(clazz.getName());
+ Dictionary dict = (Dictionary) obj;
+ // write size
+ int ds = dict.size();
+ out.writeInt(ds);
+ // for each element in Map
+ for (Enumeration e = dict.keys(); e.hasMoreElements();) {
+ Object key = e.nextElement();
+ writeObjectOverride(key);
+ writeObjectOverride(dict.get(key));
+ }
+ return;
+ } else if (obj instanceof Map) {
+ out.writeByte(C_MAP);
+ Map map = (Map) obj;
+ // write size
+ int size = map.size();
+ out.writeInt(size);
+ // for each element in Map
+ for (Object key : map.keySet()) {
+ // Write key
+ writeObjectOverride(key);
+ // Write value
+ writeObjectOverride(map.get(key));
+ }
+ return;
+ } else if (obj instanceof List) {
+ out.writeByte(C_LIST);
+ List list = (List) obj;
+ // write size
+ int size = list.size();
+ out.writeInt(size);
+ // write each element
+ for (Object item : list)
+ writeObjectOverride(item);
+ return;
+ } else if (obj instanceof Set) {
+ out.writeByte(C_SET);
+ Set set = (Set) obj;
+ // write size
+ int size = set.size();
+ out.writeInt(size);
+ // then elements
+ for (Object item : set)
+ writeObjectOverride(item);
+ return;
+ } else if (obj instanceof Collection) {
+ out.writeByte(C_COLL);
+ Collection col = (Collection) obj;
+ // write size
+ int size = col.size();
+ out.writeInt(size);
+ // then elements
+ for (Object item : col)
+ writeObjectOverride(item);
+ return;
+ } else if (obj instanceof Iterable) {
+ out.writeByte(C_ITER);
+ Iterable itr = (Iterable) obj;
+ int size = 0;
+ // Get size
+ for (@SuppressWarnings("unused")
+ Object v : itr)
+ size++;
+ // write size
+ out.writeInt(size);
+ // write elements
+ for (Object item : itr)
+ writeObjectOverride(item);
+ return;
+ } else if (obj instanceof Enum) {
+ out.writeByte(C_ENUM);
+ out.writeUTF(obj.getClass().getName());
+ out.writeUTF(((Enum) obj).name());
+ return;
+ }
+ if (obj instanceof Externalizable) {
+ out.writeByte(C_EXTER);
+ writeExternalizable((Externalizable) obj, clazz);
+ } else if (obj instanceof Serializable) {
+ out.writeByte(C_SER);
+ writeSerializable(obj, clazz);
+ return;
+ } else if (obj instanceof Version) {
+ writeObjectOverride(new SerVersion((Version) obj));
+ } else {
+ writeObjectOverride(new SerDTO(obj));
+ return;
+ }
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#write(int)
+ */
+ public final void write(final int val) throws IOException {
+ out.write(val);
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#write(byte[])
+ */
+ public final void write(final byte[] buf) throws IOException {
+ out.write(buf);
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#write(byte[], int, int)
+ */
+ public final void write(final byte[] buf, final int off, final int len) throws IOException {
+ out.write(buf, off, len);
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#flush()
+ */
+ public final void flush() throws IOException {
+ out.flush();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#reset()
+ */
+ public final void reset() throws IOException {
+ out.reset();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#close()
+ */
+ public final void close() throws IOException {
+ out.close();
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#writeBoolean(boolean)
+ */
+ public final void writeBoolean(final boolean val) throws IOException {
+ out.writeBoolean(val);
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#writeByte(int)
+ */
+ public final void writeByte(final int val) throws IOException {
+ out.writeByte(val);
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#writeShort(int)
+ */
+ public final void writeShort(final int val) throws IOException {
+ out.writeShort(val);
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#writeChar(int)
+ */
+ public final void writeChar(final int val) throws IOException {
+ out.writeChar(val);
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#writeInt(int)
+ */
+ public final void writeInt(final int val) throws IOException {
+ out.writeInt(val);
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#writeLong(long)
+ */
+ public final void writeLong(final long val) throws IOException {
+ out.writeLong(val);
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#writeFloat(float)
+ */
+ public final void writeFloat(final float val) throws IOException {
+ out.writeFloat(val);
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#writeDouble(double)
+ */
+ public final void writeDouble(final double val) throws IOException {
+ out.writeDouble(val);
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#writeBytes(java.lang.String)
+ */
+ public final void writeBytes(final String str) throws IOException {
+ out.writeBytes(str);
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#writeChars(java.lang.String)
+ */
+ public final void writeChars(final String str) throws IOException {
+ out.writeChars(str);
+ }
+
+ /**
+ *
+ * @see java.io.ObjectOutputStream#writeUTF(java.lang.String)
+ */
+ public final void writeUTF(final String str) throws IOException {
+ out.writeUTF(str);
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/OSGIObjectStreamConstants.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/OSGIObjectStreamConstants.java
new file mode 100644
index 0000000000..7163854ba0
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/OSGIObjectStreamConstants.java
@@ -0,0 +1,55 @@
+/****************************************************************************
+ * Copyright (c) 2018 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.core.util;
+
+/**
+ * @since 3.9
+ */
+public interface OSGIObjectStreamConstants {
+
+ public static final byte C_NULL = 0; // null
+ public static final byte C_SER = 1; // Serializable
+ public static final byte C_VER = 2; // Version
+ public static final byte C_ARRAY = 3; // array
+ public static final byte C_DTO = 4; // DTO
+ public static final byte C_MAP = 5; // Map
+ public static final byte C_LIST = 6; // List
+ public static final byte C_SET = 7; // Set
+ public static final byte C_COLL = 8; // Collection
+ public static final byte C_ITER = 9; // Iterable
+ public static final byte C_EXTER = 10; // Externalizable
+ public static final byte C_STRING = 11; // String
+ public static final byte C_ENUM = 12; // Enum
+ public static final byte C_OBJECT = 13; // Everything else
+ public static final byte C_DICT = 14; // Dictionary
+
+ // primitive types
+ public static final byte C_LONG = 20; // primitive long
+ public static final byte C_INT = 21; // primitive int
+ public static final byte C_SHORT = 22; // prim short
+ public static final byte C_BOOL = 23; // prim boolean
+ public static final byte C_BYTE = 24; // prim byte
+ public static final byte C_CHAR = 25; // primp character
+ public static final byte C_DOUBLE = 26; // prim double
+ public static final byte C_FLOAT = 27; // prim float
+
+ // simple object types
+ public static final byte C_OLONG = 30; // Long
+ public static final byte C_OINT = 31; // Integer
+ public static final byte C_OSHORT = 32; // Short
+ public static final byte C_OBOOL = 33; // Boolean
+ public static final byte C_OBYTE = 34; // Byte
+ public static final byte C_OCHAR = 35; // Character
+ public static final byte C_ODOUBLE = 36; // Double
+ public static final byte C_OFLOAT = 37; // Float
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/PlatformHelper.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/PlatformHelper.java
new file mode 100644
index 0000000000..b6b8998bd6
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/PlatformHelper.java
@@ -0,0 +1,109 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.core.util;
+
+import java.lang.reflect.Method;
+import org.eclipse.core.runtime.*;
+import org.eclipse.ecf.internal.core.identity.Activator;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Helper class for eliminating direct references to Platform static methods
+ * getAdapterManager and getExtensionRegistry. Note that instead of
+ * Platform.getAdapterManager(), clients can call
+ * PlatformHelper.getAdapterManager(). If this returns null, the Platform class
+ * is not available.
+ */
+public class PlatformHelper {
+
+ @SuppressWarnings("rawtypes")
+ private static Class platformClass = null;
+
+ private static IAdapterManager adapterManagerCache = null;
+
+ private static IExtensionRegistry extensionRegistryCache = null;
+
+ static {
+ Activator a = Activator.getDefault();
+ if (a != null) {
+ try {
+ BundleContext c = a.getBundleContext();
+ if (c != null) {
+ Bundle[] bundles = c.getBundles();
+ Bundle coreRuntime = null;
+ for (Bundle bundle : bundles) {
+ if (bundle.getSymbolicName().equals("org.eclipse.core.runtime")) { //$NON-NLS-1$
+ coreRuntime = bundle;
+ platformClass = coreRuntime.loadClass("org.eclipse.core.runtime.Platform"); //$NON-NLS-1$
+ break;
+ }
+ }
+ }
+ } catch (Exception e) {
+ // Platform not available...just leave platformClass == null and
+ // log
+ // as error
+ try {
+ a.log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, IStatus.WARNING,
+ "Cannot load Platform class", //$NON-NLS-1$
+ e));
+ } catch (Throwable t) {
+ // Should never happen, if does irrecoverable
+ }
+ }
+ }
+ }
+
+ public synchronized static boolean isPlatformAvailable() {
+ return platformClass != null;
+ }
+
+ public synchronized static IAdapterManager getPlatformAdapterManager() {
+ if (adapterManagerCache != null)
+ return adapterManagerCache;
+ if (isPlatformAvailable()) {
+ try {
+ @SuppressWarnings("unchecked")
+ Method m = platformClass.getMethod("getAdapterManager", (Class[]) null); //$NON-NLS-1$
+ adapterManagerCache = (IAdapterManager) m.invoke(null, (Object[]) null);
+ return adapterManagerCache;
+ } catch (Exception e) {
+ Activator.getDefault().log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, IStatus.WARNING,
+ "Cannot get PlatformAdapterManager()", e)); //$NON-NLS-1$
+ return null;
+ }
+ }
+ return null;
+ }
+
+ public synchronized static IExtensionRegistry getExtensionRegistry() {
+ if (extensionRegistryCache != null)
+ return extensionRegistryCache;
+ if (isPlatformAvailable()) {
+ try {
+ @SuppressWarnings("unchecked")
+ Method m = platformClass.getMethod("getExtensionRegistry", (Class[]) null); //$NON-NLS-1$
+ extensionRegistryCache = (IExtensionRegistry) m.invoke(null, (Object[]) null);
+ return extensionRegistryCache;
+ } catch (Exception e) {
+ Activator.getDefault().log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, IStatus.WARNING,
+ "Cannot get PlatformExtensionRegistry()", e)); //$NON-NLS-1$
+ return null;
+ }
+
+ }
+ return null;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/Proxy.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/Proxy.java
new file mode 100644
index 0000000000..8b99e8520d
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/Proxy.java
@@ -0,0 +1,149 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.core.util;
+
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+
+public class Proxy implements Serializable {
+
+ private static final long serialVersionUID = -2481483596779542834L;
+
+ public static class Type implements Serializable {
+
+ private static final long serialVersionUID = 361071073081975271L;
+
+ private static final String DIRECT_NAME = "direct"; //$NON-NLS-1$
+
+ private static final String HTTP_NAME = "http"; //$NON-NLS-1$
+
+ private static final String SOCKS_NAME = "socks"; //$NON-NLS-1$
+
+ private final transient String name;
+
+ protected Type(String name) {
+ this.name = name;
+ }
+
+ public static final Type DIRECT = new Type(DIRECT_NAME);
+
+ public static final Type HTTP = new Type(HTTP_NAME);
+
+ public static final Type SOCKS = new Type(SOCKS_NAME);
+
+ public static Type fromString(String type) {
+ if (type == null)
+ return null;
+ else if (type.equals(DIRECT_NAME))
+ return DIRECT;
+ else if (type.equals(HTTP_NAME))
+ return HTTP;
+ else if (type.equals(SOCKS_NAME))
+ return SOCKS;
+ else
+ return null;
+ }
+
+ public String toString() {
+ return name;
+ }
+
+ // For serialization
+ private static int nextOrdinal = 0;
+
+ private final int ordinal = nextOrdinal++;
+
+ private static final Type[] VALUES = {DIRECT, HTTP, SOCKS};
+
+ /**
+ * @return Object
+ * @throws ObjectStreamException not thrown by this implementation.
+ */
+ Object readResolve() throws ObjectStreamException {
+ return VALUES[ordinal];
+ }
+ }
+
+ ProxyAddress address;
+
+ Type type;
+
+ String username;
+
+ String password;
+
+ public final static Proxy NO_PROXY = new Proxy();
+
+ private Proxy() {
+ this.type = Type.DIRECT;
+ this.address = null;
+ }
+
+ public Proxy(Type type, ProxyAddress address, String username, String password) {
+ this.type = type;
+ this.address = address;
+ this.username = username;
+ this.password = password;
+ }
+
+ public Proxy(Type type, ProxyAddress address) {
+ this(type, address, null, null);
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public ProxyAddress getAddress() {
+ return address;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public boolean hasCredentials() {
+ return (username != null && !username.equals("")); //$NON-NLS-1$
+ }
+
+ public String toString() {
+ if (getType() == Type.DIRECT)
+ return "DIRECT"; //$NON-NLS-1$
+ return getType() + " @ " + getAddress(); //$NON-NLS-1$
+ }
+
+ public final boolean equals(Object obj) {
+ if (obj == null || !(obj instanceof Proxy))
+ return false;
+ Proxy p = (Proxy) obj;
+ if (p.getType() == getType()) {
+ if (getAddress() == null) {
+ return (p.getAddress() == null);
+ }
+ return getAddress().equals(p.getAddress());
+ }
+ return false;
+ }
+
+ public final int hashCode() {
+ if (getAddress() == null)
+ return getType().hashCode();
+ return getType().hashCode() + getAddress().hashCode();
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/ProxyAddress.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/ProxyAddress.java
new file mode 100644
index 0000000000..d393ac1819
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/ProxyAddress.java
@@ -0,0 +1,71 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.core.util;
+
+import java.io.Serializable;
+
+/**
+ * Class to represent an proxy address
+ */
+public class ProxyAddress implements Serializable {
+
+ private static final long serialVersionUID = 9076207407726734246L;
+
+ protected static final int DEFAULT_PORT = -1;
+
+ protected int port = -1;
+ protected String hostname = ""; //$NON-NLS-1$
+
+ public ProxyAddress(String hostname, int port) {
+ this.hostname = (hostname == null) ? "" : hostname; //$NON-NLS-1$
+ this.port = port;
+ }
+
+ public ProxyAddress(String hostname) {
+ this(hostname, DEFAULT_PORT);
+ }
+
+ public String getHostName() {
+ return this.hostname;
+ }
+
+ public int getPort() {
+ return this.port;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj) {
+ if (obj == null || this.hostname == null)
+ return false;
+ if (!(obj instanceof ProxyAddress))
+ return false;
+ ProxyAddress other = (ProxyAddress) obj;
+ return (this.hostname.equals(other.hostname) && this.port == other.port);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ if (this.hostname == null)
+ return super.hashCode();
+ return this.hostname.hashCode() ^ Math.abs(this.port);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/SerDTO.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/SerDTO.java
new file mode 100644
index 0000000000..8768884554
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/SerDTO.java
@@ -0,0 +1,79 @@
+/****************************************************************************
+ * Copyright (c) 2021 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.ecf.core.util;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @since 3.10
+ */
+public class SerDTO implements Serializable {
+
+ private static final long serialVersionUID = -1739849704193630352L;
+ private String className;
+ private Map.
+ * @param target
+ * must not be null.
+ * @return true if the target is contained within the string.
+ */
+ public static boolean contains(String string, String target) {
+ return (string.contains(target));
+ }
+
+ /**
+ * Returns the string resulting from replacing all occurrences of the target
+ * with the replace string. Note that the target matches literally, and this
+ * is not the same behavior as the String.replaceAll, which uses regular
+ * expressions for doing the matching.
+ *
+ * @param string
+ * the start string. Must not be null.
+ * @param target
+ * the target to search for in the start string. Must not be
+ * null.
+ * @param replace
+ * the replacement string to substitute when the target is found.
+ * Must not be null.
+ * @return String result. Will not be null. If target is not
+ * found in the given string, then the result will be the entire
+ * input string.
+ */
+ public static String replaceAll(String string, String target, String replace) {
+ final int index = string.indexOf(target);
+ if (index == -1)
+ return string;
+ return string.substring(0, index) + replace
+ + replaceAll(string.substring(index + target.length()), target, replace);
+ }
+
+ /**
+ * Returns the string resulting from replacing all occurrences of the target
+ * with the replace string. Note that the target matches literally but
+ * ignoring the case, and this is not the same behavior as the
+ * String.replaceAll, which uses regular expressions for doing the matching.
+ *
+ * @param string
+ * the start string. Must not be null.
+ * @param target
+ * the target to search for in the start string. Must not be
+ * null.
+ * @param replace
+ * the replacement string to substitute when the target is found.
+ * Must not be null.
+ * @return String result. Will not be null. If target is not
+ * found in the given string, then the result will be the entire
+ * input string.
+ *
+ * @see StringUtils#replaceAll(String, String, String) but case insensitive
+ * @since 2.1
+ */
+ public static String replaceAllIgnoreCase(String string, String target, String replace) {
+ final int index = string.toLowerCase().indexOf(target.toLowerCase());
+ if (index == -1)
+ return string;
+ return string.substring(0, index) + replace
+ + replaceAllIgnoreCase(string.substring(index + target.length()), target, replace);
+ }
+
+ /**
+ * Returns the string resulting from replacing the first occurrences of the
+ * target with the replace string. Note that the target matches literally,
+ * and this is not the same behavior as the String.replaceAll, which uses
+ * regular expressions for doing the matching.
+ *
+ * @param string
+ * the start string. Must not be null.
+ * @param target
+ * the target to search for in the start string. Must not be
+ * null.
+ * @param replace
+ * the replacement string to substitute when the target is found.
+ * Must not be null.
+ * @return String result. Will not be null. If target is not
+ * found in the given string, then the result will be the entire
+ * input string.
+ *
+ * @since 3.0
+ */
+ public static String replaceFirst(String string, String target, String replace) {
+ final int index = string.indexOf(target);
+ if (index == -1)
+ return string;
+ return string.substring(0, index) + replace + string.substring(index + target.length());
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/SystemLogService.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/SystemLogService.java
new file mode 100644
index 0000000000..636ffbe658
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/core/util/SystemLogService.java
@@ -0,0 +1,125 @@
+/****************************************************************************
+ * Copyright (c) 2007, 2018 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.core.util;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+
+/**
+ *
+ */
+public class SystemLogService implements LogService {
+
+ private static final SimpleDateFormat dateFormat = new SimpleDateFormat("Z yyyy.MM.dd HH:mm:ss:S"); //$NON-NLS-1$
+
+ private final String pluginName;
+
+ public SystemLogService(String pluginName) {
+ this.pluginName = pluginName;
+ }
+
+ private static final String getLogCode(int level) {
+ switch (level) {
+ case LogService.LOG_INFO:
+ return "INFO"; //$NON-NLS-1$
+ case LogService.LOG_ERROR:
+ return "ERROR"; //$NON-NLS-1$
+ case LogService.LOG_DEBUG:
+ return "DEBUG"; //$NON-NLS-1$
+ case LogService.LOG_WARNING:
+ return "WARNING"; //$NON-NLS-1$
+ default:
+ return "UNKNOWN"; //$NON-NLS-1$
+ }
+ }
+
+ private final void doLog(@SuppressWarnings("rawtypes") ServiceReference sr, int level, String message,
+ Throwable t) {
+ final StringBuffer buf = new StringBuffer("[log;"); //$NON-NLS-1$
+ buf.append(dateFormat.format(new Date())).append(";"); //$NON-NLS-1$
+ buf.append(getLogCode(level)).append(";"); //$NON-NLS-1$
+ if (sr != null)
+ buf.append(sr.getBundle().getSymbolicName()).append(";"); //$NON-NLS-1$
+ else
+ buf.append(pluginName).append(";"); //$NON-NLS-1$
+ buf.append(message).append("]"); //$NON-NLS-1$
+ if (t != null) {
+ System.err.println(buf.toString());
+ t.printStackTrace(System.err);
+ } else
+ System.out.println(buf.toString());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.log.LogService#log(int, java.lang.String)
+ */
+ public void log(int level, String message) {
+ log(null, level, message, null);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.log.LogService#log(int, java.lang.String,
+ * java.lang.Throwable)
+ */
+ public void log(int level, String message, Throwable exception) {
+ doLog(null, level, message, exception);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.log.LogService#log(org.osgi.framework.ServiceReference,
+ * int, java.lang.String)
+ */
+ public void log(@SuppressWarnings("rawtypes") ServiceReference sr, int level, String message) {
+ log(sr, level, message, null);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.log.LogService#log(org.osgi.framework.ServiceReference,
+ * int, java.lang.String, java.lang.Throwable)
+ */
+ public void log(@SuppressWarnings("rawtypes") ServiceReference sr, int level, String message, Throwable exception) {
+ doLog(sr, level, message, exception);
+ }
+
+ public org.osgi.service.log.Logger getLogger(String name) {
+ throw new UnsupportedOperationException();
+ }
+
+ public org.osgi.service.log.Logger getLogger(Class> clazz) {
+ throw new UnsupportedOperationException();
+ }
+
+ public
+ * class MyFileTransferJob extends FileTransferJob {
+ * public MyFileTransferJob(String name) {
+ * super(name);
+ * }
+ *
+ * public boolean belongsTo(Object o) {
+ * // insert own logic to decide whether
+ * // this file transfer job should be part
+ * // of a group
+ * //
+ * }
+ * }
+ *
+ * MyFileTransferJob myJob = new MyFileTransferJob("myname");
+ * incomingfiletransfer = event.receive(outputstream,myJob);
+ *
+ * @since 2.0
+ */
+public class FileTransferJob extends Job {
+
+ private IFileTransferRunnable fileTransferRunnable;
+ private IFileTransfer fileTransfer;
+
+ /**
+ * @param name the name for this file transfer job. Should not be null.
+ */
+ public FileTransferJob(String name) {
+ super(name);
+ setSystem(true);
+ }
+
+ public final void setFileTransferRunnable(IFileTransferRunnable fileTransferRunnable) {
+ this.fileTransferRunnable = fileTransferRunnable;
+ }
+
+ /**
+ * @param fileTransfer file transfer instance
+ * @since 3.0
+ */
+ public final void setFileTransfer(IFileTransfer fileTransfer) {
+ this.fileTransfer = fileTransfer;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ protected final IStatus run(IProgressMonitor mntr) {
+ if (this.fileTransferRunnable == null)
+ return new Status(IStatus.ERROR, org.eclipse.ecf.internal.filetransfer.Activator.PLUGIN_ID, IStatus.ERROR, "Runnable cannot be null", null); //$NON-NLS-1$
+ if (this.fileTransfer == null)
+ return new Status(IStatus.ERROR, org.eclipse.ecf.internal.filetransfer.Activator.PLUGIN_ID, IStatus.ERROR, "File transfer member cannot be null", null); //$NON-NLS-1$
+ return this.fileTransferRunnable.performFileTransfer(mntr);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.jobs.Job#canceling()
+ */
+ protected void canceling() {
+ fileTransfer.cancel();
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileRangeSpecification.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileRangeSpecification.java
new file mode 100644
index 0000000000..4a0447c17b
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileRangeSpecification.java
@@ -0,0 +1,74 @@
+/****************************************************************************
+ * Copyright (c) 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer;
+
+/**
+ * An object that describes a file range specification. Object implementations of this
+ * class can be
+ */
+public interface IFileRangeSpecification {
+
+ /**
+ * Get the start position to start from. The position is in bytes, and byte 0 is the first byte
+ * of the file, N-1 is the last position in the file, where N is the length of the file in bytes.
+ * @return the position in the file (in bytes) to start from. If the returned start position is
+ * less than 0, or equal to or greater than N, then it is an invalid range specification and
+ * when used in {@link IRetrieveFileTransferContainerAdapter#sendRetrieveRequest(org.eclipse.ecf.filetransfer.identity.IFileID, IFileRangeSpecification, IFileTransferListener, java.util.Map)} will result in a
+ * {@link InvalidFileRangeSpecificationException}.
+ *
+ * @see IRetrieveFileTransferContainerAdapter#sendRetrieveRequest(org.eclipse.ecf.filetransfer.identity.IFileID, IFileRangeSpecification, IFileTransferListener, java.util.Map)
+ * @see #getEndPosition()
+ */
+ public long getStartPosition();
+
+ /**
+ * Get the end position of transfer range. The position is in bytes, and byte 0 is the first byte
+ * of the file, N-1 is the last position in the file, where N is the length of the file in bytes.
+ * @return the position in the file (in bytes) to indicate the end of range to retrieve. If equal to -1,
+ * then this means that no end position is specified, and the download will continue to the end of file. If gt or eq 0,
+ * but less than the {@link #getStartPosition()} then this range specification is invalid. If greater than or
+ * equal to N (where N is length of the file in bytes), then the remaining part of the given file will
+ * be downloaded. If both {@link #getStartPosition()} and {@link #getEndPosition()} are valid, then
+ * the number of bytes downloaded will be (endPosition - startPosition) + 1. So, for example:
+ *
+ * For a fileLength = 20
+ *
+ * startPosition = 10
+ * endPosition = 19
+ * bytesDownloaded = 10
+ *
+ * startPosition = 0
+ * endPosition = -1
+ * bytesDownloaded = 20
+ *
+ * startPosition = 5
+ * endPosition = 3
+ * invalid range
+ *
+ * startPosition = 5
+ * endPosition = 6
+ * bytesDownloaded = 2
+ *
+ * startPosition = 5
+ * endPosition = -1
+ * bytesDownloaded = 15
+ *
+ *
+ *
+ * @see IRetrieveFileTransferContainerAdapter#sendRetrieveRequest(org.eclipse.ecf.filetransfer.identity.IFileID, IFileRangeSpecification, IFileTransferListener, java.util.Map)
+ * @see #getStartPosition()
+ */
+ public long getEndPosition();
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransfer.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransfer.java
new file mode 100644
index 0000000000..30eb41ea55
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransfer.java
@@ -0,0 +1,97 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.ecf.core.identity.IIdentifiable;
+import org.eclipse.ecf.filetransfer.events.IFileTransferEvent;
+
+/**
+ * File transfer super interface. This interface provides the abstract file
+ * transfer semantics for both {@link IOutgoingFileTransfer} and
+ * {@link IIncomingFileTransfer} transfer sub interfaces.
+ */
+public interface IFileTransfer extends IAdaptable, IIdentifiable {
+ /**
+ * Cancel this file transfer. If file transfer has already been completed,
+ * then this method has no effect. If the file transfer has not been
+ * completed then calling this method will result in an
+ * {@link IFileTransferEvent} being delivered to the
+ * {@link IFileTransferListener} indicating that transfer is done ({@link #isDone()}
+ * returns true), and some exception will be made available
+ *
+ */
+ public void cancel();
+
+ /**
+ * Get the percent complete for this file transfer. The returned value will
+ * be either -1.0, meaning that the underlying provider does not support
+ * reporting percent complete for this file transfer, or a value between 0
+ * and 1 reflecting the percent complete for this file transfer. If 0.0 no
+ * data has been sent, if 1.0, the file transfer is 100 percent complete.
+ *
+ * The value returned from this method should not be used to
+ * determine whether the transfer has completed, as it may not show
+ * completion in the event of an transfer failure. Note that the
+ * {@link #isDone()} method should be consulted to determine if the file
+ * transfer has completed (with or without error).
+ *
+ * @return double percent complete. Returns -1.0 if the underlying provider
+ * does not support reporting percentage complete, or between 0 and
+ * 1 to indicate actual percent complete for this file transfer
+ */
+ public double getPercentComplete();
+
+ /**
+ * Get any exception associated with this file transfer. The value returned
+ * from this method is valid only if {@link #isDone()} method returns true.
+ * If the file transfer completed successfully, {@link #isDone()} will
+ * return true, and this method will return null. If the file transfer
+ * completed unsuccessfully (some exception occurred), then
+ * {@link #isDone()} will return true, and this method will return a
+ * non-null Exception instance that occurred.
+ * null
+ * if transfer completed successfully, non-null if transfer
+ * completed with some exception. Only valid after
+ * {@link #isDone()} returns true.
+ */
+ public Exception getException();
+
+ /**
+ * Return true if this file transfer is done, false if not yet completed.
+ * The file transfer can be completed successfully, or an exception can
+ * occur and the file transfer will have failed. In either case of
+ * successful or unsuccessful transfer, this method will return true when
+ * the file transfer is complete. To determine whether the transfer
+ * completed successfully, it is necessary to also consult the
+ * {@link #getException()} method.
+ *
+ * @return boolean true if file transfer is done, false if file transfer is
+ * still in progress.
+ */
+ public boolean isDone();
+
+ /**
+ * Return resulting file length (in bytes) for this file transfer instance. If the length is not known,
+ * -1 will be returned. Note that if a {@link IFileRangeSpecification} is provided that the returned
+ * file length is the expected file length of just the range retrieved (and not the entire file).
+ *
+ *@return long file length
+ * @since 2.0
+ */
+ public long getFileLength();
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferInfo.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferInfo.java
new file mode 100644
index 0000000000..e08c9a13e9
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferInfo.java
@@ -0,0 +1,64 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer;
+
+import java.io.File;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.ecf.filetransfer.events.IFileTransferRequestEvent;
+
+/**
+ * File transfer information delivered to
+ * {@link IIncomingFileTransferRequestListener} via an event implementing
+ * {@link IFileTransferRequestEvent#getFileTransferInfo()}
+ *
+ */
+public interface IFileTransferInfo extends IAdaptable {
+ /**
+ * Get the file for the proposed file transfer
+ *
+ * @return the proposed file. Will not return null.
+ */
+ public File getFile();
+
+ /**
+ * Get the file size (in bytes).
+ *
+ * @return long file size (in bytes). If file size is unknown, will return -1.
+ */
+ public long getFileSize();
+
+ /**
+ * Get any properties associated with this file transfer. The map keys and
+ * values are assumed to be Strings.
+ *
+ * @return Map of properties associated with this file transfer info. Will
+ * not return null.
+ */
+ public Map getProperties();
+
+ /**
+ * Get any description associated with this file transfer info.
+ *
+ * @return String description. May be null if no description
+ * provided.
+ */
+ public String getDescription();
+
+ /**
+ * Get the mime type string for this file transfer info.
+ *
+ * @return String mime type. May return null if mime type is not known.
+ */
+ public String getMimeType();
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferListener.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferListener.java
new file mode 100644
index 0000000000..7e9961a0fd
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferListener.java
@@ -0,0 +1,51 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer;
+
+import org.eclipse.ecf.filetransfer.events.IFileTransferEvent;
+
+/**
+ * Listener for handling file transfer events. Instances implementing this
+ * interface or sub-interfaces will have their handleTransferEvent called
+ * asynchronously when a given event is received. Implementers must be prepared
+ * to have this method called asynchronously by an arbitrary thread.
+ *
+ *
+ * Display.getDefault().asyncExec(new Runnable() {
+ * public void run() {
+ * ... UI code here
+ * }
+ * });
+ *
+ *
+ * Further, the code in the implementations of these methods should not block
+ * via I/O operations or blocking UI calls.
+ */
+public interface IFileTransferListener {
+ /**
+ * Handle file transfer events
+ *
+ * @param event
+ * the event to be handled. should not be null.
+ */
+ public void handleTransferEvent(IFileTransferEvent event);
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferPausable.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferPausable.java
new file mode 100644
index 0000000000..3e9b553485
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferPausable.java
@@ -0,0 +1,57 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer;
+
+/**
+ * Adapter interface for pausing and resuming IFileTransfer instances that
+ * expose this adapter interface via
+ * {@link IFileTransfer#getAdapter(Class adapter)}. To use this interface,
+ * clients should do the following:
+ *
+ *
+ * IFileTransfer fileTransfer;
+ * IFileTransferPausable pausable = (IFileTransferPausable) fileTransfer.getAdapter(IFileTransferPausable.class);
+ * if (pausable !=null) {
+ * ... use it
+ * } else {
+ * ... does not support pausing
+ * }
+ *
+ *
+ */
+public interface IFileTransferPausable {
+
+ /**
+ * Pause file transfer. Returns true if the associated IFileTransfer is
+ * successfully paused. Returns false if the implementing file transfer
+ * cannot be paused, or transfer has already completed.
+ *
+ * @return boolean true if file transfer successfully paused. False if cannot be
+ * paused, or the transfer has already completed
+ */
+ public boolean pause();
+
+ /**
+ *
+ * @return boolean true if file transfer paused, false if not paused
+ */
+ public boolean isPaused();
+
+ /**
+ * Resume file transfer after having been paused. If successfully resumed,
+ * then returns true. If the associated IFileShare is not already paused, or
+ * has already completed then this method returns false.
+ *
+ * @return boolean true if transfer is successfully resumed, false otherwise
+ */
+ public boolean resume();
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferRateControl.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferRateControl.java
new file mode 100644
index 0000000000..dfd6e5f312
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferRateControl.java
@@ -0,0 +1,51 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer;
+
+/**
+ * Adapter for setting rate control on IFileTransferInfo instances that expose
+ * expose this adapter interface via
+ * {@link IFileTransfer#getAdapter(Class adapter)}. To use this interface,
+ * clients should do the following:
+ *
+ *
+ * IFileTransfer fileTransfer;
+ * IFileTransferRateControl rateController = (IFileTransferRateControl) fileTransfer.getAdapter(IFileTransferRateControl.class);
+ * if (rateController !=null) {
+ * ... use it
+ * } else {
+ * ... does not support rate control
+ * }
+ *
+ *
+ */
+public interface IFileTransferRateControl {
+ /**
+ * Set maximum download speed in bytes/second. Specifying a maximum download
+ * speed of 0 indicates that any exiting rate cap should be removed, and the
+ * transfer should proceed as fast as possible a
+ *
+ * @param maxDownloadSpeed
+ * in bytes/second
+ */
+ public void setMaxDownloadSpeed(long maxDownloadSpeed);
+
+ /**
+ * Set maximum upload speed in bytes/second. Specifying a maximum upload
+ * speed of 0 indicates that any exiting rate cap should be removed, and the
+ * transfer should proceed as fast as possible
+ *
+ * @param maxUploadSpeed
+ * in bytes/second
+ */
+ public void setMaxUploadSpeed(long maxUploadSpeed);
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferRunnable.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferRunnable.java
new file mode 100644
index 0000000000..9770501ce2
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IFileTransferRunnable.java
@@ -0,0 +1,33 @@
+/****************************************************************************
+ * Copyright (c) 2008 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ * Runnable for doing file transfer. Used by {@link FileTransferJob}s.
+ *
+ * @since 2.0
+ */
+public interface IFileTransferRunnable {
+
+ /**
+ * Synchronously perform the actual file transfer.
+ *
+ * @param monitor a progress montior. Will not be null.
+ * @return IStatus a status object indicating the ending status of the file transfer job.
+ */
+ public IStatus performFileTransfer(IProgressMonitor monitor);
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IIncomingFileTransfer.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IIncomingFileTransfer.java
new file mode 100644
index 0000000000..ee46d4dabf
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IIncomingFileTransfer.java
@@ -0,0 +1,68 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer;
+
+import java.util.Date;
+import org.eclipse.ecf.filetransfer.events.IIncomingFileTransferReceiveStartEvent;
+
+/**
+ * Incoming file transfer request. Instance implementing this interface are
+ * provided via calling the
+ * {@link IIncomingFileTransferReceiveStartEvent#receive(java.io.File)} method.
+ *
+ */
+public interface IIncomingFileTransfer extends IFileTransfer {
+ /**
+ * Get number of bytes received so far. If provider does not support
+ * reporting the number of bytes received, will return -1.
+ *
+ * @return long number of bytes received. Returns -1 if provider does not
+ * support reporting of number of bytes received during transfer
+ */
+ public long getBytesReceived();
+
+ /**
+ * Get listener assigned to this incoming file transfer. May be null if no listener
+ * has been provided.
+ *
+ * @return listener the IFileTransferListener provided for this incoming file transfer.
+ */
+ public IFileTransferListener getListener();
+
+ /**
+ * Get file range specification for this incoming file transfer instance. Will return
+ * null if the retrieval is of the entire file.
+ *
+ * @return file range specification for this incoming file transfer instance. Returns
+ * null if the retrieval is of the entire file.
+ */
+ public IFileRangeSpecification getFileRangeSpecification();
+
+ /**
+ * Obtains the name of the remote file if possible. The name will typically but not
+ * necessarily be the same as the leaf part of the path to the remote file.
+ *
+ * @return The name of the remote file or null if no such name can be determined.
+ *
+ * @since 2.0
+ */
+ public String getRemoteFileName();
+
+ /**
+ * Obtains the timestamp that reflects the time when the remote file was last
+ * modified if possible.
+ * @return The time the remote file was last modified or null if that
+ * information was not available.
+ * @since 2.0
+ */
+ public Date getRemoteLastModified();
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IIncomingFileTransferRequestListener.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IIncomingFileTransferRequestListener.java
new file mode 100644
index 0000000000..72439428f5
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IIncomingFileTransferRequestListener.java
@@ -0,0 +1,32 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer;
+
+import org.eclipse.ecf.filetransfer.events.IFileTransferRequestEvent;
+
+/**
+ * Listener for incoming file transfer requests. Instances implementing this
+ * interface are registered via the
+ * {@link ISendFileTransferContainerAdapter#addListener(IIncomingFileTransferRequestListener)}
+ *
+ * @see ISendFileTransferContainerAdapter#addListener(IIncomingFileTransferRequestListener)
+ */
+public interface IIncomingFileTransferRequestListener {
+ /**
+ * Handle file transfer requests when received asynchronously from remotes.
+ *
+ * @param event
+ * the {@link IFileTransferRequestEvent} that represents the file
+ * transfer request. Will not be should not be null.
+ */
+ public void handleFileTransferRequest(IFileTransferRequestEvent event);
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IOutgoingFileTransfer.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IOutgoingFileTransfer.java
new file mode 100644
index 0000000000..3595a575ea
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IOutgoingFileTransfer.java
@@ -0,0 +1,29 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer;
+
+/**
+ * Outgoing file transfer.
+ *
+ */
+public interface IOutgoingFileTransfer extends IFileTransfer {
+ /**
+ * Get the number of bytes sent for this outgoing file transfer. Returns 0
+ * if transfer has not be started, and -1 if underlying provider does not
+ * support reporting number of bytes sent during transfer.
+ *
+ * @return number of bytes sent. Returns 0 if the outgoing file transfer has
+ * not been started, and -1 if provider does not support reporting
+ * of number of bytes received during transfer
+ */
+ public long getBytesSent();
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFile.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFile.java
new file mode 100644
index 0000000000..9f949d7300
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFile.java
@@ -0,0 +1,37 @@
+/****************************************************************************
+ * Copyright (c) 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.ecf.filetransfer.identity.IFileID;
+
+/**
+ * Remote file representation.
+ */
+public interface IRemoteFile extends IAdaptable {
+
+ /**
+ * Get remote file info associated with this remote file.
+ * @return file info. Will not be null.
+ */
+ public IRemoteFileInfo getInfo();
+
+ /**
+ * Get the remote file id associated with this file.
+ * @return the file id associated with this file. Will not be
+ * null.
+ */
+ public IFileID getID();
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileAttributes.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileAttributes.java
new file mode 100644
index 0000000000..1981f0514d
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileAttributes.java
@@ -0,0 +1,52 @@
+/****************************************************************************
+ * Copyright (c) 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer;
+
+import java.util.Iterator;
+
+/**
+ * Remote file attributes. These attributes represent characteristics of remote files (e.g. read only, writeable, executable, archive, etc.).
+ */
+public interface IRemoteFileAttributes {
+
+ public static String READ_ATTRIBUTE = "read"; //$NON-NLS-1$
+ public static String WRITE_ATTRIBUTE = "write"; //$NON-NLS-1$
+ public static String EXEC_ATTRIBUTE = "exec"; //$NON-NLS-1$
+ public static String ARCHIVE_ATTRIBUTE = "archive"; //$NON-NLS-1$
+ public static String HIDDEN_ATTRIBUTE = "hidden"; //$NON-NLS-1$
+ public static String SYMLINK_ATTRIBUTE = "symlink"; //$NON-NLS-1$
+ public static String SYMLINK_TARGET_ATTRIBUTE = "symlinktarget"; //$NON-NLS-1$
+
+ /**
+ * Get file attribute with given key. Returns null if attribute not in
+ * this map of attributes.
+ * @param key to use to find the given attribute. Must not be null.
+ * @return value of attribute. null if not found.
+ */
+ public String getAttribute(String key);
+
+ /**
+ * Get all of the attribute keys in this map of file attributes.
+ *
+ * @return Iterator of the attribute keys for this map. Will not return null.
+ */
+ public Iterator getAttributeKeys();
+
+ /**
+ * Set a given attribute value in this remote file attributes.
+ * @param key the key to use for the attribute. Must not be null.
+ * @param value the value for the given key. Must not be null.
+ */
+ public void setAttribute(String key, String value);
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileInfo.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileInfo.java
new file mode 100644
index 0000000000..1f489a9e3e
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileInfo.java
@@ -0,0 +1,95 @@
+/****************************************************************************
+ * Copyright (c) 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer;
+
+/**
+ * Information about a remote file. Last modified day/time, length in bytes,
+ * whether the remote file is a directory, a name, and file attributes.
+ * @see IRemoteFile
+ */
+public interface IRemoteFileInfo {
+
+ public static final int NO_LENGTH = -1;
+
+ /**
+ * @deprecated
+ */
+ public static final int NONE = NO_LENGTH;
+
+ public static final int NO_LAST_MODIFIED = 0;
+
+ /**
+ * Returns the last modified time for this file, or {@link #NO_LAST_MODIFIED }
+ * if the file does not exist or the last modified time could not be computed.
+ * false if this
+ * file does not exist.
+ *
+ * @return true if this file is a directory, and false
+ * otherwise.
+ */
+ public boolean isDirectory();
+
+ /**
+ * Returns the name of this file.
+ *
+ * @return the name of this file. Will not return null.
+ */
+ public String getName();
+
+ /**
+ * Get remote file attributes.
+ * @return IRemoteFileAttributes for this IRemoteFile. Will not return null.
+ */
+ public IRemoteFileAttributes getAttributes();
+
+ /**
+ * Set the attributes for this remote file info.
+ * @param attributes the new attribute values to use.
+ */
+ public void setAttributes(IRemoteFileAttributes attributes);
+
+ /**
+ * Set the underlying name for this remote file info.
+ *
+ * @param name the new name to use. Must not be null.
+ */
+ public void setName(String name);
+
+ /**
+ * Set the last modified time for this remote file info.
+ *
+ * @param time the time to use. See {@link #getLastModified()} for meaning of time value.
+ */
+ public void setLastModified(long time);
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileSystemBrowserContainerAdapter.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileSystemBrowserContainerAdapter.java
new file mode 100644
index 0000000000..802c7d9084
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileSystemBrowserContainerAdapter.java
@@ -0,0 +1,75 @@
+/****************************************************************************
+ * Copyright (c) 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.ecf.core.identity.Namespace;
+import org.eclipse.ecf.core.security.IConnectContext;
+import org.eclipse.ecf.core.util.Proxy;
+import org.eclipse.ecf.filetransfer.identity.IFileID;
+
+/**
+ * Remote file system browser adapter. This adapter can be retrieved from a container
+ * for exposing remote file system browsing capabilities.
+ */
+public interface IRemoteFileSystemBrowserContainerAdapter extends IAdaptable {
+
+ /**
+ * Get the {@link Namespace} instance for creating IFileIDs that represent remote files or directories.
+ *
+ * @return Namespace for remote files or directories. Will not be null.
+ */
+ public Namespace getBrowseNamespace();
+
+ /**
+ * Send a request for file or directory information for given directoryOrFileID.
+ * @param directoryOrFileID the IFileID representing/specifying the remote directory or file to access.
+ * @param listener the listener that will be notified asynchronously when a response to this request is received. Must not be
+ * null.
+ * @return IRemoteFileSystemRequest the request instance.
+ * @throws RemoteFileSystemException if browse request cannot be accomplished
+ */
+ public IRemoteFileSystemRequest sendBrowseRequest(IFileID directoryOrFileID, IRemoteFileSystemListener listener) throws RemoteFileSystemException;
+
+ /**
+ * Set connect context for authentication upon subsequent
+ * {@link #sendBrowseRequest(IFileID, IRemoteFileSystemListener)}. This
+ * method should be called with a non-null connectContext in order to allow
+ * authentication to occur during call to
+ * {@link #sendBrowseRequest(IFileID, IRemoteFileSystemListener)}.
+ *
+ * @param connectContext
+ * the connect context to use for authenticating during
+ * subsequent call to
+ * {@link #sendBrowseRequest(IFileID, IRemoteFileSystemListener)}.
+ * If null, then no authentication will be
+ * attempted.
+ */
+ public void setConnectContextForAuthentication(IConnectContext connectContext);
+
+ /**
+ * Set proxy for use upon subsequent
+ * {@link #sendBrowseRequest(IFileID, IRemoteFileSystemListener)}. This
+ * method should be called with a non-null proxy to allow the given proxy to
+ * be used in subsequent calls to
+ * {@link #sendBrowseRequest(IFileID, IRemoteFileSystemListener)}.
+ *
+ * @param proxy
+ * the proxy to use for subsequent calls to
+ * {@link #sendBrowseRequest(IFileID, IRemoteFileSystemListener)}.
+ * If null, then no proxy will be used.
+ */
+ public void setProxy(Proxy proxy);
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileSystemListener.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileSystemListener.java
new file mode 100644
index 0000000000..305e758dcb
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileSystemListener.java
@@ -0,0 +1,49 @@
+/****************************************************************************
+ * Copyright (c) 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer;
+
+import org.eclipse.ecf.filetransfer.events.IRemoteFileSystemEvent;
+
+/**
+ * Listener for handling events associated with remote file
+ * browsing activities.
+ *
+ * Display.getDefault().asyncExec(new Runnable() {
+ * public void run() {
+ * ... UI code here
+ * }
+ * });
+ *
+ *
+ * Further, the code in the implementations of these methods should not block
+ * via I/O operations or blocking UI calls.
+ */
+public interface IRemoteFileSystemListener {
+
+ /**
+ * Handle the remote file event.
+ * @param event the event to received to handle. Will not be null.
+ */
+ public void handleRemoteFileEvent(IRemoteFileSystemEvent event);
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileSystemRequest.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileSystemRequest.java
new file mode 100644
index 0000000000..6a35269675
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRemoteFileSystemRequest.java
@@ -0,0 +1,40 @@
+/****************************************************************************
+ * Copyright (c) 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.ecf.filetransfer.identity.IFileID;
+
+/**
+ * Remote file request.
+ */
+public interface IRemoteFileSystemRequest extends IAdaptable {
+
+ /**
+ * Cancel this request.
+ */
+ public void cancel();
+
+ /**
+ * Get the listener associated with this request
+ * @return IRemoteFileSystemListener associated with this request.
+ */
+ public IRemoteFileSystemListener getRemoteFileListener();
+
+ /**
+ * Get directoryID that represents the directory accessed.
+ * @return IFileID for remote directory or file. Will not return null.
+ */
+ public IFileID getFileID();
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRetrieveFileTransferContainerAdapter.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRetrieveFileTransferContainerAdapter.java
new file mode 100644
index 0000000000..eec9d8c914
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRetrieveFileTransferContainerAdapter.java
@@ -0,0 +1,218 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer;
+
+import java.util.Map;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.ecf.core.IContainer;
+import org.eclipse.ecf.core.identity.IDFactory;
+import org.eclipse.ecf.core.identity.Namespace;
+import org.eclipse.ecf.core.security.IConnectContext;
+import org.eclipse.ecf.core.util.Proxy;
+import org.eclipse.ecf.filetransfer.events.*;
+import org.eclipse.ecf.filetransfer.identity.IFileID;
+
+/**
+ * Entry point retrieval file transfer adapter. This adapter interface allows
+ * providers to expose file retrieval semantics to clients in a transport
+ * independent manner. To be used, a non-null adapter reference must be returned
+ * from a call to {@link IContainer#getAdapter(Class)}. Once a non-null
+ * reference is retrieved, then it may be used to send a retrieve request.
+ * Events will then be asynchronously delivered to the provided listener to
+ * complete file transfer.
+ *
+ * // Get IRetrieveFileTransferContainerAdapter adapter
+ * IRetrieveFileTransferContainerAdapter ftc = (IRetrieveFileTransferContainerAdapter) container
+ * .getAdapter(IRetrieveFileTransferContainerAdapter.class);
+ * if (ftc != null) {
+ * // Create listener for receiving/responding to asynchronous file transfer events
+ * IFileTransferListener listener = new IFileTransferListener() {
+ * public void handleTransferEvent(IFileTransferEvent event) {
+ * // If incoming receive start event, respond by specifying local file to save to
+ * if (event instanceof IIncomingFileTransferReceiveStartEvent) {
+ * IIncomingFileTransferReceiveStartEvent rse = (IIncomingFileTransferReceiveStartEvent) event;
+ * try {
+ * rse.receive(new File("composent.main.page.html"));
+ * } catch (IOException e) {
+ * // Handle exception appropriately
+ * }
+ * }
+ * }
+ * };
+ * // Identify file to retrieve and create ID
+ * IFileID remoteFileID = FileIDFactory.getDefault().createID(
+ * ftc.getRetrieveNamespace(), "http://www.composent.com/index.html");
+ * // Actually make request to start retrieval. The listener provided will then be notified asynchronously
+ * // as file transfer events occur
+ * ftc.sendRetrieveRequest(remoteFileID, listener, null);
+ * }
+ *
+ *
+ * Where the IFileTransferEvent subtypes for the receiver will be:
+ *
+ *
+ */
+public interface IRetrieveFileTransferContainerAdapter extends IAdaptable {
+
+ /**
+ * Send request for transfer of a remote file to local file storage. This
+ * method is used to initiate a file retrieve for a remoteFileID (first
+ * parameter). File transfer events are asynchronously delivered a file
+ * transfer listener (second parameter). The given remoteFileID and
+ * transferListener must not be null.
+ *
+ * IFileID remoteFileID = FileIDFactory.getDefault().createID(
+ * ftc.getRetrieveNamespace(), "http://www.composent.com/index.html");
+ *
+ *
+ * Must not be null.
+ * @param transferListener
+ * a listener for file transfer events. Must not be null. Must not be null. See Note above.
+ * @param options
+ * a Map of options associated with sendRetrieveRequest. The
+ * particular name/value pairs will be unique to the individual
+ * providers. May be null.
+ * @throws IncomingFileTransferException
+ * if the provider is not connected or is not in the correct
+ * state for initiating file transfer
+ */
+ public void sendRetrieveRequest(IFileID remoteFileID, IFileTransferListener transferListener, Map options) throws IncomingFileTransferException;
+
+ /**
+ * Send request for transfer of a remote file to local file storage. This
+ * method is used to initiate a file retrieve for a remoteFileID (first
+ * parameter). File transfer events are asynchronously delivered a file
+ * transfer listener (third parameter). The given remoteFileID and
+ * transferListener must not be null.
+ *
+ * IFileID remoteFileID = FileIDFactory.getDefault().createID(
+ * ftc.getRetrieveNamespace(), "http://www.composent.com/index.html");
+ *
+ *
+ * Must not be null.
+ * @param rangeSpecification a range specification for retrieving a portion of the given
+ * remote file. If null the entire file will be retrieved (as per {@link #sendRetrieveRequest(IFileID, IFileTransferListener, Map)}.
+ * If non-null the given file range will be used to retrieve the given file. For example, if the
+ * rangeSpecification has a start value of 1 and end value of 3, and the total length of the file is
+ * 5 bytes with content [a, b, c, d, e], a successful retrieve request would transfer bytes 'b', 'c', and 'd', but not 'a', and 'e'.
+ * @param transferListener
+ * a listener for file transfer events. Must not be null. See Note above.
+ * @param options
+ * a Map of options associated with sendRetrieveRequest. The
+ * particular name/value pairs will be unique to the individual
+ * providers. May be null.
+ * @throws IncomingFileTransferException
+ * if the provider is not connected or is not in the correct
+ * state for initiating file transfer
+ */
+ public void sendRetrieveRequest(IFileID remoteFileID, IFileRangeSpecification rangeSpecification, IFileTransferListener transferListener, Map options) throws IncomingFileTransferException;
+
+ /**
+ * Get namespace to be used for creation of remoteFileID for retrieve
+ * request. Result typically used as first parameter for
+ * {@link IDFactory#createID(Namespace, String)} to be used as first in
+ * {@link #sendRetrieveRequest(IFileID, IFileTransferListener, Map)}
+ *
+ * @return Namespace to use for ID creation via
+ * {@link IDFactory#createID(Namespace, String)}. Will not be
+ * null.
+ */
+ public Namespace getRetrieveNamespace();
+
+ /**
+ * Set connect context for authentication upon subsequent
+ * {@link #sendRetrieveRequest(IFileID, IFileTransferListener, Map)}. This
+ * method should be called with a non-null connectContext in order to allow
+ * authentication to occur during call to
+ * {@link #sendRetrieveRequest(IFileID, IFileTransferListener, Map)}.
+ *
+ * @param connectContext
+ * the connect context to use for authenticating during
+ * subsequent call to
+ * {@link #sendRetrieveRequest(IFileID, IFileTransferListener, Map)}.
+ * If null, then no authentication will be
+ * attempted.
+ */
+ public void setConnectContextForAuthentication(IConnectContext connectContext);
+
+ /**
+ * Set proxy for use upon subsequent
+ * {@link #sendRetrieveRequest(IFileID, IFileTransferListener, Map)}. This
+ * method should be called with proxy to allow the given proxy to
+ * be used in subsequent calls to
+ * {@link #sendRetrieveRequest(IFileID, IFileTransferListener, Map)}.
+ * null or has not been called providers must use
+ * the org.eclipse.core.net proxy API to obtain proxy information
+ * and proxy credentials if they support proxies of the type(s) supported by
+ * that API. The API is provided by an OSGi service of type
+ * org.eclipse.core.net.proxy.IProxyService.
+ * IProxyService
+ * providers may use other defaults.
+ * null, then proxy information is obtained from
+ * IProxyService if available. Otherwise provider
+ * defined defaults may be used.
+ */
+ public void setProxy(Proxy proxy);
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRetrieveFileTransferOptions.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRetrieveFileTransferOptions.java
new file mode 100644
index 0000000000..58eb2c5793
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IRetrieveFileTransferOptions.java
@@ -0,0 +1,47 @@
+/****************************************************************************
+ * Copyright (c) 2009 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer;
+
+import java.util.Map;
+
+/**
+ * @since 3.1
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IRetrieveFileTransferOptions {
+
+ /**
+ * This constant defines a key in options Map passed to {@link IRetrieveFileTransferContainerAdapter#sendRetrieveRequest(org.eclipse.ecf.filetransfer.identity.IFileID, IFileTransferListener, java.util.Map)}.
+ * Supporting providers will use this key to look for a value of type Map, and if found the String key/value pairs in the
+ * Map will be used as request headers. The expected type of the value associated with this key is of type {@link Map}.
+ *
+ */
+ public static final String REQUEST_HEADERS = IRetrieveFileTransferOptions.class.getName() + ".requestHeaders"; //$NON-NLS-1$
+
+ /**
+ * This constant defines a key in options Map passed to {@link IRetrieveFileTransferContainerAdapter#sendRetrieveRequest(org.eclipse.ecf.filetransfer.identity.IFileID, IFileTransferListener, java.util.Map)}.
+ * Supporting providers will use this key to look for a value of type Integer or String, and if found this value
+ * will be used to determine the socket connection timeout for this request. The expected type of the value
+ * associated with this key is of type Integer, or String value of an Integer.
+ */
+ public static final String CONNECT_TIMEOUT = IRetrieveFileTransferOptions.class.getName() + ".connectTimeout"; //$NON-NLS-1$
+
+ /**
+ * This constant defines a key in options Map passed to {@link IRetrieveFileTransferContainerAdapter#sendRetrieveRequest(org.eclipse.ecf.filetransfer.identity.IFileID, IFileTransferListener, java.util.Map)}.
+ * Supporting providers will use this key to look for a value of type Integer or String, and if found this value
+ * will be used to determine the socket read timeout for this request. The expected type of the value
+ * associated with this key is of type Integer, or String value of an Integer.
+ */
+ public static final String READ_TIMEOUT = IRetrieveFileTransferOptions.class.getName() + ".readTimeout"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/ISendFileTransferContainerAdapter.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/ISendFileTransferContainerAdapter.java
new file mode 100644
index 0000000000..4d97ccaa13
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/ISendFileTransferContainerAdapter.java
@@ -0,0 +1,188 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer;
+
+import java.io.File;
+import java.util.Map;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.ecf.core.IContainer;
+import org.eclipse.ecf.core.identity.Namespace;
+import org.eclipse.ecf.core.security.IConnectContext;
+import org.eclipse.ecf.core.util.Proxy;
+import org.eclipse.ecf.filetransfer.events.*;
+import org.eclipse.ecf.filetransfer.identity.IFileID;
+
+/**
+ * Entry point outgoing file transfer container adapter. This adapter interface
+ * allows providers to expose file sending semantics to clients in a transport
+ * independent manner. To be used, a non-null adapter reference must be returned
+ * from a call to {@link IContainer#getAdapter(Class)}. Once a non-null
+ * reference is retrieved, then it may be used to request to send a file to a
+ * remote user. Events will then be asynchronously delivered to the provided
+ * listener to complete file transfer.
+ *
+ * // Get ISendFileTransferContainerAdapter adapter
+ * ISendFileTransferContainerAdapter ftc = (ISendFileTransferContainerAdapter) container.getAdapter(ISendFileTransferContainerAdapter.class);
+ * if (ftc != null) {
+ * // Create listener for receiving/responding to asynchronous file transfer events
+ * IFileTransferListener listener = new IFileTransferListener() {
+ * public void handleTransferEvent(IFileTransferEvent event) {
+ * // If this event is a response to the transfer request, check if file transfer rejected
+ * if (event instanceof IOutgoingFileTransferResponseEvent) {
+ * IOutgoingFileTransferResponseEvent oftr = (IOutgoingFileTransferResponseEvent) event;
+ * if (!oftr.requestAccepted()) {
+ * // request rejected...tell user
+ * }
+ * }
+ * }
+ * };
+ * // Specify the target file ID
+ * // This following specifies the path: ~/path/filename.ext
+ * ID targetID = FileIDFactory.getDefault().createFileID(ftc.getOutgoingNamespace(),new URL("scp://user@host/path/filename.ext"));
+ * // This following specifies the path: /path/filename.ext
+ * // ID targetID = FileIDFactory.getDefault().createFileID(ftc.getOutgoingNamespace(),new URL("scp://user@host//path/filename.ext"));
+ * // Specify the local file to send
+ * File localFileToSend = new File("filename");
+ * // Actually send outgoing file request to remote user.
+ * ftc.sendOutgoingRequest(targetID, localFileToSend, listener, null);
+ * }
+ *
+ *
+ * For the sender the delivered events will be:
+ *
+ *
+ * and for the {@link IIncomingFileTransferRequestListener} events
+ * delivered will be:
+ *
+ *
+ */
+public interface ISendFileTransferContainerAdapter extends IAdaptable {
+ /**
+ * Send request for outgoing file transfer. This method is used to initiate
+ * a file transfer to a targetReceiver (first parameter) of the
+ * localFileToSend (second parameter). File transfer events are
+ * asynchronously delivered to the file transferListener (third parameter)
+ *
+ * @param targetReceiver
+ * the ID of the remote to receive the file transfer request.
+ * Must not be should not be null.
+ * @param localFileToSend
+ * the {@link IFileTransferInfo} for the local file to send. Must
+ * not be should not be null.
+ * @param transferListener
+ * a {@link IFileTransferListener} for responding to file
+ * transfer events. Must not be should not be null..
+ * If the target receiver responds then an
+ * {@link IOutgoingFileTransferResponseEvent} will be delivered
+ * to the listener
+ * @param options
+ * a Map of options associated with sendOutgoingRequest. The
+ * particular name/value pairs will be unique to the individual
+ * providers. May be should not be null..
+ * @throws SendFileTransferException
+ * if the provider is not connected or is not in the correct
+ * state for initiating file transfer
+ */
+ public void sendOutgoingRequest(IFileID targetReceiver, IFileTransferInfo localFileToSend, IFileTransferListener transferListener, Map options) throws SendFileTransferException;
+
+ /**
+ * Send request for outgoing file transfer. This method is used to initiate
+ * a file transfer to a targetReceiver (first parameter) of the
+ * localFileToSend (second parameter). File transfer events are
+ * asynchronously delivered to the file transferListener (third parameter)
+ *
+ * @param targetReceiver
+ * the ID of the remote to receive the file transfer request.
+ * Must not be null.
+ * @param localFileToSend
+ * the {@link File} for the local file to send. Must not be
+ * null.
+ * @param transferListener
+ * a {@link IFileTransferListener} for responding to file
+ * transfer events. Must not be null. If the
+ * target receiver responds then an IOutgoingFileTransfer will be
+ * delivered to the listener
+ * @param options
+ * a Map of options associated with sendOutgoingRequest. The
+ * particular name/value pairs will be unique to the individual
+ * providers. May be null.
+ * @throws SendFileTransferException
+ * if the provider is not connected or is not in the correct
+ * state for initiating file transfer
+ */
+ public void sendOutgoingRequest(IFileID targetReceiver, File localFileToSend, IFileTransferListener transferListener, Map options) throws SendFileTransferException;
+
+ /**
+ * Add incoming file transfer listener. If the underlying provider supports
+ * receiving file transfer requests
+ *
+ * @param listener
+ * to receive incoming file transfer request events. Must not be
+ * null.
+ */
+ public void addListener(IIncomingFileTransferRequestListener listener);
+
+ /**
+ * Remove incoming file transfer listener
+ *
+ * @param listener
+ * the listener to remove. Must not be null.
+ * @return true if listener actually removed, false otherwise
+ */
+ public boolean removeListener(IIncomingFileTransferRequestListener listener);
+
+ /**
+ * Get namespace for outgoing file transfer.
+ * @return Namespace for outgoing IFileID instances. Will not return null.
+ */
+ public Namespace getOutgoingNamespace();
+
+ /**
+ * Set connect context for authentication upon subsequent
+ * {@link #sendOutgoingRequest(IFileID, IFileTransferInfo, IFileTransferListener, Map)}. This
+ * method should be called with a non-null connectContext in order to allow
+ * authentication to occur during call to
+ * {@link #sendOutgoingRequest(IFileID, IFileTransferInfo, IFileTransferListener, Map)}.
+ *
+ * @param connectContext
+ * the connect context to use for authenticating during
+ * subsequent call to
+ * {@link #sendOutgoingRequest(IFileID, IFileTransferInfo, IFileTransferListener, Map)}.
+ * If null, then no authentication will be
+ * attempted.
+ */
+ public void setConnectContextForAuthentication(IConnectContext connectContext);
+
+ /**
+ * Set proxy for use upon subsequent
+ * {@link #sendOutgoingRequest(IFileID, IFileTransferInfo, IFileTransferListener, Map)}. This
+ * method should be called with a non-null proxy to allow the given proxy to
+ * be used in subsequent calls to
+ * {@link #sendOutgoingRequest(IFileID, IFileTransferInfo, IFileTransferListener, Map)}.
+ *
+ * @param proxy
+ * the proxy to use for subsequent calls to
+ * {@link #sendOutgoingRequest(IFileID, IFileTransferInfo, IFileTransferListener, Map)}.
+ * If null, then no proxy will be used.
+ */
+ public void setProxy(Proxy proxy);
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/ISendFileTransferOptions.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/ISendFileTransferOptions.java
new file mode 100644
index 0000000000..09a4c4d39e
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/ISendFileTransferOptions.java
@@ -0,0 +1,22 @@
+/****************************************************************************
+ * Copyright (c) 2009 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer;
+
+/**
+ * @since 3.1
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface ISendFileTransferOptions {
+ // Nothing
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IncomingFileTransferException.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IncomingFileTransferException.java
new file mode 100644
index 0000000000..ff1beb1148
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/IncomingFileTransferException.java
@@ -0,0 +1,117 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer;
+
+import java.util.Map;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.ecf.core.util.ECFException;
+
+/**
+ * Exception thrown upon incoming file transfer problem
+ *
+ */
+public class IncomingFileTransferException extends ECFException {
+
+ private static final long serialVersionUID = 2438441801862623371L;
+
+ private int errorCode = -1;
+ private Map responseHeaders;
+
+ public IncomingFileTransferException(IStatus status) {
+ super(status);
+ }
+
+ public IncomingFileTransferException() {
+ // null constructor
+ }
+
+ public IncomingFileTransferException(int errorCode) {
+ this();
+ this.errorCode = errorCode;
+ }
+
+ public IncomingFileTransferException(String message) {
+ super(message);
+ }
+
+ public IncomingFileTransferException(String message, int errorCode) {
+ super(message);
+ this.errorCode = errorCode;
+ }
+
+ public IncomingFileTransferException(Throwable cause) {
+ super(cause);
+ }
+
+ public IncomingFileTransferException(Throwable cause, int errorCode) {
+ super(cause);
+ this.errorCode = errorCode;
+ }
+
+ public IncomingFileTransferException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public IncomingFileTransferException(String message, Throwable cause, int errorCode) {
+ super(message, cause);
+ this.errorCode = errorCode;
+ }
+
+ /**
+ * @param message message
+ * @param cause cause
+ * @param errorCode errorCode
+ * @param responseHeaders responseHeaders
+ * @since 4.0
+ */
+ public IncomingFileTransferException(String message, Throwable cause, int errorCode, Map responseHeaders) {
+ super(message, cause);
+ this.errorCode = errorCode;
+ this.responseHeaders = responseHeaders;
+ }
+
+ /**
+ * @param message message
+ * @param errorCode errorCode
+ * @param responseHeaders responseHeaders
+ * @since 4.0
+ */
+ public IncomingFileTransferException(String message, int errorCode, Map responseHeaders) {
+ super(message);
+ this.errorCode = errorCode;
+ this.responseHeaders = responseHeaders;
+ }
+
+ /**
+ * @param cause cause
+ * @param errorCode errorCode
+ * @param responseHeaders responseHeaders
+ * @since 4.0
+ */
+ public IncomingFileTransferException(Throwable cause, int errorCode, Map responseHeaders) {
+ super(cause);
+ this.errorCode = errorCode;
+ this.responseHeaders = responseHeaders;
+ }
+
+ public int getErrorCode() {
+ return errorCode;
+ }
+
+ /**
+ * @since 4.0
+ * @return Map response headers
+ */
+ public Map getResponseHeaders() {
+ return responseHeaders;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/InvalidFileRangeSpecificationException.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/InvalidFileRangeSpecificationException.java
new file mode 100644
index 0000000000..bda248d97c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/InvalidFileRangeSpecificationException.java
@@ -0,0 +1,76 @@
+/****************************************************************************
+ * Copyright (c) 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer;
+
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ *
+ */
+public class InvalidFileRangeSpecificationException extends IncomingFileTransferException {
+
+ private static final long serialVersionUID = 532923607480972210L;
+
+ private IFileRangeSpecification rangeSpec = null;
+
+ /**
+ * @param rangeSpec rangeSpec
+ */
+ public InvalidFileRangeSpecificationException(IFileRangeSpecification rangeSpec) {
+ super();
+ this.rangeSpec = rangeSpec;
+ }
+
+ /**
+ * @param status status
+ * @param rangeSpec range spec
+ */
+ public InvalidFileRangeSpecificationException(IStatus status, IFileRangeSpecification rangeSpec) {
+ super(status);
+ this.rangeSpec = rangeSpec;
+ }
+
+ /**
+ * @param message message
+ * @param cause cause
+ * @param rangeSpec range spec
+ */
+ public InvalidFileRangeSpecificationException(String message, Throwable cause, IFileRangeSpecification rangeSpec) {
+ super(message, cause);
+ this.rangeSpec = rangeSpec;
+ }
+
+ /**
+ * @param message message
+ * @param rangeSpec range spec
+ */
+ public InvalidFileRangeSpecificationException(String message, IFileRangeSpecification rangeSpec) {
+ super(message);
+ this.rangeSpec = rangeSpec;
+ }
+
+ /**
+ * @param cause cause
+ * @param rangeSpec range spec
+ */
+ public InvalidFileRangeSpecificationException(Throwable cause, IFileRangeSpecification rangeSpec) {
+ super(cause);
+ this.rangeSpec = rangeSpec;
+ }
+
+ public IFileRangeSpecification getFileRangeSpecification() {
+ return this.rangeSpec;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/RemoteFileSystemException.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/RemoteFileSystemException.java
new file mode 100644
index 0000000000..b52d5b4ea0
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/RemoteFileSystemException.java
@@ -0,0 +1,62 @@
+/****************************************************************************
+ * Copyright (c) 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.ecf.core.util.ECFException;
+
+/**
+ *
+ */
+public class RemoteFileSystemException extends ECFException {
+
+ private static final long serialVersionUID = -2199951600347999396L;
+
+ /**
+ *
+ */
+ public RemoteFileSystemException() {
+ super();
+ }
+
+ /**
+ * @param status status
+ */
+ public RemoteFileSystemException(IStatus status) {
+ super(status);
+ }
+
+ /**
+ * @param message message
+ * @param cause cause
+ */
+ public RemoteFileSystemException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * @param message message
+ */
+ public RemoteFileSystemException(String message) {
+ super(message);
+ }
+
+ /**
+ * @param cause cause
+ */
+ public RemoteFileSystemException(Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/SendFileTransferException.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/SendFileTransferException.java
new file mode 100644
index 0000000000..5e0534d348
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/SendFileTransferException.java
@@ -0,0 +1,70 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.ecf.core.util.ECFException;
+
+/**
+ * Outgoing file transfer exception
+ *
+ */
+public class SendFileTransferException extends ECFException {
+
+ private static final long serialVersionUID = -3752377147967128446L;
+
+ private int errorCode = -1;
+
+ public SendFileTransferException(IStatus status) {
+ super(status);
+ }
+
+ public SendFileTransferException() {
+ // null constructor
+ }
+
+ public SendFileTransferException(int errorCode) {
+ this();
+ this.errorCode = errorCode;
+ }
+
+ public SendFileTransferException(String message) {
+ super(message);
+ }
+
+ public SendFileTransferException(String message, int errorCode) {
+ super(message);
+ this.errorCode = errorCode;
+ }
+
+ public SendFileTransferException(Throwable cause) {
+ super(cause);
+ }
+
+ public SendFileTransferException(Throwable cause, int errorCode) {
+ super(cause);
+ this.errorCode = errorCode;
+ }
+
+ public SendFileTransferException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public SendFileTransferException(String message, Throwable cause, int errorCode) {
+ super(message, cause);
+ this.errorCode = errorCode;
+ }
+
+ public int getErrorCode() {
+ return errorCode;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/UserCancelledException.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/UserCancelledException.java
new file mode 100644
index 0000000000..a5359052f7
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/UserCancelledException.java
@@ -0,0 +1,45 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc., Peter Nehrer, Boris Bokowski.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.ecf.core.util.ECFException;
+
+/**
+ * Exception class for user cancellation
+ *
+ */
+public class UserCancelledException extends ECFException {
+
+ private static final long serialVersionUID = -1147166028435325320L;
+
+ public UserCancelledException() {
+ // null constructor
+ }
+
+ public UserCancelledException(IStatus status) {
+ super(status);
+ }
+
+ public UserCancelledException(String message) {
+ super(message);
+ }
+
+ public UserCancelledException(Throwable cause) {
+ super(cause);
+ }
+
+ public UserCancelledException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IFileTransferConnectStartEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IFileTransferConnectStartEvent.java
new file mode 100644
index 0000000000..c931182f63
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IFileTransferConnectStartEvent.java
@@ -0,0 +1,95 @@
+/****************************************************************************
+ * Copyright (c) 2009 IBM, and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer.events;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.ecf.filetransfer.*;
+import org.eclipse.ecf.filetransfer.identity.IFileID;
+
+/**
+ * Event sent to {@link IFileTransferListener} associated with
+ * {@link IIncomingFileTransfer} or
+ * {@link IOutgoingFileTransferEvent} or
+ * {@link IRemoteFileSystemRequest} instances.
+ * null, the provider will
+ * use create and prepare a default connect job.
+ * NOTE: the given job should *not* be
+ * scheduled/started prior to being provided as a parameter to
+ * this method.
+ * @return passed in job or default connect job if parameter connectJob was
+ * null.
+ */
+ FileTransferJob prepareConnectJob(FileTransferJob connectJob);
+
+ /**
+ * Connect using a job.
+ * null.
+ * NOTE: the given job should *not* be
+ * scheduled/started prior to being provided as a parameter to
+ * this method.
+ *
+ */
+ void connectUsingJob(FileTransferJob connectJob);
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IFileTransferEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IFileTransferEvent.java
new file mode 100644
index 0000000000..90aa6687ff
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IFileTransferEvent.java
@@ -0,0 +1,22 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer.events;
+
+import org.eclipse.ecf.core.util.Event;
+
+/**
+ * Super interface for all file transfer events
+ *
+ */
+public interface IFileTransferEvent extends Event {
+ // no methods for interface
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IFileTransferRequestEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IFileTransferRequestEvent.java
new file mode 100644
index 0000000000..65cca8b354
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IFileTransferRequestEvent.java
@@ -0,0 +1,102 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer.events;
+
+import java.io.File;
+import java.io.OutputStream;
+
+import org.eclipse.ecf.core.identity.ID;
+import org.eclipse.ecf.filetransfer.IFileTransferInfo;
+import org.eclipse.ecf.filetransfer.IFileTransferListener;
+import org.eclipse.ecf.filetransfer.IIncomingFileTransfer;
+import org.eclipse.ecf.filetransfer.IIncomingFileTransferRequestListener;
+import org.eclipse.ecf.filetransfer.IncomingFileTransferException;
+
+/**
+ * Event to represent remote file transfer requests. Events implementing this
+ * interface are delivered to {@link IIncomingFileTransferRequestListener}
+ *
+ * @see IIncomingFileTransferRequestListener#handleFileTransferRequest(IFileTransferRequestEvent)
+ */
+public interface IFileTransferRequestEvent extends IFileTransferEvent {
+ /**
+ * Get ID of remote requester
+ *
+ * @return ID of remote requester. Will not be null.
+ */
+ public ID getRequesterID();
+
+ /**
+ * Get file transfer info associated with this file transfer request even
+ *
+ * @return IFileTransfer info. Will not be null.
+ */
+ public IFileTransferInfo getFileTransferInfo();
+
+ /**
+ * Accept the file transfer request. This method should be called if the
+ * receiver of the IFileTransferRequestEvent would like to accept the file
+ * transfer request. Will not return null. Once called
+ * successfully, then {@link #requestAccepted()} will return true, and
+ * further calls to {@link #accept(File)} or
+ * {@link #accept(OutputStream, IFileTransferListener)} will throw
+ * IncomingFileTransferExceptions.
+ *
+ * @param localFileToSave
+ * the file on the local file system to receive the remote file.
+ * Must not be null.
+ * @return IIncomingFileTransfer to receive file. Will not be
+ * null.
+ * @throws IncomingFileTransferException
+ * if accept message cannot be delivered back to requester
+ */
+ public IIncomingFileTransfer accept(File localFileToSave) throws IncomingFileTransferException;
+
+ /**
+ * Accept the file transfer request. This method should be called if the
+ * receiver of the IFileTransferRequestEvent would like to accept the file
+ * transfer request. Will not return null. Once called
+ * successfully, then {@link #requestAccepted()} will return true, and
+ * further calls to {@link #accept(File)} or
+ * {@link #accept(OutputStream, IFileTransferListener)} will throw
+ * IncomingFileTransferExceptions.
+ *
+ * @param outputStream
+ * the output stream to receive the accepted file contents. Must
+ * not be null.
+ * @param listener
+ * for file transfer events during file reception. May be
+ * null.
+ * @return IIncomingFileTransfer to receive file. Will not be
+ * null.
+ * @throws IncomingFileTransferException
+ * if accept message cannot be delivered back to requester
+ */
+ public IIncomingFileTransfer accept(OutputStream outputStream, IFileTransferListener listener) throws IncomingFileTransferException;
+
+ /**
+ * Reject the file transfer request. This method should be called if the
+ * receiver of the IFileTransferRequestEvent would like to reject the file
+ * transfer request
+ *
+ */
+ public void reject();
+
+ /**
+ * If request was accepted from remote target (via successful call to
+ * {@link #accept(File)}this method will return true, if rejected or failed
+ * returns false.
+ *
+ * @return true if request was accepted, false if rejected or failed
+ */
+ public boolean requestAccepted();
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferEvent.java
new file mode 100644
index 0000000000..d7a9fc8d2f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferEvent.java
@@ -0,0 +1,28 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer.events;
+
+import org.eclipse.ecf.filetransfer.IIncomingFileTransfer;
+
+/**
+ * Super interface for incoming file transfer events
+ *
+ */
+public interface IIncomingFileTransferEvent extends IFileTransferEvent {
+ /**
+ * Get {@link IIncomingFileTransfer} associated with this event
+ *
+ * @return IIncomingFileTransfer that is source of this event. Will not be
+ * null.
+ */
+ public IIncomingFileTransfer getSource();
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceiveDataEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceiveDataEvent.java
new file mode 100644
index 0000000000..9361ebf491
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceiveDataEvent.java
@@ -0,0 +1,24 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer.events;
+
+import org.eclipse.ecf.filetransfer.IFileTransferListener;
+import org.eclipse.ecf.filetransfer.IIncomingFileTransfer;
+
+/**
+ * Event sent to {@link IFileTransferListener} associated with
+ * {@link IIncomingFileTransfer} instances data are received
+ *
+ */
+public interface IIncomingFileTransferReceiveDataEvent extends IIncomingFileTransferEvent {
+ // no methods for interface
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceiveDoneEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceiveDoneEvent.java
new file mode 100644
index 0000000000..8943b30bfb
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceiveDoneEvent.java
@@ -0,0 +1,39 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer.events;
+
+import org.eclipse.ecf.filetransfer.UserCancelledException;
+
+/**
+ * Event sent to IFileTransferListeners when an incoming file transfer is
+ * completed.
+ *
+ */
+public interface IIncomingFileTransferReceiveDoneEvent extends IIncomingFileTransferEvent {
+
+ /**
+ * Get any exception associated with this file transfer. If the file
+ * transfer completed successfully, this method will return
+ * null. If the file transfer completed unsuccessfully (some
+ * exception occurred), then this method will return a non-null
+ * Exception instance that occurred.
+ * null
+ * if transfer completed successfully, non-null if transfer
+ * completed with some exception.
+ */
+ public Exception getException();
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceivePausedEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceivePausedEvent.java
new file mode 100644
index 0000000000..b6eae4088d
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceivePausedEvent.java
@@ -0,0 +1,21 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer.events;
+
+/**
+ * Event sent to IFileTransferListeners when an incoming file transfer is
+ * paused.
+ *
+ */
+public interface IIncomingFileTransferReceivePausedEvent extends IIncomingFileTransferEvent {
+ // no methods
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceiveResumedEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceiveResumedEvent.java
new file mode 100644
index 0000000000..56b9c3220d
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceiveResumedEvent.java
@@ -0,0 +1,155 @@
+/****************************************************************************
+ * Copyright (c) 2008 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ * Cloudsmith, Inc. - additional API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer.events;
+
+import java.io.*;
+import java.util.Map;
+import org.eclipse.ecf.filetransfer.*;
+import org.eclipse.ecf.filetransfer.identity.IFileID;
+
+/**
+ * Event sent to {@link IFileTransferListener} associated with
+ * {@link IIncomingFileTransfer} instances when file transfer is resumed.
+ *
+ */
+public interface IIncomingFileTransferReceiveResumedEvent extends IIncomingFileTransferEvent {
+
+ /**
+ * Get IFileID for incoming file
+ *
+ * @return IFileID for this file transfer event. Will not be
+ * null.
+ */
+ public IFileID getFileID();
+
+ /**
+ * Get incoming file transfer object by specifying a local File instance to
+ * save the received contents to.
+ *
+ * @param localFileToSave
+ * the file on the local file system to receive and save the
+ * remote file. Must not be null.
+ * @param append
+ * if true, and data received is appended to the
+ * given localFileToSave. If false, data are written
+ * to the beginning of the given localFileToSave, and any
+ * existing contents are overwritten.
+ * @return IIncomingFileTransfer the incoming file transfer object. Will not
+ * be null.
+ * @throws IOException
+ * if localFileToSave cannot be opened for writing.
+ * @since 2.0
+ */
+ public IIncomingFileTransfer receive(File localFileToSave, boolean append) throws IOException;
+
+ /**
+ * Just like {@link #receive(File,boolean)} but this method also give the
+ * caller a chance to provide a factory that creates the job that will
+ * perform the actual file transfer. The intended use for this is when the
+ * user of the framework needs more elaborate control over such jobs such as
+ * waiting for a group of parallel file transfers to complete. Such
+ * functionality can for instance exploit the Eclipse runtime concept of Job
+ * families.
+ *
+ * @param localFileToSave
+ * the file on the local file system to receive and save the
+ * remote file. Must not be null.
+ * @param append
+ * if true, and data received is appended to the
+ * given localFileToSave. If false, data are written
+ * to the beginning of the given localFileToSave, and any
+ * existing contents are overwritten.
+ * @param fileTransferJob
+ * A subclass of {@link FileTransferJob} to use to run the actual
+ * transfer. If null, provider will create default
+ * implementation. NOTE: the given job should *not* be
+ * scheduled/started prior to being provided as parameter to this
+ * method.
+ * @return IIncomingFileTransfer the incoming file transfer object. NOTE:
+ * the caller is responsible for calling
+ * {@link OutputStream#close()} on the OutputStream provided. If the
+ * stream provided is buffered, then
+ * {@link BufferedOutputStream#flush()} should be called to
+ * guarantee that the data received is actually written to the given
+ * OutputStream.
+ * @throws IOException
+ * if streamToStore cannot be opened for writing.
+ * @since 2.0
+ */
+ public IIncomingFileTransfer receive(File localFileToSave, FileTransferJob fileTransferJob, boolean append) throws IOException;
+
+ /**
+ * Get incoming file transfer by specifying an OutputStream instance to save
+ * the received contents to. NOTE: the caller is responsible for calling
+ * {@link OutputStream#close()} on the OutputStream provided. If the stream
+ * provided is buffered, then {@link BufferedOutputStream#flush()} should be
+ * called to guaranteed that the data received is actually written to the
+ * given OutputStream.
+ *
+ * @param streamToStore
+ * the output stream to store the incoming file. Must not be
+ * null.
+ * @return IIncomingFileTransfer the incoming file transfer object. NOTE:
+ * the caller is responsible for calling
+ * {@link OutputStream#close()} on the OutputStream provided. If the
+ * stream provided is buffered, then
+ * {@link BufferedOutputStream#flush()} should be called to
+ * guarantee that the data received is actually written to the given
+ * OutputStream.
+ * @throws IOException
+ * if streamToStore cannot be opened for writing
+ */
+ public IIncomingFileTransfer receive(OutputStream streamToStore) throws IOException;
+
+ /**
+ * Just like {@link #receive(OutputStream)} but this method also give the
+ * caller a chance to provide a factory that creates the job that will
+ * perform the actual file transfer. The intended use for this is when the
+ * user of the framework needs more elaborate control over such jobs such as
+ * waiting for a group of parallel file transfers to complete. Such
+ * functionality can for instance exploit the Eclipse runtime concept of Job
+ * families.
+ *
+ * @param streamToStore
+ * the output stream to store the incoming file. Must not be
+ * null.
+ * @param fileTransferJob
+ * A subclass of {@link FileTransferJob} to use to run the actual
+ * transfer. If null, provider will create default
+ * implementation. NOTE: the given job should *not* be
+ * scheduled/started prior to being provided as a parameter to
+ * this method.
+ * @return IIncomingFileTransfer the incoming file transfer object. NOTE:
+ * the caller is responsible for calling
+ * {@link OutputStream#close()} on the OutputStream provided. If the
+ * stream provided is buffered, then
+ * {@link BufferedOutputStream#flush()} should be called to
+ * guarantee that the data received is actually written to the given
+ * OutputStream.
+ * @throws IOException
+ * if streamToStore cannot be opened for writing
+ */
+ public IIncomingFileTransfer receive(OutputStream streamToStore, FileTransferJob fileTransferJob) throws IOException;
+
+ /**
+ * Cancel incoming file transfer
+ */
+ public void cancel();
+
+ /**
+ * Get response headers.
+ * @return Map of response headers. null if no headers available.
+ * @since 4.0
+ */
+ public Map getResponseHeaders();
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceiveStartEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceiveStartEvent.java
new file mode 100644
index 0000000000..94d8543857
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IIncomingFileTransferReceiveStartEvent.java
@@ -0,0 +1,143 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ * Cloudsmith, Inc. - additional API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer.events;
+
+import java.io.*;
+import java.util.Map;
+import org.eclipse.ecf.filetransfer.*;
+import org.eclipse.ecf.filetransfer.identity.IFileID;
+
+/**
+ * Event sent to {@link IFileTransferListener} associated with
+ * {@link IIncomingFileTransfer} instances
+ *
+ */
+public interface IIncomingFileTransferReceiveStartEvent extends IIncomingFileTransferEvent {
+
+ /**
+ * Get IFileID for incoming file
+ *
+ * @return IFileID for this file transfer event. Will not be
+ * null.
+ */
+ public IFileID getFileID();
+
+ /**
+ * Get incoming file transfer object by specifying a local File instance to
+ * save the received contents to.
+ *
+ * @param localFileToSave
+ * the file on the local file system to receive and save the
+ * remote file. Must not be null. If the file
+ * already exists, its content will be overwritten by any data
+ * received.
+ * @return IIncomingFileTransfer the incoming file transfer object. Will not
+ * be null.
+ * @throws IOException
+ * if localFileToSave cannot be opened for writing
+ */
+ public IIncomingFileTransfer receive(File localFileToSave) throws IOException;
+
+ /**
+ * Just like {@link #receive(File)} but this method also give the caller
+ * a chance to provide a factory that creates the job that will perform the
+ * actual file transfer. The intended use for this is when the user of the
+ * framework needs more elaborate control over such jobs such as waiting for a
+ * group of parallel file transfers to complete. Such functionality can for
+ * instance exploit the Eclipse runtime concept of Job families.
+ *
+ * @param localFileToSave
+ * the file on the local file system to receive and save the
+ * remote file. Must not be null. If the file
+ * already exists, its content will be overwritten by any data
+ * received.
+ * @param fileTransferJob A subclass of {@link FileTransferJob} to use to run the actual transfer. If
+ * null, provider will create default implementation. NOTE: the given job should
+ * *not* be scheduled/started prior to being provided as a parameter to this method.
+ * @return IIncomingFileTransfer the incoming file transfer object. NOTE:
+ * the caller is responsible for calling
+ * {@link OutputStream#close()} on the OutputStream provided. If the
+ * stream provided is buffered, then
+ * {@link BufferedOutputStream#flush()} should be called to
+ * guaranteed that the data received is actually written to the
+ * given OutputStream.
+ * @throws IOException
+ * if streamToStore cannot be opened for writing
+ *
+ * @since 2.0
+ */
+ public IIncomingFileTransfer receive(File localFileToSave, FileTransferJob fileTransferJob) throws IOException;
+
+ /**
+ * Get incoming file transfer by specifying an OutputStream instance to save
+ * the received contents to. NOTE: the caller is responsible for calling
+ * {@link OutputStream#close()} on the OutputStream provided. If the stream
+ * provided is buffered, then {@link BufferedOutputStream#flush()} should be
+ * called to guaranteed that the data received is actually written to the
+ * given OutputStream.
+ *
+ * @param streamToStore
+ * the output stream to store the incoming file. Must not be
+ * null.
+ * @return IIncomingFileTransfer the incoming file transfer object. NOTE:
+ * the caller is responsible for calling
+ * {@link OutputStream#close()} on the OutputStream provided. If the
+ * stream provided is buffered, then
+ * {@link BufferedOutputStream#flush()} should be called to
+ * guaranteed that the data received is actually written to the
+ * given OutputStream.
+ * @throws IOException
+ * if streamToStore cannot be opened for writing
+ */
+ public IIncomingFileTransfer receive(OutputStream streamToStore) throws IOException;
+
+ /**
+ * Just like {@link #receive(OutputStream)} but this method also give the caller
+ * a chance to provide a factory that creates the job that will perform the
+ * actual file transfer. The intended use for this is when the user of the
+ * framework needs more elaborate control over such jobs such as waiting for a
+ * group of parallel file transfers to complete. Such functionality can for
+ * instance exploit the Eclipse runtime concept of Job families.
+ *
+ * @param streamToStore
+ * the output stream to store the incoming file. Must not be
+ * null.
+ * @param fileTransferJob A subclass of {@link FileTransferJob} to use to run the actual transfer. If
+ * null, provider will create default implementation. NOTE: the given job should
+ * *not* be scheduled/started prior to being provided as a parameter to this method.
+ * @return IIncomingFileTransfer the incoming file transfer object. NOTE:
+ * the caller is responsible for calling
+ * {@link OutputStream#close()} on the OutputStream provided. If the
+ * stream provided is buffered, then
+ * {@link BufferedOutputStream#flush()} should be called to
+ * guaranteed that the data received is actually written to the
+ * given OutputStream.
+ * @throws IOException
+ * if streamToStore cannot be opened for writing
+ *
+ * @since 2.0
+ */
+ public IIncomingFileTransfer receive(OutputStream streamToStore, FileTransferJob fileTransferJob) throws IOException;
+
+ /**
+ * Cancel incoming file transfer
+ */
+ public void cancel();
+
+ /**
+ * Get response headers.
+ * @return Map of response headers. null if no headers available.
+ * @since 4.0
+ */
+ public Map getResponseHeaders();
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferEvent.java
new file mode 100644
index 0000000000..6fc9de3d67
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferEvent.java
@@ -0,0 +1,28 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer.events;
+
+import org.eclipse.ecf.filetransfer.IOutgoingFileTransfer;
+
+/**
+ * Super interface for outgoing file transfer events
+ *
+ */
+public interface IOutgoingFileTransferEvent extends IFileTransferEvent {
+ /**
+ * Get {@link IOutgoingFileTransfer} source associated with this event
+ *
+ * @return IOutgoingFileTransfer that is source of this event. Will not be
+ * null.
+ */
+ public IOutgoingFileTransfer getSource();
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferResponseEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferResponseEvent.java
new file mode 100644
index 0000000000..6d2ee807e9
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferResponseEvent.java
@@ -0,0 +1,40 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ * Cloudsmith, Inc. - additional API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer.events;
+
+import org.eclipse.ecf.filetransfer.*;
+
+/**
+ * Asynchronous event sent to {@link IFileTransferListener} associated with
+ * {@link IOutgoingFileTransfer} instances when a response is received from the
+ * remote target (or provider times out).
+ *
+ */
+public interface IOutgoingFileTransferResponseEvent extends IOutgoingFileTransferEvent {
+ /**
+ * If request was accepted from remote target this method will return true,
+ * if rejected or failed returns false.
+ *
+ * @return true if request was accepted, false if rejected or failed
+ */
+ public boolean requestAccepted();
+
+ /**
+ * Set the {@link FileTransferJob} to use for the actual file transfer. This method only
+ * has effect if the {@link #requestAccepted()} returns true.
+ * @param job the job to use. If null, or this method is not called, then
+ * a default FileTransferJob is used. NOTE: the given job should
+ * *not* be scheduled/started prior to being provided as a parameter to this method.
+ */
+ public void setFileTransferJob(FileTransferJob job);
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferSendDataEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferSendDataEvent.java
new file mode 100644
index 0000000000..534da60a0b
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferSendDataEvent.java
@@ -0,0 +1,24 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer.events;
+
+import org.eclipse.ecf.filetransfer.IFileTransferListener;
+import org.eclipse.ecf.filetransfer.IOutgoingFileTransfer;
+
+/**
+ * Event sent to {@link IFileTransferListener} associated with
+ * {@link IOutgoingFileTransfer} instances when some data are received
+ *
+ */
+public interface IOutgoingFileTransferSendDataEvent extends IOutgoingFileTransferEvent {
+ // no methods for interface
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferSendDoneEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferSendDoneEvent.java
new file mode 100644
index 0000000000..0c5aff4547
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferSendDoneEvent.java
@@ -0,0 +1,25 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer.events;
+
+import org.eclipse.ecf.filetransfer.IFileTransferListener;
+import org.eclipse.ecf.filetransfer.IOutgoingFileTransfer;
+
+/**
+ * Event sent to {@link IFileTransferListener} associated with
+ * {@link IOutgoingFileTransfer} instances when the file transfer is complete
+ *
+ */
+public interface IOutgoingFileTransferSendDoneEvent extends IOutgoingFileTransferEvent {
+ // no methods for interface
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferSendPausedEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferSendPausedEvent.java
new file mode 100644
index 0000000000..8db1714723
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferSendPausedEvent.java
@@ -0,0 +1,21 @@
+/****************************************************************************
+ * Copyright (c) 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer.events;
+
+/**
+ *
+ */
+public interface IOutgoingFileTransferSendPausedEvent extends IOutgoingFileTransferEvent {
+ // no methods for interface
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferSendResumedEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferSendResumedEvent.java
new file mode 100644
index 0000000000..8f426aff38
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IOutgoingFileTransferSendResumedEvent.java
@@ -0,0 +1,22 @@
+/****************************************************************************
+ * Copyright (c) 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer.events;
+
+/**
+ *
+ */
+public interface IOutgoingFileTransferSendResumedEvent extends IOutgoingFileTransferEvent {
+ // no methods for interface
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IRemoteFileSystemBrowseEvent.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IRemoteFileSystemBrowseEvent.java
new file mode 100644
index 0000000000..8c0a695dc4
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/events/IRemoteFileSystemBrowseEvent.java
@@ -0,0 +1,41 @@
+/****************************************************************************
+ * Copyright (c) 2007, 2009 Composent, Inc., IBM and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ * Henrich Kraemer - bug 263613, [transport] Update site contacting / downloading is not cancelable
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer.events;
+
+import org.eclipse.ecf.filetransfer.IRemoteFile;
+
+/**
+ * Event that indicates that a directory list is available via {@link #getRemoteFiles()}.
+ * null.
+ * @since 5.0
+ */
+ public static FileIDFactory getDefault() {
+ return instance;
+ }
+
+ /**
+ * Create an IFileID from a Namespace and a String.
+ *
+ * @param namespace
+ * the namespace to use to create the IFileID. Can use
+ * {@link IRetrieveFileTransferContainerAdapter#getRetrieveNamespace()}.
+ * Must not be null.
+ * @param remoteFile
+ * the remote filename to use. Must not be null.
+ * @return IFileID instance. Will not return null.
+ * @throws FileCreateException
+ * thrown if some problem creating IFileID from given namespace
+ * and filename
+ */
+ public IFileID createFileID(Namespace namespace, URL remoteFile) throws FileCreateException {
+ return createFileID(namespace, new Object[] {remoteFile});
+ }
+
+ /**
+ * Create an IFileID from a Namespace and a String.
+ *
+ * @param namespace
+ * the namespace to use to create the IFileID. Can use
+ * {@link IRetrieveFileTransferContainerAdapter#getRetrieveNamespace()}.
+ * Must not be null.
+ * @param remoteFile
+ * the remote filename to use. Must not be null.
+ * @return IFileID instance. Will not return null.
+ * @throws FileCreateException
+ * thrown if some problem creating IFileID from given namespace
+ * and filename
+ */
+ public IFileID createFileID(Namespace namespace, String remoteFile) throws FileCreateException {
+ return createFileID(namespace, new Object[] {remoteFile});
+ }
+
+ /**
+ * Create an IFileID from a Namespace and a String.
+ *
+ * @param namespace
+ * the namespace to use to create the IFileID. Can use
+ * {@link IRetrieveFileTransferContainerAdapter#getRetrieveNamespace()}.
+ * Must not be null.
+ * @param remoteFile
+ * the remote resource identifier to use. Must not be null.
+ * @return IFileID instance. Will not return null.
+ * @throws FileCreateException
+ * thrown if some problem creating IFileID from given namespace
+ * and filename
+ * @since 5.0
+ */
+ public IFileID createFileID(Namespace namespace, URI remoteFile) throws FileCreateException {
+ return createFileID(namespace, new Object[] {remoteFile});
+ }
+
+ /**
+ * Create an IFileID from a Namespace and a String.
+ *
+ * @param namespace
+ * the namespace to use to create the IFileID. Can use
+ * {@link IRetrieveFileTransferContainerAdapter#getRetrieveNamespace()}.
+ * Must not be null.
+ * @param arguments
+ * Object [] of arguments to use to create file ID. These
+ * arguments will be passed to the
+ * {@link Namespace#createInstance(Object[])} method of the
+ * appropriate Namespace setup by the provider
+ * @return IFileID instance. Will not return null.
+ * @throws FileCreateException
+ * thrown if some problem creating IFileID from given namespace
+ * and filename
+ */
+ public IFileID createFileID(Namespace namespace, Object[] arguments) throws FileCreateException {
+ Trace.entering(Activator.PLUGIN_ID, FileTransferDebugOptions.METHODS_ENTERING, this.getClass(), "createFileID", new Object[] {namespace, arguments}); //$NON-NLS-1$
+ try {
+ IFileID result = (IFileID) IDFactory.getDefault().createID(namespace, arguments);
+ Trace.exiting(Activator.PLUGIN_ID, FileTransferDebugOptions.METHODS_EXITING, this.getClass(), "createFileID", result); //$NON-NLS-1$
+ return result;
+ } catch (Exception e) {
+ Trace.throwing(Activator.PLUGIN_ID, FileTransferDebugOptions.EXCEPTIONS_THROWING, FileIDFactory.class, "createFileID", e); //$NON-NLS-1$
+ throw new FileCreateException("Exception in createFileID", e); //$NON-NLS-1$
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/identity/IFileID.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/identity/IFileID.java
new file mode 100644
index 0000000000..16eb5ffcfa
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/identity/IFileID.java
@@ -0,0 +1,49 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer.identity;
+
+import java.net.*;
+import org.eclipse.ecf.core.identity.ID;
+
+/**
+ * ID for a remote file.
+ *
+ */
+public interface IFileID extends ID {
+
+ /**
+ * Get the file name from this IFileID. This will return just the filename
+ * portion of a more complex file ID, e.g. index.html from IFileID created
+ * with value "http://www.composent.com/index.html"
+ *
+ * @return String just the file name and extension (if any) for this given
+ * IFileID. Will not be null.
+ */
+ public String getFilename();
+
+ /**
+ * Get the url associated with the file identified by this IFileID.
+ *
+ * @return URL associated with this IFileID. Will not be null.
+ * @exception MalformedURLException thrown if URL cannot be created for this IFileID
+ */
+ public URL getURL() throws MalformedURLException;
+
+ /**
+ * Get the URI associated with the file identified by this IFileID.
+ *
+ * @return URI associated with this IFileID. Will not be null.
+ * @throws URISyntaxException thrown if URI cannot be created for this IFileID.
+ * @since 5.0
+ */
+ public URI getURI() throws URISyntaxException;
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/identity/IFileIDFactory.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/identity/IFileIDFactory.java
new file mode 100644
index 0000000000..240e68e4f4
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/identity/IFileIDFactory.java
@@ -0,0 +1,92 @@
+/****************************************************************************
+ * Copyright (c) 2010 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.filetransfer.identity;
+
+import java.net.URI;
+import java.net.URL;
+import org.eclipse.ecf.core.identity.Namespace;
+import org.eclipse.ecf.filetransfer.IRetrieveFileTransferContainerAdapter;
+
+/**
+ * @since 5.0
+ */
+public interface IFileIDFactory {
+
+ /**
+ * Create an IFileID from a Namespace and a String.
+ *
+ * @param namespace
+ * the namespace to use to create the IFileID. Can use
+ * {@link IRetrieveFileTransferContainerAdapter#getRetrieveNamespace()}.
+ * Must not be null.
+ * @param remoteFile
+ * the remote filename to use. Must not be null.
+ * @return IFileID instance. Will not return null.
+ * @throws FileCreateException
+ * thrown if some problem creating IFileID from given namespace
+ * and filename
+ */
+ public IFileID createFileID(Namespace namespace, URL remoteFile) throws FileCreateException;
+
+ /**
+ * Create an IFileID from a Namespace and a String.
+ *
+ * @param namespace
+ * the namespace to use to create the IFileID. Can use
+ * {@link IRetrieveFileTransferContainerAdapter#getRetrieveNamespace()}.
+ * Must not be null.
+ * @param remoteFile
+ * the remote filename to use. Must not be null.
+ * @return IFileID instance. Will not return null.
+ * @throws FileCreateException
+ * thrown if some problem creating IFileID from given namespace
+ * and filename
+ */
+ public IFileID createFileID(Namespace namespace, String remoteFile) throws FileCreateException;
+
+ /**
+ * Create an IFileID from a Namespace and a String.
+ *
+ * @param namespace
+ * the namespace to use to create the IFileID. Can use
+ * {@link IRetrieveFileTransferContainerAdapter#getRetrieveNamespace()}.
+ * Must not be null.
+ * @param remoteFile
+ * the remote resource identifier to use. Must not be null.
+ * @return IFileID instance. Will not return null.
+ * @throws FileCreateException
+ * thrown if some problem creating IFileID from given namespace
+ * and filename
+ * @since 5.0
+ */
+ public IFileID createFileID(Namespace namespace, URI remoteFile) throws FileCreateException;
+
+ /**
+ * Create an IFileID from a Namespace and a String.
+ *
+ * @param namespace
+ * the namespace to use to create the IFileID. Can use
+ * {@link IRetrieveFileTransferContainerAdapter#getRetrieveNamespace()}.
+ * Must not be null.
+ * @param arguments
+ * Object [] of arguments to use to create file ID. These
+ * arguments will be passed to the
+ * {@link Namespace#createInstance(Object[])} method of the
+ * appropriate Namespace setup by the provider
+ * @return IFileID instance. Will not return null.
+ * @throws FileCreateException
+ * thrown if some problem creating IFileID from given namespace
+ * and filename
+ */
+ public IFileID createFileID(Namespace namespace, Object[] arguments) throws FileCreateException;
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/IRemoteFileSystemBrowser.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/IRemoteFileSystemBrowser.java
new file mode 100644
index 0000000000..ffa3ddbcfe
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/IRemoteFileSystemBrowser.java
@@ -0,0 +1,23 @@
+/****************************************************************************
+ * Copyright (c) 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer.service;
+
+import org.eclipse.ecf.filetransfer.IRemoteFileSystemBrowserContainerAdapter;
+
+/**
+ * Remote file system browser service interface. See {@link IRemoteFileSystemBrowserContainerAdapter}
+ */
+public interface IRemoteFileSystemBrowser extends IRemoteFileSystemBrowserContainerAdapter {
+ // Methods in super interface
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/IRemoteFileSystemBrowserFactory.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/IRemoteFileSystemBrowserFactory.java
new file mode 100644
index 0000000000..edfa47c216
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/IRemoteFileSystemBrowserFactory.java
@@ -0,0 +1,29 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer.service;
+
+/**
+ * Remote file browser factory. This service interface is used by clients to
+ * create a new IRemoteFileSystemBrowser instance.
+ */
+public interface IRemoteFileSystemBrowserFactory {
+
+ /**
+ * Get new instance of IRemoteFileSystemBrowser.
+ *
+ * @return IRemoteFileSystemBrowser for initiating a retrieval of a remote file.
+ */
+ public IRemoteFileSystemBrowser newInstance();
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/IRetrieveFileTransfer.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/IRetrieveFileTransfer.java
new file mode 100644
index 0000000000..a0f7cd418c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/IRetrieveFileTransfer.java
@@ -0,0 +1,21 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer.service;
+
+import org.eclipse.ecf.filetransfer.IRetrieveFileTransferContainerAdapter;
+
+public interface IRetrieveFileTransfer extends IRetrieveFileTransferContainerAdapter {
+ // no methods for interface
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/IRetrieveFileTransferFactory.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/IRetrieveFileTransferFactory.java
new file mode 100644
index 0000000000..50c0b6648d
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/IRetrieveFileTransferFactory.java
@@ -0,0 +1,29 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer.service;
+
+/**
+ * Retrieve file transfer factory. This service interface is used by clients to
+ * create a new IRetrieveFileTransfer instance.
+ */
+public interface IRetrieveFileTransferFactory {
+
+ /**
+ * Get new instance of IRetrieveFileTransfer.
+ *
+ * @return IRetrieveFileTransfer for initiating a retrieval of a remote file.
+ */
+ public IRetrieveFileTransfer newInstance();
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/ISendFileTransfer.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/ISendFileTransfer.java
new file mode 100644
index 0000000000..b9cd2cb3bf
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/ISendFileTransfer.java
@@ -0,0 +1,21 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer.service;
+
+import org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter;
+
+public interface ISendFileTransfer extends ISendFileTransferContainerAdapter {
+ // no methods for interface
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/ISendFileTransferFactory.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/ISendFileTransferFactory.java
new file mode 100644
index 0000000000..e5b510848c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/filetransfer/service/ISendFileTransferFactory.java
@@ -0,0 +1,30 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.filetransfer.service;
+
+/**
+ * Send file transfer factory. This service interface is used by clients to
+ * create a new ISendFileTransfer instance, used to send file to remote
+ * clients.
+ */
+public interface ISendFileTransferFactory {
+
+ /**
+ * Get new instance of ISendFileTransfer.
+ *
+ * @return ISendFileTransfer for initiating send of a local file.
+ */
+ public ISendFileTransfer newInstance();
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/core/ECFDebugOptions.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/core/ECFDebugOptions.java
new file mode 100644
index 0000000000..6ae8fc32bb
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/core/ECFDebugOptions.java
@@ -0,0 +1,27 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.internal.core;
+
+public interface ECFDebugOptions {
+
+ public static final String DEBUG = ECFPlugin.PLUGIN_ID + "/debug"; //$NON-NLS-1$
+
+ public static final String EXCEPTIONS_CATCHING = DEBUG + "/exceptions/catching"; //$NON-NLS-1$
+
+ public static final String EXCEPTIONS_THROWING = DEBUG + "/exceptions/throwing"; //$NON-NLS-1$
+
+ public static final String METHODS_ENTERING = DEBUG + "/methods/entering"; //$NON-NLS-1$
+
+ public static final String METHODS_EXITING = DEBUG + "/methods/exiting"; //$NON-NLS-1$
+
+ public static final String BUNDLECLASSRESOLVER = DEBUG + "/bundleclassresolver"; //$NON-NLS-1$
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/core/ECFPlugin.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/core/ECFPlugin.java
new file mode 100644
index 0000000000..dbd24f72ab
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/internal/core/ECFPlugin.java
@@ -0,0 +1,583 @@
+/****************************************************************************
+ * Copyright (c) 2004, 2020 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.internal.core;
+
+import java.util.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.ecf.core.*;
+import org.eclipse.ecf.core.identity.ID;
+import org.eclipse.ecf.core.provider.IContainerInstantiator;
+import org.eclipse.ecf.core.security.ECFSSLContextFactory;
+import org.eclipse.ecf.core.security.SSLContextFactory;
+import org.eclipse.ecf.core.start.ECFStartJob;
+import org.eclipse.ecf.core.start.IECFStart;
+import org.eclipse.ecf.core.util.*;
+import org.eclipse.ecf.internal.core.identity.Activator;
+import org.osgi.framework.*;
+import org.osgi.service.log.LogService;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+public class ECFPlugin implements BundleActivator {
+
+ public static final String PLUGIN_ID = "org.eclipse.ecf"; //$NON-NLS-1$
+
+ private static final String ECFNAMESPACE = PLUGIN_ID;
+
+ private static final String CONTAINER_FACTORY_NAME = "containerFactory"; //$NON-NLS-1$
+
+ private static final String CONTAINER_FACTORY_EPOINT = ECFNAMESPACE + "." + CONTAINER_FACTORY_NAME; //$NON-NLS-1$
+
+ private static final String STARTUP_NAME = "start"; //$NON-NLS-1$
+
+ public static final String START_EPOINT = ECFNAMESPACE + "." + STARTUP_NAME; //$NON-NLS-1$
+
+ public static final String PLUGIN_RESOURCE_BUNDLE = ECFNAMESPACE + ".ECFPluginResources"; //$NON-NLS-1$
+
+ public static final String CLASS_ATTRIBUTE = "class"; //$NON-NLS-1$
+
+ public static final String NAME_ATTRIBUTE = "name"; //$NON-NLS-1$
+
+ public static final String DESCRIPTION_ATTRIBUTE = "description"; //$NON-NLS-1$
+
+ public static final String VALUE_ATTRIBUTE = "value"; //$NON-NLS-1$
+
+ public static final String SERVER_ATTRIBUTE = "server"; //$NON-NLS-1$
+
+ public static final String HIDDEN_ATTRIBUTE = "hidden"; //$NON-NLS-1$
+
+ public static final String ASYNCH_ATTRIBUTE = "asynchronous"; //$NON-NLS-1$
+
+ public static final String CONTAINER_NAME = "container"; //$NON-NLS-1$
+
+ public static final String CONTAINER_EPOINT = ECFNAMESPACE + "." + CONTAINER_NAME; //$NON-NLS-1$
+
+ public static final String FACTORY_ATTRIBUTE = "factoryName"; //$NON-NLS-1$
+
+ public static final String ID_ATTRIBUTE = "containerId"; //$NON-NLS-1$
+
+ public static final String PARAMETER_ELEMENT = "parameter"; //$NON-NLS-1$
+
+ public static final String PARAMETER_NAME = "name"; //$NON-NLS-1$
+
+ public static final String PARAMETER_VALUE = "value"; //$NON-NLS-1$
+
+ // The shared instance.
+ private static ECFPlugin plugin;
+
+ BundleContext context = null;
+
+ private Map disposables = new HashMap(1);
+
+ // This is Object rather than IExtensionRegistryManager to avoid loading
+ // IRegistryChangeListener class (optional)
+ Object registryManager = null;
+
+ private ServiceRegistration containerFactoryServiceRegistration;
+
+ private ServiceRegistration containerManagerServiceRegistration;
+
+ private ServiceTracker logServiceTracker = null;
+
+ private LogService logService = null;
+
+ private AdapterManagerTracker adapterManagerTracker = null;
+
+ private BundleActivator ecfTrustManager;
+
+ private ServiceRegistration sslContextFactoryRegistration;
+
+ private ECFSSLContextFactory ecfSSLContextFactory;
+
+ /**
+ * Returns the shared instance.
+ * @return ECFPlugin
+ */
+ public synchronized static ECFPlugin getDefault() {
+ if (plugin == null)
+ plugin = new ECFPlugin();
+ return plugin;
+ }
+
+ public BundleContext getContext() {
+ return context;
+ }
+
+ public ECFPlugin() {
+ // null constructor
+ }
+
+ void disposeContainersForDescription(ContainerTypeDescription description) {
+ String descriptionName = description.getName();
+ IContainerManager cm = (IContainerManager) ContainerFactory.getDefault();
+ Listtrue if the given factory was set for this protocol, false if not
+ */
+ public boolean setRetrieveFileTransferFactory(String protocol, String id, IRetrieveFileTransferFactory factory, int priority);
+
+ /**
+ * true the factory is added as a URI rather than a URL, meaning that no URLStreamHandler is
+ * registered for the given protocol. This is in contrast to the {@link #setRetrieveFileTransferFactory(String, String, IRetrieveFileTransferFactory, int)},
+ * which automatically registers an URLStreamHandler for the given protocol. If false, URLs will be used and an URLStreamHandler will be registered for the
+ * given protocol factory. NOTE: If this flag is true, providers that attempt to access IFileID.getURL() may be unable to do so, since the
+ * URI may not be successfully parsed as a URL.
+ *
+ * @return true if the given factory was set for this protocol, false if not
+ */
+ public boolean setRetrieveFileTransferFactory(String protocol, String id, IRetrieveFileTransferFactory factory, int priority, boolean uri);
+
+ /**
+ * Get the factory id of the active factory for the given protocol. If the given protocol does not have an
+ * active factory, returns null.
+ *
+ * @param protocol the protocol to get the id for (e.g. http/https)
+ *
+ * @return id of the factory associated with the given protocol
+ */
+ public String getRetrieveFileTransferFactoryId(String protocol);
+
+ /**
+ * Get the priority of the active factory for the given protocol. If the given protocol does not have an active factory, returns -1.
+ *
+ * @param protocol the protocol to get the priority for (e.g. http/https)
+ *
+ * @return int priority for the given protocol
+ */
+ public int getRetrieveFileTransferPriority(String protocol);
+
+ /**
+ * Remove the factory with the given id.
+ * @param id the id of the factory to remove.
+ * @return true if a factory was removed. false otherwise.
+ */
+ public boolean removeRetrieveFileTransferFactory(String id);
+
+ /**
+ * true if the given factory was set for this protocol, false if not
+ */
+ public boolean setBrowseFileTransferFactory(String protocol, String id, IRemoteFileSystemBrowserFactory factory, int priority);
+
+ /**
+ * true the factory is added as a URI rather than a URL, meaning that no URLStreamHandler is
+ * registered for the given protocol. This is in contrast to the {@link #setRetrieveFileTransferFactory(String, String, IRetrieveFileTransferFactory, int)},
+ * which automatically registers an URLStreamHandler for the given protocol. If false, URLs will be used and an URLStreamHandler will be registered for the
+ * given protocol factory. NOTE: If this flag is true, providers that attempt to access IFileID.getURL() may be unable to do so, since the
+ * URI may not be successfully parsed as a URL.
+ *
+ * @return true if the given factory was set for this protocol, false if not
+ */
+ public boolean setBrowseFileTransferFactory(String protocol, String id, IRemoteFileSystemBrowserFactory factory, int priority, boolean uri);
+
+ /**
+ * Get the factory id of the active factory for the given protocol. If the given protocol does not have an
+ * active factory, returns null.
+ *
+ * @param protocol the protocol to get the id for (e.g. http/https)
+ *
+ * @return id of the factory associated with the given protocol
+ */
+ public String getBrowseFileTransferFactoryId(String protocol);
+
+ /**
+ * Get the priority of the active factory for the given protocol. If the given protocol does not have an active factory, returns -1.
+ *
+ * @param protocol the protocol to get the priority for (e.g. http/https)
+ *
+ * @return int priority for the given protocol
+ */
+ public int getBrowseFileTransferPriority(String protocol);
+
+ /**
+ * Remove the factory with the given id.
+ * @param id the id of the factory to remove.
+ * @return true if a factory was removed. false otherwise.
+ */
+ public boolean removeBrowseFileTransferFactory(String id);
+
+ /**
+ * true if the given factory was set for this protocol, false if not
+ */
+ public boolean setSendFileTransferFactory(String protocol, String id, ISendFileTransferFactory factory, int priority);
+
+ /**
+ * true the factory is added as a URI rather than a URL, meaning that no URLStreamHandler is
+ * registered for the given protocol. This is in contrast to the {@link #setRetrieveFileTransferFactory(String, String, IRetrieveFileTransferFactory, int)},
+ * which automatically registers an URLStreamHandler for the given protocol. If false, URLs will be used and an URLStreamHandler will be registered for the
+ * given protocol factory. NOTE: If this flag is true, providers that attempt to access IFileID.getURL() may be unable to do so, since the
+ * URI may not be successfully parsed as a URL.
+ *
+ * @return true if the given factory was set for this protocol, false if not
+ */
+ public boolean setSendFileTransferFactory(String protocol, String id, ISendFileTransferFactory factory, int priority, boolean uri);
+
+ /**
+ * Get the factory id of the active factory for the given protocol. If the given protocol does not have an
+ * active factory, returns null.
+ *
+ * @param protocol the protocol to get the id for (e.g. http/https)
+ *
+ * @return id of the factory associated with the given protocol
+ */
+ public String getSendFileTransferFactoryId(String protocol);
+
+ /**
+ * Get the priority of the active factory for the given protocol. If the given protocol does not have an active factory, returns -1.
+ *
+ * @param protocol the protocol to get the priority for (e.g. http/https)
+ *
+ * @return int priority for the given protocol
+ */
+ public int getSendFileTransferPriority(String protocol);
+
+ /**
+ * Remove the factory with the given id.
+ * @param id the id of the factory to remove.
+ * @return true if a factory was removed. false otherwise.
+ */
+ public boolean removeSendFileTransferFactory(String id);
+
+ /**
+ * Reinitialized protocol to factory mapping defined via extension registry/extension points.
+ * @return true if reinitialization succeeds, false if not
+ */
+ public boolean reinitialize();
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/AbstractFileSystemBrowser.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/AbstractFileSystemBrowser.java
new file mode 100644
index 0000000000..2dfe8de688
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/AbstractFileSystemBrowser.java
@@ -0,0 +1,267 @@
+/****************************************************************************
+ * Copyright (c) 2007, 2010 Composent, Inc., IBM and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ * Henrich Kraemer - bug 263613, [transport] Update site contacting / downloading is not cancelable
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.provider.filetransfer.browse;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
+import org.eclipse.core.net.proxy.IProxyData;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.ecf.core.security.IConnectContext;
+import org.eclipse.ecf.core.util.Proxy;
+import org.eclipse.ecf.filetransfer.IRemoteFile;
+import org.eclipse.ecf.filetransfer.IRemoteFileSystemListener;
+import org.eclipse.ecf.filetransfer.IRemoteFileSystemRequest;
+import org.eclipse.ecf.filetransfer.UserCancelledException;
+import org.eclipse.ecf.filetransfer.events.IRemoteFileSystemBrowseEvent;
+import org.eclipse.ecf.filetransfer.events.IRemoteFileSystemEvent;
+import org.eclipse.ecf.filetransfer.identity.IFileID;
+import org.eclipse.ecf.internal.provider.filetransfer.Activator;
+import org.eclipse.ecf.internal.provider.filetransfer.Messages;
+import org.eclipse.ecf.provider.filetransfer.util.ProxySetupHelper;
+
+/**
+ * Abstract class for browsing an efs file system.
+ */
+public abstract class AbstractFileSystemBrowser {
+
+ protected IFileID fileID = null;
+ protected IRemoteFileSystemListener listener = null;
+
+ private Exception exception = null;
+ protected IRemoteFile[] remoteFiles = null;
+
+ protected Proxy proxy;
+ protected URL directoryOrFile;
+
+ protected IConnectContext connectContext;
+
+ protected DirectoryJob job = null;
+
+ Object lock = new Object();
+
+ protected class DirectoryJob extends Job {
+
+ private IRemoteFileSystemRequest request;
+
+ public DirectoryJob() {
+ super(fileID.getName());
+ }
+
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ if (monitor.isCanceled())
+ throw newUserCancelledException();
+ runRequest();
+ } catch (Exception e) {
+ AbstractFileSystemBrowser.this.setException(e);
+ } finally {
+ listener.handleRemoteFileEvent(createRemoteFileEvent());
+ cleanUp();
+ }
+ return Status.OK_STATUS;
+ }
+
+ public void setRequest(IRemoteFileSystemRequest request) {
+ this.request = request;
+ }
+
+ public IRemoteFileSystemRequest getRequest() {
+ return request;
+ }
+
+ protected void canceling() {
+ request.cancel();
+ }
+
+ }
+
+ protected void cancel() {
+ synchronized (lock) {
+ if (job != null) {
+ job.cancel();
+ }
+ }
+
+ }
+
+ protected void cleanUp() {
+ synchronized (lock) {
+ job = null;
+ }
+ }
+
+ /**
+ * Run the actual request. This method is called within the job created to actually get the
+ * directory or file information.
+ * @throws Exception if some problem with making the request or receiving response to the request.
+ */
+ protected abstract void runRequest() throws Exception;
+
+ public AbstractFileSystemBrowser(IFileID directoryOrFileID, IRemoteFileSystemListener listener, URL url, IConnectContext connectContext, Proxy proxy) {
+ Assert.isNotNull(directoryOrFileID);
+ this.fileID = directoryOrFileID;
+ Assert.isNotNull(listener);
+ this.listener = listener;
+ this.directoryOrFile = url;
+ this.connectContext = connectContext;
+ this.proxy = proxy;
+ }
+
+ public abstract class RemoteFileSystemRequest implements IRemoteFileSystemRequest {
+ public void cancel() {
+ synchronized (lock) {
+ if (job != null)
+ job.cancel();
+ }
+ }
+
+ public IFileID getFileID() {
+ return fileID;
+ }
+
+ public IRemoteFileSystemListener getRemoteFileListener() {
+ return listener;
+ }
+
+ }
+
+ public IRemoteFileSystemRequest sendBrowseRequest() {
+ job = new DirectoryJob();
+
+ IRemoteFileSystemRequest request = createRemoteFileSystemRequest();
+ job.setRequest(request);
+ if (Job.getJobManager().isSuspended()) {
+ job.run(new NullProgressMonitor());
+ } else {
+ job.schedule();
+ }
+ return request;
+ }
+
+ protected IRemoteFileSystemRequest createRemoteFileSystemRequest() {
+ return new RemoteFileSystemRequest() {
+ public null.
+ * @param proxies the proxies to select from. May be null or array of length 0.
+ * @return proxy data selected from the proxies provided.
+ */
+ protected IProxyData selectProxyFromProxies(String protocol, IProxyData[] proxies) {
+ try {
+ return ProxySetupHelper.selectProxyFromProxies(protocol, proxies);
+ } catch (NoClassDefFoundError e) {
+ // If the proxy API is not available a NoClassDefFoundError will be thrown here.
+ // If that happens then we just want to continue on.
+ Activator.logNoProxyWarning(e);
+ return null;
+ }
+ }
+
+ protected void setupProxies() {
+ // If it's been set directly (via ECF API) then this overrides platform settings
+ if (proxy == null) {
+ try {
+ proxy = ProxySetupHelper.getProxy(directoryOrFile.toExternalForm());
+ } catch (NoClassDefFoundError e) {
+ // If the proxy API is not available a NoClassDefFoundError will be thrown here.
+ // If that happens then we just want to continue on.
+ Activator.logNoProxyWarning(e);
+ }
+ }
+ if (proxy != null)
+ setupProxy(proxy);
+ }
+
+ protected synchronized void setException(Exception exception) {
+ this.exception = exception;
+ }
+
+ protected synchronized Exception getException() {
+ return this.exception;
+ }
+
+ protected synchronized boolean isCanceled() {
+ return exception instanceof UserCancelledException;
+ }
+
+ protected synchronized void setCanceled(Exception e) {
+ if (e instanceof UserCancelledException) {
+ exception = e;
+ } else {
+ exception = newUserCancelledException();
+ }
+ }
+
+ protected UserCancelledException newUserCancelledException() {
+ return new UserCancelledException(Messages.AbstractRetrieveFileTransfer_Exception_User_Cancelled);
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/LocalFileSystemBrowser.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/LocalFileSystemBrowser.java
new file mode 100644
index 0000000000..3b8cfaf872
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/LocalFileSystemBrowser.java
@@ -0,0 +1,65 @@
+/****************************************************************************
+ * Copyright (c) 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.provider.filetransfer.browse;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import org.eclipse.ecf.core.util.Proxy;
+import org.eclipse.ecf.filetransfer.IRemoteFileSystemListener;
+import org.eclipse.ecf.filetransfer.RemoteFileSystemException;
+import org.eclipse.ecf.filetransfer.identity.IFileID;
+import org.eclipse.ecf.internal.provider.filetransfer.Messages;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * A class for asynchronously browsing a {@link java.io.File}-based filesystem.
+ */
+public class LocalFileSystemBrowser extends AbstractFileSystemBrowser {
+
+ protected File local;
+
+ /**
+ * @param listener listener
+ * @param directoryID2 remote directory
+ * @throws RemoteFileSystemException if some problem
+ */
+ public LocalFileSystemBrowser(IFileID directoryID2, IRemoteFileSystemListener listener) throws RemoteFileSystemException {
+ super(directoryID2, listener, null, null, null);
+ try {
+ local = new File(directoryID2.getURL().getPath());
+ } catch (MalformedURLException e) {
+ throw new RemoteFileSystemException(e);
+ }
+ if (!local.exists())
+ throw new RemoteFileSystemException(NLS.bind(Messages.FileSystemBrowser_EXCEPTION_DIRECTORY_DOES_NOT_EXIST, local));
+ }
+
+ protected void runRequest() throws Exception {
+ if (local.isDirectory()) {
+ File[] files = local.listFiles();
+ remoteFiles = new LocalRemoteFile[files.length];
+ for (int i = 0; i < files.length; i++) {
+ remoteFiles[i] = new LocalRemoteFile(files[i]);
+ }
+ } else {
+ remoteFiles = new LocalRemoteFile[1];
+ remoteFiles[0] = new LocalRemoteFile(local);
+ }
+ }
+
+ protected void setupProxy(Proxy proxy) {
+ // nothing
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/LocalRemoteFile.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/LocalRemoteFile.java
new file mode 100644
index 0000000000..7d64236305
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/browse/LocalRemoteFile.java
@@ -0,0 +1,120 @@
+/****************************************************************************
+ * Copyright (c) 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.provider.filetransfer.browse;
+
+import java.io.File;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IAdapterManager;
+import org.eclipse.ecf.core.identity.IDFactory;
+import org.eclipse.ecf.filetransfer.IRemoteFile;
+import org.eclipse.ecf.filetransfer.IRemoteFileAttributes;
+import org.eclipse.ecf.filetransfer.IRemoteFileInfo;
+import org.eclipse.ecf.filetransfer.identity.FileIDFactory;
+import org.eclipse.ecf.filetransfer.identity.IFileID;
+import org.eclipse.ecf.internal.provider.filetransfer.Activator;
+import org.eclipse.ecf.provider.filetransfer.identity.FileTransferNamespace;
+
+/**
+ * Local representation of an {@link IRemoteFile}.
+ */
+public class LocalRemoteFile implements IRemoteFile {
+
+ File file = null;
+
+ IRemoteFileInfo info;
+
+ /**
+ * @param file the file
+ */
+ public LocalRemoteFile(File file) {
+ this.file = file;
+ Assert.isNotNull(file);
+ this.info = new IRemoteFileInfo() {
+
+ IRemoteFileAttributes attributes = new LocalRemoteFileAttributes(LocalRemoteFile.this.file);
+
+ public IRemoteFileAttributes getAttributes() {
+ return attributes;
+ }
+
+ public long getLastModified() {
+ return LocalRemoteFile.this.file.lastModified();
+ }
+
+ public long getLength() {
+ return LocalRemoteFile.this.file.length();
+ }
+
+ public String getName() {
+ return LocalRemoteFile.this.file.getName();
+ }
+
+ public boolean isDirectory() {
+ return LocalRemoteFile.this.file.isDirectory();
+ }
+
+ public void setAttributes(IRemoteFileAttributes attributes) {
+ // can't set attributes
+ }
+
+ public void setLastModified(long time) {
+ // can't set post hoc
+ }
+
+ public void setName(String name) {
+ // Can't modify post hoc
+ }
+ };
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.filetransfer.IRemoteFile#getID()
+ */
+ public IFileID getID() {
+ try {
+ return FileIDFactory.getDefault().createFileID(IDFactory.getDefault().getNamespaceByName(FileTransferNamespace.PROTOCOL), file.toURL());
+ } catch (Exception e) {
+ // Should never happen
+ return null;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.filetransfer.IRemoteFile#getInfo()
+ */
+ public IRemoteFileInfo getInfo() {
+ return info;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+ */
+ public remoteFileContents and localFileContent
+ * must be non-null after successful completion of the
+ * implementation of this method.
+ *
+ * @throws SendFileTransferException if some problem
+ */
+ protected abstract void openStreams() throws SendFileTransferException;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#getOutgoingNamespace()
+ */
+ public Namespace getOutgoingNamespace() {
+ return IDFactory.getDefault().getNamespaceByName(FileTransferNamespace.PROTOCOL);
+ }
+
+ public IFileTransferListener getListener() {
+ return listener;
+ }
+
+ protected String createJobName() {
+ return getRemoteFileURL().toString();
+ }
+
+ protected void setupAndScheduleJob() {
+ if (fileTransferJob == null)
+ fileTransferJob = new FileTransferJob(createJobName());
+ fileTransferJob.setFileTransferRunnable(fileTransferRunnable);
+ fileTransferJob.setFileTransfer(this);
+ job = fileTransferJob;
+ job.schedule();
+ }
+
+ protected void fireSendStartEvent() {
+ listener.handleTransferEvent(new IOutgoingFileTransferResponseEvent() {
+
+ public String toString() {
+ final StringBuffer sb = new StringBuffer("IOutgoingFileTransferResponseEvent["); //$NON-NLS-1$
+ sb.append("isdone=").append(done).append(";"); //$NON-NLS-1$ //$NON-NLS-2$
+ sb.append("bytesSent=").append(bytesSent) //$NON-NLS-1$
+ .append("]"); //$NON-NLS-1$
+ return sb.toString();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.filetransfer.events.IOutgoingFileTransferResponseEvent#requestAccepted()
+ */
+ public boolean requestAccepted() {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.filetransfer.events.IOutgoingFileTransferEvent#getSource()
+ */
+ public IOutgoingFileTransfer getSource() {
+ return AbstractOutgoingFileTransfer.this;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.filetransfer.events.IOutgoingFileTransferResponseEvent#setFileTransferJob(org.eclipse.ecf.filetransfer.FileTransferJob)
+ */
+ public void setFileTransferJob(org.eclipse.ecf.filetransfer.FileTransferJob ftj) {
+ AbstractOutgoingFileTransfer.this.fileTransferJob = ftj;
+ }
+
+ });
+ }
+
+ protected abstract void setupProxy(Proxy proxy);
+
+ protected void setupProxies() {
+ // If it's been set directly (via ECF API) then this overrides platform settings
+ if (proxy == null) {
+ try {
+ proxy = ProxySetupHelper.getProxy(getRemoteFileURL().toExternalForm());
+ } catch (NoClassDefFoundError e) {
+ // If the proxy API is not available a NoClassDefFoundError will be thrown here.
+ // If that happens then we just want to continue on.
+ Activator.logNoProxyWarning(e);
+ }
+ }
+ if (proxy != null)
+ setupProxy(proxy);
+
+ }
+
+ /**
+ * Select a single proxy from a set of proxies available for the given host. This implementation
+ * selects in the following manner: 1) If proxies provided is null or array of 0 length, null
+ * is returned. If only one proxy is available (array of length 1) then the entry is returned.
+ * If proxies provided is length greater than 1, then if the type of a proxy in the array matches the given
+ * protocol (e.g. http, https), then the first matching proxy is returned. If the protocol does
+ * not match any of the proxies, then the *first* proxy (i.e. proxies[0]) is returned. Subclasses may
+ * override if desired.
+ *
+ * @param protocol the target protocol (e.g. http, https, scp, etc). Will not be null.
+ * @param proxies the proxies to select from. May be null or array of length 0.
+ * @return proxy data selected from the proxies provided.
+ */
+ protected IProxyData selectProxyFromProxies(String protocol, IProxyData[] proxies) {
+ if (proxies == null || proxies.length == 0)
+ return null;
+ // If only one proxy is available, then use that
+ if (proxies.length == 1)
+ return proxies[0];
+ // If more than one proxy is available, then if http/https protocol then look for that
+ // one...if not found then use first
+ if (protocol.equalsIgnoreCase("http")) { //$NON-NLS-1$
+ for (IProxyData proxie : proxies) {
+ if (proxie.getType().equals(IProxyData.HTTP_PROXY_TYPE)) {
+ return proxie;
+ }
+ }
+ } else if (protocol.equalsIgnoreCase("https")) { //$NON-NLS-1$
+ for (IProxyData proxie : proxies) {
+ if (proxie.getType().equals(IProxyData.HTTPS_PROXY_TYPE)) {
+ return proxie;
+ }
+ }
+ }
+ // If we haven't found it yet, then return the first one.
+ return proxies[0];
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#sendOutgoingRequest(org.eclipse.ecf.filetransfer.identity.IFileID, org.eclipse.ecf.filetransfer.IFileTransferInfo, org.eclipse.ecf.filetransfer.IFileTransferListener, java.util.Map)
+ */
+ public void sendOutgoingRequest(IFileID targetReceiver, IFileTransferInfo localFileToSend, IFileTransferListener transferListener, Map ops) throws SendFileTransferException {
+ Assert.isNotNull(targetReceiver, Messages.AbstractOutgoingFileTransfer_RemoteFileID_Not_Null);
+ Assert.isNotNull(transferListener, Messages.AbstractOutgoingFileTransfer_TransferListener_Not_Null);
+ Assert.isNotNull(localFileToSend, Messages.AbstractOutgoingFileTransfer_EXCEPTION_FILE_TRANSFER_INFO_NOT_NULL);
+ this.done = false;
+ this.bytesSent = 0;
+ this.exception = null;
+ this.fileTransferInfo = localFileToSend;
+ this.remoteFileID = targetReceiver;
+ this.options = ops;
+
+ try {
+ this.remoteFileURL = targetReceiver.getURL();
+ } catch (final MalformedURLException e) {
+ throw new SendFileTransferException(NLS.bind(Messages.AbstractOutgoingFileTransfer_MalformedURLException, targetReceiver), e);
+ }
+ this.listener = transferListener;
+ setupProxies();
+ openStreams();
+ fireSendStartEvent();
+ setupAndScheduleJob();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#sendOutgoingRequest(org.eclipse.ecf.filetransfer.identity.IFileID, java.io.File, org.eclipse.ecf.filetransfer.IFileTransferListener, java.util.Map)
+ */
+ public void sendOutgoingRequest(IFileID targetReceiver, final File localFileToSend, IFileTransferListener transferListener, Map ops) throws SendFileTransferException {
+ sendOutgoingRequest(targetReceiver, new FileTransferInfo(localFileToSend, null, null), transferListener, ops);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#addListener(org.eclipse.ecf.filetransfer.IIncomingFileTransferRequestListener)
+ */
+ public void addListener(IIncomingFileTransferRequestListener l) {
+ // Not needed
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#removeListener(org.eclipse.ecf.filetransfer.IIncomingFileTransferRequestListener)
+ */
+ public boolean removeListener(IIncomingFileTransferRequestListener l) {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#setConnectContextForAuthentication(org.eclipse.ecf.core.security.IConnectContext)
+ */
+ public void setConnectContextForAuthentication(IConnectContext connectContext) {
+ this.connectContext = connectContext;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#setProxy(org.eclipse.ecf.core.util.Proxy)
+ */
+ public void setProxy(Proxy proxy) {
+ this.proxy = proxy;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/outgoing/AbstractUrlConnectionOutgoingFileTransfer.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/outgoing/AbstractUrlConnectionOutgoingFileTransfer.java
new file mode 100644
index 0000000000..f15a2eb425
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/outgoing/AbstractUrlConnectionOutgoingFileTransfer.java
@@ -0,0 +1,146 @@
+/****************************************************************************
+ * Copyright (c) 2004 Composent, Inc.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors: Composent, Inc. - initial API and implementation
+ * Cloudsmith, Inc. - additional API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.provider.filetransfer.outgoing;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.ProtocolException;
+import java.net.URLConnection;
+import org.eclipse.ecf.core.util.Proxy;
+import org.eclipse.ecf.filetransfer.SendFileTransferException;
+import org.eclipse.ecf.filetransfer.service.ISendFileTransfer;
+import org.eclipse.ecf.internal.provider.filetransfer.Messages;
+import org.eclipse.ecf.provider.filetransfer.util.JREProxyHelper;
+import org.eclipse.osgi.util.NLS;
+
+public abstract class AbstractUrlConnectionOutgoingFileTransfer extends AbstractOutgoingFileTransfer implements ISendFileTransfer {
+
+ private static final int OK_RESPONSE_CODE = 200;
+
+ protected URLConnection urlConnection;
+
+ protected long lastModifiedTime = 0L;
+
+ protected int httpVersion = 1;
+
+ protected int responseCode = -1;
+
+ protected String responseMessage = null;
+
+ private JREProxyHelper proxyHelper = null;
+
+ public AbstractUrlConnectionOutgoingFileTransfer() {
+ super();
+ proxyHelper = new JREProxyHelper();
+ }
+
+ /**
+ * Setup and connect. Subclasses should override as appropriate. After calling is complete,
+ * the urlConnection member variable should be non-null, and ready to have it's
+ * getInputStream() method called.
+ *
+ * @throws IOException if the connection cannot be opened.
+ */
+ protected abstract void connect() throws IOException;
+
+ protected boolean isConnected() {
+ return (urlConnection != null);
+ }
+
+ public int getResponseCode() {
+ if (responseCode != -1)
+ return responseCode;
+ if (isHTTP()) {
+ final String response = urlConnection.getHeaderField(0);
+ if (response == null) {
+ responseCode = -1;
+ httpVersion = 1;
+ return responseCode;
+ }
+ if (response == null || !response.startsWith("HTTP/")) //$NON-NLS-1$
+ return -1;
+ response.trim();
+ final int mark = response.indexOf(" ") + 1; //$NON-NLS-1$
+ if (mark == 0)
+ return -1;
+ if (response.charAt(mark - 2) != '1')
+ httpVersion = 0;
+ int last = mark + 3;
+ if (last > response.length())
+ last = response.length();
+ responseCode = Integer.parseInt(response.substring(mark, last));
+ if (last + 1 <= response.length())
+ responseMessage = response.substring(last + 1);
+ } else {
+ responseCode = OK_RESPONSE_CODE;
+ responseMessage = "OK"; //$NON-NLS-1$
+ }
+
+ return responseCode;
+
+ }
+
+ private boolean isHTTP() {
+ final String protocol = getRemoteFileURL().getProtocol();
+ if (protocol.equalsIgnoreCase("http") || protocol.equalsIgnoreCase("https")) //$NON-NLS-1$ //$NON-NLS-2$
+ return true;
+ return false;
+ }
+
+ /**
+ * @param proxy2 the ECF proxy to setup
+ */
+ protected void setupProxy(final Proxy proxy2) {
+ proxyHelper.setupProxy(proxy2);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.provider.filetransfer.retrieve.AbstractRetrieveFileTransfer#openStreams()
+ */
+ protected void openStreams() throws SendFileTransferException {
+ try {
+ File localFile = getFileTransferInfo().getFile();
+ // Set input stream from local file
+ setInputStream(new BufferedInputStream(new FileInputStream(localFile)));
+ // Then connect
+ connect();
+ // Make PUT request
+ setOutputStream(urlConnection.getOutputStream());
+ } catch (final Exception e) {
+ throw new SendFileTransferException(NLS.bind(Messages.UrlConnectionOutgoingFileTransfer_EXCEPTION_COULD_NOT_CONNECT, getRemoteFileURL().toString()), e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.provider.filetransfer.retrieve.AbstractRetrieveFileTransfer#hardClose()
+ */
+ protected void hardClose() {
+ super.hardClose();
+ int rCode = getResponseCode();
+ if (rCode != OK_RESPONSE_CODE) {
+ exception = new ProtocolException(NLS.bind("{0} {1}", Integer.valueOf(rCode), responseMessage)); //$NON-NLS-1$
+ }
+ urlConnection = null;
+ if (proxyHelper != null) {
+ proxyHelper.dispose();
+ proxyHelper = null;
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/outgoing/LocalFileOutgoingFileTransfer.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/outgoing/LocalFileOutgoingFileTransfer.java
new file mode 100644
index 0000000000..3f6afa41e5
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/outgoing/LocalFileOutgoingFileTransfer.java
@@ -0,0 +1,71 @@
+/****************************************************************************
+ * Copyright (c) 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ * Cloudsmith, Inc. - additional API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.provider.filetransfer.outgoing;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.net.URL;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.ecf.core.util.Proxy;
+import org.eclipse.ecf.filetransfer.IFileTransferInfo;
+import org.eclipse.ecf.filetransfer.SendFileTransferException;
+import org.eclipse.ecf.internal.provider.filetransfer.Messages;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ *
+ */
+public class LocalFileOutgoingFileTransfer extends AbstractOutgoingFileTransfer {
+
+ public LocalFileOutgoingFileTransfer() {
+ // not needed
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.provider.filetransfer.outgoing.AbstractOutgoingFileTransfer#openStreams()
+ */
+ protected void openStreams() throws SendFileTransferException {
+ IFileTransferInfo localFileTransferInfo = getFileTransferInfo();
+ Assert.isNotNull(localFileTransferInfo);
+ // Setup input file
+ File inputFile = localFileTransferInfo.getFile();
+ try {
+ setInputStream(new BufferedInputStream(new FileInputStream(inputFile)));
+ } catch (Exception e) {
+ hardClose();
+ throw new SendFileTransferException(NLS.bind(Messages.LocalFileOutgoingFileTransfer_EXCEPTION_OPENING_FOR_INPUT, inputFile));
+ }
+ URL url = getRemoteFileURL();
+ Assert.isNotNull(url);
+ try {
+ File outputFile = new File(url.getPath());
+ setOutputStream(new BufferedOutputStream(new FileOutputStream(outputFile)));
+ } catch (Exception e) {
+ hardClose();
+ throw new SendFileTransferException(NLS.bind(Messages.LocalFileOutgoingFileTransfer_EXCEPTION_OPENING_FOR_OUTPUT, url));
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.provider.filetransfer.outgoing.AbstractOutgoingFileTransfer#setupProxy(org.eclipse.ecf.core.util.Proxy)
+ */
+ protected void setupProxy(Proxy proxy) {
+ // No proxy for local file system
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/outgoing/MultiProtocolOutgoingAdapter.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/outgoing/MultiProtocolOutgoingAdapter.java
new file mode 100644
index 0000000000..0b0effc568
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/outgoing/MultiProtocolOutgoingAdapter.java
@@ -0,0 +1,165 @@
+/****************************************************************************
+ * Copyright (c) 2004, 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.provider.filetransfer.outgoing;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.util.Map;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IAdapterManager;
+import org.eclipse.ecf.core.identity.IDFactory;
+import org.eclipse.ecf.core.identity.Namespace;
+import org.eclipse.ecf.core.security.IConnectContext;
+import org.eclipse.ecf.core.util.Proxy;
+import org.eclipse.ecf.filetransfer.IFileTransferInfo;
+import org.eclipse.ecf.filetransfer.IFileTransferListener;
+import org.eclipse.ecf.filetransfer.IIncomingFileTransferRequestListener;
+import org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter;
+import org.eclipse.ecf.filetransfer.SendFileTransferException;
+import org.eclipse.ecf.filetransfer.identity.IFileID;
+import org.eclipse.ecf.filetransfer.service.ISendFileTransfer;
+import org.eclipse.ecf.internal.provider.filetransfer.Activator;
+import org.eclipse.ecf.internal.provider.filetransfer.Messages;
+import org.eclipse.ecf.provider.filetransfer.identity.FileTransferNamespace;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Multi protocol handler for outgoing file transfer. Multiplexes between Apache
+ * httpclient 3.0.1-based file retriever and the URLConnection-based file
+ * retriever.
+ */
+public class MultiProtocolOutgoingAdapter implements ISendFileTransfer {
+
+ IConnectContext connectContext = null;
+ Proxy proxy = null;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#getOutgoingNamespace()
+ */
+ public Namespace getOutgoingNamespace() {
+ return IDFactory.getDefault().getNamespaceByName(FileTransferNamespace.PROTOCOL);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.filetransfer.IRetrieveFileTransferContainerAdapter#setConnectContextForAuthentication(org.eclipse.ecf.core.security.IConnectContext)
+ */
+ public void setConnectContextForAuthentication(IConnectContext connectContext) {
+ this.connectContext = connectContext;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.filetransfer.IRetrieveFileTransferContainerAdapter#setProxy(org.eclipse.ecf.core.util.Proxy)
+ */
+ public void setProxy(Proxy proxy) {
+ this.proxy = proxy;
+ }
+
+ public void sendOutgoingRequest(IFileID targetID, File outgoingFile, IFileTransferListener transferListener, Map options) throws SendFileTransferException {
+
+ Assert.isNotNull(targetID);
+ Assert.isNotNull(outgoingFile);
+ Assert.isNotNull(transferListener);
+
+ String protocol = null;
+ try {
+ protocol = targetID.getURI().getScheme();
+ } catch (URISyntaxException e) {
+ try {
+ protocol = targetID.getURL().getProtocol();
+ } catch (final MalformedURLException e1) {
+ throw new SendFileTransferException(Messages.AbstractRetrieveFileTransfer_MalformedURLException);
+ }
+ }
+
+ ISendFileTransferContainerAdapter fileTransfer = Activator.getDefault().getSendFileTransfer(protocol);
+
+ // If no handler setup for this protocol then throw
+ if (fileTransfer == null) {
+ if (protocol.equalsIgnoreCase("file")) { //$NON-NLS-1$
+ fileTransfer = new LocalFileOutgoingFileTransfer();
+ }
+ }
+
+ if (fileTransfer == null) {
+ throw new SendFileTransferException(NLS.bind(Messages.MultiProtocolOutgoingAdapter_EXCEPTION_NO_PROTOCOL_HANDER, targetID));
+ }
+
+ fileTransfer.setConnectContextForAuthentication(connectContext);
+ fileTransfer.setProxy(proxy);
+ fileTransfer.sendOutgoingRequest(targetID, outgoingFile, transferListener, options);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#addListener(org.eclipse.ecf.filetransfer.IIncomingFileTransferRequestListener)
+ */
+ public void addListener(IIncomingFileTransferRequestListener listener) {
+ // We don't have any listeners
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#removeListener(org.eclipse.ecf.filetransfer.IIncomingFileTransferRequestListener)
+ */
+ public boolean removeListener(IIncomingFileTransferRequestListener listener) {
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ecf.filetransfer.ISendFileTransferContainerAdapter#sendOutgoingRequest(org.eclipse.ecf.filetransfer.identity.IFileID, org.eclipse.ecf.filetransfer.IFileTransferInfo, org.eclipse.ecf.filetransfer.IFileTransferListener, java.util.Map)
+ */
+ public void sendOutgoingRequest(IFileID targetID, IFileTransferInfo localFileToSend, IFileTransferListener transferListener, Map options) throws SendFileTransferException {
+ Assert.isNotNull(targetID);
+ Assert.isNotNull(localFileToSend);
+ Assert.isNotNull(transferListener);
+
+ String protocol = null;
+ try {
+ protocol = targetID.getURI().getScheme();
+ } catch (URISyntaxException e) {
+ try {
+ protocol = targetID.getURL().getProtocol();
+ } catch (final MalformedURLException e1) {
+ throw new SendFileTransferException(Messages.AbstractRetrieveFileTransfer_MalformedURLException);
+ }
+ }
+
+ ISendFileTransferContainerAdapter fileTransfer = Activator.getDefault().getSendFileTransfer(protocol);
+
+ // If no handler setup for this protocol then throw
+ if (fileTransfer == null) {
+ throw new SendFileTransferException(NLS.bind(Messages.MultiProtocolOutgoingAdapter_EXCEPTION_NO_PROTOCOL_HANDER, targetID));
+ }
+
+ fileTransfer.setConnectContextForAuthentication(connectContext);
+ fileTransfer.setProxy(proxy);
+ fileTransfer.sendOutgoingRequest(targetID, localFileToSend, transferListener, options);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+ */
+ public remoteFileContents and localFileContent
+ * must be non-null after successful completion of the
+ * implementation of this method.
+ *
+ * @throws IncomingFileTransferException if some problem
+ */
+ protected abstract void openStreams() throws IncomingFileTransferException;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.ecf.filetransfer.IRetrieveFileTransferContainerAdapter#
+ * sendRetrieveRequest(org.eclipse.ecf.filetransfer.identity.IFileID,
+ * org.eclipse.ecf.filetransfer.IFileTransferListener, java.util.Map)
+ */
+ public void sendRetrieveRequest(final IFileID remoteFileID1, IFileTransferListener transferListener, Map options1) throws IncomingFileTransferException {
+ sendRetrieveRequest(remoteFileID1, null, transferListener, options1);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.ecf.filetransfer.IRetrieveFileTransferContainerAdapter#
+ * getRetrieveNamespace()
+ */
+ public Namespace getRetrieveNamespace() {
+ return IDFactory.getDefault().getNamespaceByName(FileTransferNamespace.PROTOCOL);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.filetransfer.IFileTransferPausable#isPaused()
+ */
+ public boolean isPaused() {
+ return paused;
+ }
+
+ /**
+ * Subclass overridable version of {@link #pause()}. Subclasses must provide
+ * an implementation of this method to support {@link IFileTransferPausable}
+ * .
+ *
+ * @return true if the pause is successful. false otherwise.
+ */
+ protected abstract boolean doPause();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.filetransfer.IFileTransferPausable#pause()
+ */
+ public boolean pause() {
+ return doPause();
+ }
+
+ /**
+ * Subclass overridable version of {@link #resume()}. Subclasses must
+ * provide an implementation of this method to support
+ * {@link IFileTransferPausable}.
+ *
+ * @return true if the resume is successful. false otherwise.
+ */
+ protected abstract boolean doResume();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.filetransfer.IFileTransferPausable#resume()
+ */
+ public boolean resume() {
+ return doResume();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.filetransfer.IIncomingFileTransfer#getListener()
+ */
+ public IFileTransferListener getListener() {
+ return listener;
+ }
+
+ protected String createRangeName() {
+ if (rangeSpecification == null)
+ return ""; //$NON-NLS-1$
+ return "[" + rangeSpecification.getStartPosition() + "," + rangeSpecification.getEndPosition() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ protected String createJobName() {
+ return getRemoteFileURL().toString() + createRangeName();
+ }
+
+ protected void setupAndScheduleJob(FileTransferJob fileTransferJob) {
+ if (fileTransferJob == null) {
+ // Create our own
+ fileTransferJob = new FileTransferJob(createJobName());
+ }
+ // Now set to our runnable
+ fileTransferJob.setFileTransferRunnable(fileTransferRunnable);
+ fileTransferJob.setFileTransfer(this);
+ if (isDone()) {
+ return;
+ }
+ synchronized (jobLock) {
+ job = fileTransferJob;
+ job.schedule();
+ }
+ }
+
+ protected void fireReceiveStartEvent() {
+ listener.handleTransferEvent(new IIncomingFileTransferReceiveStartEvent() {
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.ecf.filetransfer.events.
+ * IIncomingFileTransferEvent#getFileID()
+ */
+ public IIncomingFileTransfer getSource() {
+ return AbstractRetrieveFileTransfer.this;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.ecf.filetransfer.events.
+ * IIncomingFileTransferReceiveStartEvent#getFileID()
+ */
+ public IFileID getFileID() {
+ return remoteFileID;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.ecf.filetransfer.events.
+ * IIncomingFileTransferReceiveStartEvent
+ * #receive(java.io.File)
+ */
+ public IIncomingFileTransfer receive(File localFileToSave) throws IOException {
+ return receive(localFileToSave, null);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.ecf.filetransfer.events.
+ * IIncomingFileTransferReceiveStartEvent
+ * #receive(java.io.File,
+ * org.eclipse.ecf.filetransfer.FileTransferJob)
+ */
+ public IIncomingFileTransfer receive(File localFileToSave, FileTransferJob fileTransferJob) throws IOException {
+ setOutputStream(new BufferedOutputStream(new FileOutputStream(localFileToSave)));
+ setupAndScheduleJob(fileTransferJob);
+ return AbstractRetrieveFileTransfer.this;
+ }
+
+ /**
+ * @param streamToStore
+ * @return incoming file transfer instance.
+ * @throws IOException
+ * not thrown in this implementation.
+ */
+ public IIncomingFileTransfer receive(OutputStream streamToStore) throws IOException {
+ return receive(streamToStore, null);
+ }
+
+ /**
+ * @throws IOException
+ * not actually thrown by this implementation.
+ */
+ public IIncomingFileTransfer receive(OutputStream streamToStore, FileTransferJob fileTransferJob) throws IOException {
+ setOutputStream(streamToStore);
+ setCloseOutputStream(false);
+ setupAndScheduleJob(fileTransferJob);
+ return AbstractRetrieveFileTransfer.this;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.ecf.filetransfer.events.
+ * IIncomingFileTransferReceiveStartEvent#cancel()
+ */
+ public void cancel() {
+ AbstractRetrieveFileTransfer.this.cancel();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ final StringBuffer sb = new StringBuffer("IIncomingFileTransferReceiveStartEvent["); //$NON-NLS-1$
+ sb.append("isdone=").append(isDone()).append(";"); //$NON-NLS-1$ //$NON-NLS-2$
+ sb.append("bytesReceived=").append(bytesReceived) //$NON-NLS-1$
+ .append("]"); //$NON-NLS-1$
+ return sb.toString();
+ }
+
+ public Map getResponseHeaders() {
+ return responseHeaders;
+ }
+
+ });
+ }
+
+ protected void fireReceiveResumedEvent() {
+ listener.handleTransferEvent(new IIncomingFileTransferReceiveResumedEvent() {
+
+ public IIncomingFileTransfer getSource() {
+ return AbstractRetrieveFileTransfer.this;
+ }
+
+ public IFileID getFileID() {
+ return remoteFileID;
+ }
+
+ public IIncomingFileTransfer receive(File localFileToSave, boolean append) throws IOException {
+ return receive(localFileToSave, null, append);
+ }
+
+ public IIncomingFileTransfer receive(File localFileToSave, FileTransferJob fileTransferJob, boolean append) throws IOException {
+ setOutputStream(new BufferedOutputStream(new FileOutputStream(localFileToSave.getName(), append)));
+ setupAndScheduleJob(fileTransferJob);
+ return AbstractRetrieveFileTransfer.this;
+ }
+
+ /**
+ * @param streamToStore
+ * @return incoming file transfer instance.
+ * @throws IOException
+ * not thrown in this implementation.
+ */
+ public IIncomingFileTransfer receive(OutputStream streamToStore) throws IOException {
+ return receive(streamToStore, null);
+ }
+
+ /**
+ * @throws IOException
+ * not actually thrown by this implementation.
+ */
+ public IIncomingFileTransfer receive(OutputStream streamToStore, FileTransferJob fileTransferJob) throws IOException {
+ setOutputStream(streamToStore);
+ setCloseOutputStream(false);
+ setupAndScheduleJob(fileTransferJob);
+ return AbstractRetrieveFileTransfer.this;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.ecf.filetransfer.events.
+ * IIncomingFileTransferReceiveStartEvent#cancel()
+ */
+ public void cancel() {
+ hardClose();
+ }
+
+ public String toString() {
+ final StringBuffer sb = new StringBuffer("IIncomingFileTransferReceiveResumedEvent["); //$NON-NLS-1$
+ sb.append("isdone=").append(isDone()).append(";"); //$NON-NLS-1$ //$NON-NLS-2$
+ sb.append("bytesReceived=").append(bytesReceived) //$NON-NLS-1$
+ .append("]"); //$NON-NLS-1$
+ return sb.toString();
+ }
+
+ public Map getResponseHeaders() {
+ return responseHeaders;
+ }
+
+ });
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.ecf.filetransfer.IIncomingFileTransfer#getFileRangeSpecification
+ * ()
+ */
+ public IFileRangeSpecification getFileRangeSpecification() {
+ return rangeSpecification;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.ecf.filetransfer.IRetrieveFileTransferContainerAdapter#
+ * sendRetrieveRequest(org.eclipse.ecf.filetransfer.identity.IFileID,
+ * org.eclipse.ecf.filetransfer.IFileRangeSpecification,
+ * org.eclipse.ecf.filetransfer.IFileTransferListener, java.util.Map)
+ */
+ /**
+ * @throws IncomingFileTransferException if some problem sending retrieve request
+ */
+ public void sendRetrieveRequest(IFileID rFileID, IFileRangeSpecification rangeSpec, IFileTransferListener transferListener, Map ops) throws IncomingFileTransferException {
+ Assert.isNotNull(rFileID, Messages.AbstractRetrieveFileTransfer_RemoteFileID_Not_Null);
+ Assert.isNotNull(transferListener, Messages.AbstractRetrieveFileTransfer_TransferListener_Not_Null);
+ synchronized (jobLock) {
+ this.job = null;
+ }
+ this.remoteFileURL = null;
+ this.remoteFileID = rFileID;
+ this.listener = transferListener;
+ this.remoteFileContents = null;
+ this.localFileContents = null;
+ this.closeOutputStream = true;
+ resetDoneAndException();
+ this.bytesReceived = 0;
+ this.fileLength = -1;
+ this.options = ops;
+ this.paused = false;
+ this.rangeSpecification = rangeSpec;
+
+ try {
+ this.remoteFileURL = rFileID.getURL();
+ } catch (final MalformedURLException e) {
+ setDoneException(e);
+ fireTransferReceiveDoneEvent();
+ return;
+ }
+ try {
+ setupProxies();
+ openStreams();
+ } catch (final IncomingFileTransferException e) {
+ setDoneException(e);
+ fireTransferReceiveDoneEvent();
+ }
+ }
+
+ /**
+ * Setup ECF proxy. Subclasses must override this method to do appropriate
+ * proxy setup. This method will be called from within
+ * {@link #sendRetrieveRequest(IFileID, IFileTransferListener, Map)} and
+ * {@link #sendRetrieveRequest(IFileID, IFileRangeSpecification, IFileTransferListener, Map)}
+ * , prior to the actual call to {@link #openStreams()}.
+ *
+ * @param proxy
+ * the proxy to be setup. Will not be null.
+ */
+ protected abstract void setupProxy(Proxy proxy);
+
+ /**
+ * Select a single proxy from a set of proxies available for the given host.
+ * This implementation selects in the following manner: 1) If proxies
+ * provided is null or array of 0 length, null is returned. If only one
+ * proxy is available (array of length 1) then the entry is returned. If
+ * proxies provided is length greater than 1, then if the type of a proxy in the array
+ * matches the given protocol (e.g. http, https), then the first matching
+ * proxy is returned. If the protocol does not match any of the proxies,
+ * then the *first* proxy (i.e. proxies[0]) is returned. Subclasses may
+ * override if desired.
+ *
+ * @param protocol
+ * the target protocol (e.g. http, https, scp, etc). Will not be
+ * null.
+ * @param proxies
+ * the proxies to select from. May be null or array
+ * of length 0.
+ * @return proxy data selected from the proxies provided.
+ */
+ protected IProxyData selectProxyFromProxies(String protocol, IProxyData[] proxies) {
+ if (proxies == null || proxies.length == 0)
+ return null;
+ // If only one proxy is available, then use that
+ if (proxies.length == 1)
+ return proxies[0];
+ // If more than one proxy is available, then if http/https protocol then
+ // look for that
+ // one...if not found then use first
+ if (protocol.equalsIgnoreCase("http")) { //$NON-NLS-1$
+ for (IProxyData proxie : proxies) {
+ if (proxie.getType().equals(IProxyData.HTTP_PROXY_TYPE)) {
+ return proxie;
+ }
+ }
+ } else if (protocol.equalsIgnoreCase("https")) { //$NON-NLS-1$
+ for (IProxyData proxie : proxies) {
+ if (proxie.getType().equals(IProxyData.HTTPS_PROXY_TYPE)) {
+ return proxie;
+ }
+ }
+ }
+ // If we haven't found it yet, then return the first one.
+ return proxies[0];
+ }
+
+ protected void setupProxies() {
+ // If it's been set directly (via ECF API) then this overrides platform
+ // settings
+ if (proxy == null) {
+ try {
+ proxy = ProxySetupHelper.getProxy(getRemoteFileURL().toExternalForm());
+ } catch (NoClassDefFoundError e) {
+ // If the proxy API is not available a NoClassDefFoundError will be thrown here.
+ // If that happens then we just want to continue on.
+ Activator.logNoProxyWarning(e);
+ }
+ }
+ if (proxy != null)
+ setupProxy(proxy);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.ecf.filetransfer.IIncomingFileTransfer#getRemoteFileName()
+ */
+ public String getRemoteFileName() {
+ String pathStr = getRemoteFileURL().getPath();
+ if (pathStr.length() > 0) {
+ IPath path = Path.fromPortableString(pathStr);
+ if (path.segmentCount() > 0)
+ return path.lastSegment();
+ }
+ return null;
+ }
+
+ protected boolean targetHasGzSuffix(String target) {
+ if (target == null)
+ return false;
+ if (target.endsWith(".gz")) //$NON-NLS-1$
+ return true;
+ return false;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/retrieve/HttpHelper.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/retrieve/HttpHelper.java
new file mode 100644
index 0000000000..04c217ffd7
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/retrieve/HttpHelper.java
@@ -0,0 +1,41 @@
+/****************************************************************************
+ * Copyright (c) 2008 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.provider.filetransfer.retrieve;
+
+import java.util.StringTokenizer;
+
+/**
+ *
+ */
+public class HttpHelper {
+
+ public static final String CONTENT_DISPOSITION_HEADER = "Content-Disposition"; //$NON-NLS-1$
+
+ public static String getRemoteFileNameFromContentDispositionHeader(String headerValue) {
+ if (headerValue != null) {
+ StringTokenizer tokens = new StringTokenizer(headerValue, " \t\n\r\f=;,"); //$NON-NLS-1$
+ while (tokens.hasMoreTokens()) {
+ String token = tokens.nextToken();
+ if (token.equals("filename") && tokens.hasMoreTokens()) { //$NON-NLS-1$
+ // Expect next token to be the filename
+ String fileName = tokens.nextToken();
+ if (fileName.startsWith("\"") && fileName.endsWith("\"")) //$NON-NLS-1$ //$NON-NLS-2$
+ fileName = fileName.substring(1, fileName.length() - 1);
+ return fileName;
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/retrieve/MultiProtocolRetrieveAdapter.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/retrieve/MultiProtocolRetrieveAdapter.java
new file mode 100644
index 0000000000..8bf777f990
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/retrieve/MultiProtocolRetrieveAdapter.java
@@ -0,0 +1,164 @@
+/****************************************************************************
+ * Copyright (c) 2004, 2007 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.provider.filetransfer.retrieve;
+
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.util.Map;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IAdapterManager;
+import org.eclipse.ecf.core.identity.IDFactory;
+import org.eclipse.ecf.core.identity.Namespace;
+import org.eclipse.ecf.core.security.IConnectContext;
+import org.eclipse.ecf.core.util.Proxy;
+import org.eclipse.ecf.filetransfer.IFileRangeSpecification;
+import org.eclipse.ecf.filetransfer.IFileTransferListener;
+import org.eclipse.ecf.filetransfer.IRetrieveFileTransferContainerAdapter;
+import org.eclipse.ecf.filetransfer.IncomingFileTransferException;
+import org.eclipse.ecf.filetransfer.identity.IFileID;
+import org.eclipse.ecf.filetransfer.service.IRetrieveFileTransfer;
+import org.eclipse.ecf.internal.provider.filetransfer.Activator;
+import org.eclipse.ecf.internal.provider.filetransfer.Messages;
+import org.eclipse.ecf.provider.filetransfer.identity.FileTransferNamespace;
+
+/**
+ * Multi protocol handler for retrieve file transfer. Multiplexes between Apache
+ * httpclient 3.0.1-based file retriever and the URLConnection-based file
+ * retriever.
+ */
+public class MultiProtocolRetrieveAdapter implements IRetrieveFileTransfer {
+
+ IConnectContext connectContext = null;
+ Proxy proxy = null;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.filetransfer.IRetrieveFileTransferContainerAdapter#getRetrieveNamespace()
+ */
+ public Namespace getRetrieveNamespace() {
+ return IDFactory.getDefault().getNamespaceByName(FileTransferNamespace.PROTOCOL);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.filetransfer.IRetrieveFileTransferContainerAdapter#setConnectContextForAuthentication(org.eclipse.ecf.core.security.IConnectContext)
+ */
+ public void setConnectContextForAuthentication(IConnectContext connectContext) {
+ this.connectContext = connectContext;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.filetransfer.IRetrieveFileTransferContainerAdapter#setProxy(org.eclipse.ecf.core.util.Proxy)
+ */
+ public void setProxy(Proxy proxy) {
+ this.proxy = proxy;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.filetransfer.IRetrieveFileTransferContainerAdapter#sendRetrieveRequest(org.eclipse.ecf.filetransfer.identity.IFileID,
+ * org.eclipse.ecf.filetransfer.IFileTransferListener, java.util.Map)
+ */
+ public void sendRetrieveRequest(IFileID remoteFileID, IFileTransferListener transferListener, Map options) throws IncomingFileTransferException {
+
+ Assert.isNotNull(remoteFileID);
+ Assert.isNotNull(transferListener);
+
+ String protocol = null;
+ try {
+ protocol = remoteFileID.getURI().getScheme();
+ } catch (URISyntaxException e) {
+ try {
+ protocol = remoteFileID.getURL().getProtocol();
+ } catch (final MalformedURLException e1) {
+ throw new IncomingFileTransferException(Messages.AbstractRetrieveFileTransfer_MalformedURLException);
+ }
+ }
+
+ IRetrieveFileTransferContainerAdapter fileTransfer = Activator.getDefault().getFileTransfer(protocol);
+
+ // We will default to JRE-provided file transfer if nothing else
+ // available
+ // for given protocol
+ if (fileTransfer == null)
+ fileTransfer = new UrlConnectionRetrieveFileTransfer();
+
+ // Set connect context
+ fileTransfer.setConnectContextForAuthentication(connectContext);
+ // Set Proxy
+ fileTransfer.setProxy(proxy);
+
+ // send request using given file transfer protocol
+ fileTransfer.sendRetrieveRequest(remoteFileID, transferListener, options);
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ecf.filetransfer.IRetrieveFileTransferContainerAdapter#sendRetrieveRequest(org.eclipse.ecf.filetransfer.identity.IFileID,
+ * org.eclipse.ecf.filetransfer.IFileRangeSpecification,
+ * org.eclipse.ecf.filetransfer.IFileTransferListener, java.util.Map)
+ */
+ public void sendRetrieveRequest(IFileID remoteFileID, IFileRangeSpecification rangeSpecification, IFileTransferListener transferListener, Map options) throws IncomingFileTransferException {
+ Assert.isNotNull(remoteFileID);
+ Assert.isNotNull(transferListener);
+
+ String protocol = null;
+ try {
+ protocol = remoteFileID.getURI().getScheme();
+ } catch (URISyntaxException e) {
+ try {
+ protocol = remoteFileID.getURL().getProtocol();
+ } catch (final MalformedURLException e1) {
+ throw new IncomingFileTransferException(Messages.AbstractRetrieveFileTransfer_MalformedURLException);
+ }
+ }
+
+ IRetrieveFileTransferContainerAdapter fileTransfer = Activator.getDefault().getFileTransfer(protocol);
+
+ // We will default to JRE-provided file transfer if nothing else
+ // available
+ // for given protocol
+ if (fileTransfer == null)
+ fileTransfer = new UrlConnectionRetrieveFileTransfer();
+
+ // Set connect context
+ fileTransfer.setConnectContextForAuthentication(connectContext);
+ // Set Proxy
+ fileTransfer.setProxy(proxy);
+
+ // send request using given file transfer protocol
+ fileTransfer.sendRetrieveRequest(remoteFileID, rangeSpecification, transferListener, options);
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
+ */
+ public true if streams successfully, false
+ * otherwise.
+ */
+ private boolean openStreamsForResume() {
+ final URL theURL = getRemoteFileURL();
+ int code = -1;
+ try {
+ remoteFileURL = new URL(theURL.toString());
+ setupAuthentication();
+ connect();
+ setResumeRequestHeaderValues();
+ // Make actual GET request
+ setInputStream(urlConnection.getInputStream());
+ code = getResponseCode();
+ responseHeaders = getResponseHeaders();
+ if (code == HttpURLConnection.HTTP_PARTIAL || code == HttpURLConnection.HTTP_OK) {
+ getResumeResponseHeaderValues();
+ this.paused = false;
+ fireReceiveResumedEvent();
+ return true;
+ } else if (code == HttpURLConnection.HTTP_NOT_FOUND) {
+ throw new IncomingFileTransferException(NLS.bind("File not found: {0}", getRemoteFileURL().toString()), code, responseHeaders); //$NON-NLS-1$
+ } else if (code == HttpURLConnection.HTTP_UNAUTHORIZED) {
+ throw new IncomingFileTransferException("Unauthorized", code, responseHeaders); //$NON-NLS-1$
+ } else if (code == HttpURLConnection.HTTP_FORBIDDEN) {
+ throw new IncomingFileTransferException("Forbidden", code, responseHeaders); //$NON-NLS-1$
+ } else if (code == HttpURLConnection.HTTP_PROXY_AUTH) {
+ throw new IncomingFileTransferException("Proxy authentication required", code, responseHeaders); //$NON-NLS-1$
+ } else {
+ throw new IncomingFileTransferException(NLS.bind("General connection error with response code={0}", Integer.valueOf(code)), code, responseHeaders); //$NON-NLS-1$
+ }
+ } catch (final Exception e) {
+ this.exception = (e instanceof IncomingFileTransferException) ? e : new IncomingFileTransferException(NLS.bind(Messages.UrlConnectionRetrieveFileTransfer_EXCEPTION_COULD_NOT_CONNECT, getRemoteFileURL().toString()), e, code, responseHeaders);
+ this.done = true;
+ hardClose();
+ fireTransferReceiveDoneEvent();
+ return false;
+ }
+ }
+
+ private static final String ACCEPT_ENCODING = "Accept-encoding"; //$NON-NLS-1$
+ private static final String CONTENT_ENCODING_GZIP = "gzip"; //$NON-NLS-1$
+
+ private static final String CONTENT_ENCODING_ACCEPTED = CONTENT_ENCODING_GZIP; // +
+
+ private static class Compression {
+
+ private String type;
+
+ private Compression(String i) {
+ this.type = i;
+ }
+
+ static Compression NONE = new Compression("none"); //$NON-NLS-1$
+
+ static Compression GZIP = new Compression("gzip"); //$NON-NLS-1$
+
+ public String toString() {
+ return type;
+ }
+ }
+
+ private void setCompressionRequestHeader() {
+ // Set request header for possible gzip encoding, but only if
+ // 1) The file range specification is null (we want the whole file)
+ // 2) The target remote file does *not* end in .gz (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=280205)
+ if (getFileRangeSpecification() == null && !targetHasGzSuffix(super.getRemoteFileName()))
+ urlConnection.setRequestProperty(ACCEPT_ENCODING, CONTENT_ENCODING_ACCEPTED);
+ }
+
+ private Compression getCompressionResponseHeader() {
+ String encoding = urlConnection.getContentEncoding();
+ if (null == encoding) {
+ return Compression.NONE;
+ // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=269018
+ } else if (encoding.equalsIgnoreCase(CONTENT_ENCODING_GZIP) && !targetHasGzSuffix(remoteFileName)) {
+ return Compression.GZIP;
+ }
+ return Compression.NONE;
+ }
+
+ private InputStream getDecompressedStream() throws IOException {
+ InputStream input = urlConnection.getInputStream();
+ getResponseHeaderValues();
+ Compression type = getCompressionResponseHeader();
+
+ if (Compression.GZIP == type) {
+ return new java.util.zip.GZIPInputStream(input);
+ // } else if (Compression.DEFLATE == type) {
+ // return new java.util.zip.InflaterInputStream(input);
+ }
+ return input;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/util/JREProxyHelper.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/util/JREProxyHelper.java
new file mode 100644
index 0000000000..02f943ac27
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/util/JREProxyHelper.java
@@ -0,0 +1,92 @@
+/****************************************************************************
+ * Copyright (c) 2007, 2010 Composent, Inc. and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Composent, Inc. - initial API and implementation
+ * Henrich Kraemer - bug 295030, Update Manager doesn't work with SOCKS proxy
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+
+package org.eclipse.ecf.provider.filetransfer.util;
+
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;
+import java.util.Properties;
+import org.eclipse.ecf.core.util.Proxy;
+
+/**
+ * Helper class for setting the JRE proxy value (http and socks).
+ */
+public class JREProxyHelper {
+
+ private static final String SOCKS_PROXY_PORT_SYSTEM_PROPERTY = "socksProxyPort"; //$NON-NLS-1$
+
+ private static final String SOCKS_PROXY_HOST_SYSTEM_PROPERTY = "socksProxyHost"; //$NON-NLS-1$
+
+ private static final String HTTP_PROXY_PORT_SYSTEM_PROPERTY = "http.proxyPort"; //$NON-NLS-1$
+
+ private static final String HTTP_PROXY_HOST_SYSTEM_PROPERTY = "http.proxyHost"; //$NON-NLS-1$
+
+ private String proxyHostProperty;
+ private String proxyPortProperty;
+
+ private String oldHost;
+ private String oldPort;
+
+ public void setupProxy(final Proxy proxy2) {
+ Properties systemProperties = System.getProperties();
+ proxyHostProperty = (proxy2.getType().equals(Proxy.Type.HTTP)) ? HTTP_PROXY_HOST_SYSTEM_PROPERTY : SOCKS_PROXY_HOST_SYSTEM_PROPERTY;
+ proxyPortProperty = (proxy2.getType().equals(Proxy.Type.HTTP)) ? HTTP_PROXY_PORT_SYSTEM_PROPERTY : SOCKS_PROXY_PORT_SYSTEM_PROPERTY;
+ oldHost = systemProperties.getProperty(proxyHostProperty);
+ if (oldHost != null) {
+ oldPort = systemProperties.getProperty(proxyPortProperty);
+ }
+ systemProperties.setProperty(proxyHostProperty, proxy2.getAddress().getHostName());
+ int proxyPort = proxy2.getAddress().getPort();
+ if (proxyPort != -1)
+ systemProperties.setProperty(proxyPortProperty, proxyPort + ""); //$NON-NLS-1$
+ final String username = proxy2.getUsername();
+ boolean setAuthenticator = false;
+ if (username != null && !username.equals("")) { //$NON-NLS-1$
+ final String password = (proxy2.getPassword() == null) ? "" : proxy2.getPassword(); //$NON-NLS-1$
+ if (proxy2.hasCredentials()) {
+ Authenticator.setDefault(new Authenticator() {
+ /* (non-Javadoc)
+ * @see java.net.Authenticator#getPasswordAuthentication()
+ */
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password.toCharArray());
+ }
+ });
+ setAuthenticator = true;
+ }
+ }
+ if (!setAuthenticator) {
+ Authenticator.setDefault(new Authenticator() {
+ /* (non-Javadoc)
+ * @see java.net.Authenticator#getPasswordAuthentication()
+ */
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return null;
+ }
+ });
+ }
+ }
+
+ public void dispose() {
+ // reset old values
+ if (oldHost != null) {
+ System.getProperties().setProperty(proxyHostProperty, oldHost);
+ oldHost = null;
+ if (oldPort != null) {
+ System.getProperties().setProperty(proxyPortProperty, oldPort);
+ oldPort = null;
+ }
+ }
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/util/PollingInputStream.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/util/PollingInputStream.java
new file mode 100644
index 0000000000..c78b09e310
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/util/PollingInputStream.java
@@ -0,0 +1,276 @@
+/****************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * EclipseSource - modification after copying to ECF filetransfer provider
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.provider.filetransfer.util;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ecf.internal.provider.filetransfer.Activator;
+
+/**
+ * Polls a progress monitor periodically and handles timeouts over extended
+ * durations. For this class to be effective, a high numAttempts should be
+ * specified, and the underlying stream should time out frequently on reads
+ * (every second or so).
+ *
+ * Supports resuming partially completed operations after an
+ * InterruptedIOException if the underlying stream does. Check the
+ * bytesTransferred field to determine how much of the operation completed;
+ * conversely, at what point to resume.
+ *
+ * @since 3.0
+ */
+public class PollingInputStream extends FilterInputStream {
+ private int numAttempts;
+ private IProgressMonitor monitor;
+ private boolean cancellable;
+
+ private String readTimeoutMessage = "Timeout while reading input stream"; //$NON-NLS-1$
+ private String closeTimeoutMessage = "Timeout while closing input stream"; //$NON-NLS-1$
+
+ /**
+ * Creates a new polling input stream.
+ *
+ * @param in
+ * the underlying input stream
+ * @param numAttempts
+ * the number of attempts before issuing an
+ * InterruptedIOException, if 0, retries indefinitely until
+ * canceled
+ * @param monitor
+ * the progress monitor to be polled for cancellation
+ */
+ public PollingInputStream(InputStream in, int numAttempts, IProgressMonitor monitor) {
+ super(in);
+ this.numAttempts = numAttempts;
+ this.monitor = monitor;
+ this.cancellable = true;
+ }
+
+ /**
+ * Creates a new polling input stream.
+ *
+ * @param in
+ * the underlying input stream
+ * @param numAttempts
+ * the number of attempts before issuing an
+ * InterruptedIOException, if 0, retries indefinitely until
+ * canceled
+ * @param monitor
+ * the progress monitor to be polled for cancellation
+ * @param readTimeoutMessage message to go with InteruptedIOException if read timeout
+ * @param closeTimeoutMessage message to go with InteruptedIOException if close timeout
+ * @since 3.1
+ */
+ public PollingInputStream(InputStream in, int numAttempts, IProgressMonitor monitor, String readTimeoutMessage, String closeTimeoutMessage) {
+ super(in);
+ this.numAttempts = numAttempts;
+ this.monitor = monitor;
+ this.cancellable = true;
+ if (readTimeoutMessage != null)
+ this.readTimeoutMessage = readTimeoutMessage;
+ if (closeTimeoutMessage != null)
+ this.closeTimeoutMessage = closeTimeoutMessage;
+ }
+
+ /**
+ * Wraps the underlying stream's method. It may be important to wait for an
+ * input stream to be closed because it holds an implicit lock on a system
+ * resource (such as a file) while it is open. Closing a stream may take
+ * time if the underlying stream is still servicing a previous request.
+ *
+ * @throws OperationCanceledException
+ * if the progress monitor is canceled
+ * @throws InterruptedIOException
+ * if the underlying operation times out numAttempts times
+ */
+ public void close() throws InterruptedIOException {
+ int attempts = 0;
+ try {
+ readPendingInput();
+ } catch (IOException e) {
+ // We shouldn't get an exception when we're getting the available
+ // input.
+ // If we do, just log it so we can close.
+ logError(e.getMessage(), e);
+ } finally {
+ boolean stop = false;
+ while (!stop) {
+ try {
+ if (in != null)
+ in.close();
+ stop = true;
+ } catch (InterruptedIOException e) {
+ if (checkCancellation())
+ throw new OperationCanceledException();
+ if (++attempts == numAttempts)
+ throw new InterruptedIOException(closeTimeoutMessage);
+ } catch (IOException e) {
+ // ignore it - see
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=203423#c10
+ }
+ }
+ }
+ }
+
+ private void logError(String message, IOException e) {
+ Activator a = Activator.getDefault();
+ if (a != null)
+ a.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, message, e));
+ }
+
+ /**
+ * Wraps the underlying stream's method.
+ *
+ * @return the next byte of data, or -1 if the end of the stream is reached.
+ * @throws OperationCanceledException
+ * if the progress monitor is canceled
+ * @throws InterruptedIOException
+ * if the underlying operation times out numAttempts times and
+ * no data was received, bytesTransferred will be zero
+ * @throws IOException
+ * if an i/o error occurs
+ */
+ public int read() throws IOException {
+ int attempts = 0;
+ for (;;) {
+ if (checkCancellation())
+ throw new OperationCanceledException();
+ try {
+ return in.read();
+ } catch (InterruptedIOException e) {
+ if (++attempts == numAttempts)
+ throw new InterruptedIOException(readTimeoutMessage);
+ }
+ }
+ }
+
+ /**
+ * Wraps the underlying stream's method.
+ *
+ * @param buffer
+ * - the buffer into which the data is read.
+ * @param off
+ * - the start offset of the data.
+ * @param len
+ * - the maximum number of bytes read.
+ * @return the total number of bytes read into the buffer, or -1 if there is
+ * no more data because the end of the stream has been reached.
+ * @throws OperationCanceledException
+ * if the progress monitor is canceled
+ * @throws InterruptedIOException
+ * if the underlying operation times out numAttempts times and
+ * no data was received, bytesTransferred will be zero
+ * @throws IOException
+ * if an i/o error occurs
+ */
+ public int read(byte[] buffer, int off, int len) throws IOException {
+ int attempts = 0;
+ for (;;) {
+ if (checkCancellation())
+ throw new OperationCanceledException();
+ try {
+ return in.read(buffer, off, len);
+ } catch (InterruptedIOException e) {
+ if (e.bytesTransferred != 0)
+ return e.bytesTransferred; // keep partial transfer
+ if (++attempts == numAttempts)
+ throw new InterruptedIOException(readTimeoutMessage);
+ }
+ }
+ }
+
+ /**
+ * Wraps the underlying stream's method.
+ *
+ * @param count
+ * - the number of bytes to be skipped.
+ * @return the actual number of bytes skipped.
+ * @throws OperationCanceledException
+ * if the progress monitor is canceled
+ * @throws InterruptedIOException
+ * if the underlying operation times out numAttempts times and
+ * no data was received, bytesTransferred will be zero
+ * @throws IOException
+ * if an i/o error occurs
+ */
+ public long skip(long count) throws IOException {
+ int attempts = 0;
+ for (;;) {
+ if (checkCancellation())
+ throw new OperationCanceledException();
+ try {
+ return in.skip(count);
+ } catch (InterruptedIOException e) {
+ if (e.bytesTransferred != 0)
+ return e.bytesTransferred; // keep partial transfer
+ if (++attempts == numAttempts)
+ throw new InterruptedIOException(readTimeoutMessage);
+ }
+ }
+ }
+
+ /**
+ * Reads any pending input from the input stream so that the stream can
+ * savely be closed.
+ *
+ * @throws IOException if some problem reading
+ */
+ protected void readPendingInput() throws IOException {
+ byte[] buffer = new byte[2048];
+ while (true) {
+ int available = in.available();
+ if (available < 1)
+ break;
+ if (available > buffer.length)
+ available = buffer.length;
+ if (in.read(buffer, 0, available) < 1)
+ break;
+ }
+ }
+
+ /**
+ * Called to set whether cancellation will be checked by this stream.
+ * Turning cancellation checking off can be very useful for protecting
+ * critical portions of a protocol that shouldn't be interrupted. For
+ * example, it is often necessary to protect login sequences.
+ *
+ * @param cancellable
+ * a flag controlling whether this stream will check for
+ * cancellation.
+ */
+ public void setIsCancellable(boolean cancellable) {
+ this.cancellable = cancellable;
+ }
+
+ /**
+ * Checked whether the monitor for this stream has been cancelled. If the
+ * cancellable flag is false then the monitor is never
+ * cancelled.
+ *
+ * @return true if the monitor has been cancelled and
+ * false otherwise.
+ */
+ private boolean checkCancellation() {
+ if (cancellable) {
+ return monitor.isCanceled();
+ }
+ return false;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/util/ProxySetupHelper.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/util/ProxySetupHelper.java
new file mode 100644
index 0000000000..bcd20edd16
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/util/ProxySetupHelper.java
@@ -0,0 +1,105 @@
+/****************************************************************************
+ * Copyright (c) 2010 IBM, and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.provider.filetransfer.util;
+
+import java.net.URI;
+import java.net.URL;
+import org.eclipse.core.net.proxy.IProxyData;
+import org.eclipse.core.net.proxy.IProxyService;
+import org.eclipse.ecf.core.util.Proxy;
+import org.eclipse.ecf.core.util.ProxyAddress;
+import org.eclipse.ecf.internal.provider.filetransfer.Activator;
+
+/**
+ * Proxy setup utilities.
+ *
+ * NOTE: Use of this class implies the presence of the core.net.proxy
+ * API...this class will not load (NoClassDefFoundError will be thrown if load/use is attempted)
+ * if the core.net.proxy bundle is not present in the runtime.
+ *
+ * @noextend This class is not intended to be extended by clients.
+ * @since 3.1
+ */
+public class ProxySetupHelper {
+ public static Proxy getProxy(String url) {
+ Proxy proxy = null;
+ try {
+ IProxyService proxyService = Activator.getDefault().getProxyService();
+ // Only do this if platform service exists
+ if (proxyService != null && proxyService.isProxiesEnabled()) {
+ // Setup via proxyService entry
+ URI uri = new URI(url);
+ final IProxyData[] proxies = proxyService.select(uri);
+ IProxyData selectedProxy = selectProxyFromProxies(uri.getScheme(), proxies);
+ if (selectedProxy != null) {
+ proxy = new Proxy(((selectedProxy.getType().equalsIgnoreCase(IProxyData.SOCKS_PROXY_TYPE)) ? Proxy.Type.SOCKS : Proxy.Type.HTTP), new ProxyAddress(selectedProxy.getHost(), selectedProxy.getPort()), selectedProxy.getUserId(), selectedProxy.getPassword());
+ }
+ }
+ } catch (Exception e) {
+ // If we don't even have the classes for this (i.e. the org.eclipse.core.net plugin not available)
+ // then we simply log and ignore
+ Activator.logNoProxyWarning(e);
+ } catch (NoClassDefFoundError e) {
+ Activator.logNoProxyWarning(e);
+ }
+ return proxy;
+ }
+
+ public static Proxy getSocksProxy(URL url) {
+ String host = url.getHost();
+ int port = url.getPort();
+ String strURL = IProxyData.SOCKS_PROXY_TYPE + "://" + host; //$NON-NLS-1$
+ if (port != -1) {
+ strURL += ":" + port; //$NON-NLS-1$
+ }
+ return ProxySetupHelper.getProxy(strURL);
+ }
+
+ /**
+ * Select a single proxy from a set of proxies available for the given host. This implementation
+ * selects in the following manner: 1) If proxies provided is null or array of 0 length, null
+ * is returned. If only one proxy is available (array of length 1) then the entry is returned.
+ * If proxies provided is length greater than 1, then if the type of a proxy in the array matches the given
+ * protocol (e.g. http, https), then the first matching proxy is returned. If the protocol does
+ * not match any of the proxies, then the *first* proxy (i.e. proxies[0]) is returned.
+ *
+ * @param protocol the target protocol (e.g. http, https, scp, etc). Will not be null.
+ * @param proxies the proxies to select from. May be null or array of length 0.
+ * @return proxy data selected from the proxies provided.
+ */
+ public static IProxyData selectProxyFromProxies(String protocol, IProxyData[] proxies) {
+ if (proxies == null || proxies.length == 0)
+ return null;
+ // If only one proxy is available, then use that
+ if (proxies.length == 1)
+ return proxies[0];
+ // If more than one proxy is available, then if http/https protocol then look for that
+ // one...if not found then use first
+ if (protocol.equalsIgnoreCase("http")) { //$NON-NLS-1$
+ for (IProxyData proxie : proxies) {
+ if (proxie.getType().equals(IProxyData.HTTP_PROXY_TYPE)) {
+ return proxie;
+ }
+ }
+ } else if (protocol.equalsIgnoreCase("https")) { //$NON-NLS-1$
+ for (IProxyData proxie : proxies) {
+ if (proxie.getType().equals(IProxyData.HTTPS_PROXY_TYPE)) {
+ return proxie;
+ }
+ }
+ }
+ // If we haven't found it yet, then return the first one.
+ return proxies[0];
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/util/TimeoutInputStream.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/util/TimeoutInputStream.java
new file mode 100644
index 0000000000..45109558a6
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/ecf/provider/filetransfer/util/TimeoutInputStream.java
@@ -0,0 +1,378 @@
+/****************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *****************************************************************************/
+package org.eclipse.ecf.provider.filetransfer.util;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+
+/**
+ * Wraps an input stream that blocks indefinitely to simulate timeouts on
+ * read(), skip(), and close(). The resulting input stream is buffered and
+ * supports retrying operations that failed due to an InterruptedIOException.
+ *
+ * Supports resuming partially completed operations after an
+ * InterruptedIOException REGARDLESS of whether the underlying stream does
+ * unless the underlying stream itself generates InterruptedIOExceptions in
+ * which case it must also support resuming. Check the bytesTransferred field to
+ * determine how much of the operation completed; conversely, at what point to
+ * resume.
+ *
+ * @since 3.0
+ */
+public class TimeoutInputStream extends FilterInputStream {
+ // unsynchronized variables
+ private final long readTimeout; // read() timeout in millis
+ private final long closeTimeout; // close() timeout in millis, or -1
+
+ // requests for the thread (synchronized)
+ private boolean closeRequested = false; // if true, close requested
+
+ // responses from the thread (synchronized)
+ private Thread thread; // if null, thread has terminated
+ private byte[] iobuffer; // circular buffer
+ private int head = 0; // points to first unread byte
+ private int length = 0; // number of remaining unread bytes
+ private IOException ioe = null; // if non-null, contains a pending exception
+ private boolean waitingForClose = false; // if true, thread is waiting for
+ // close()
+
+ private boolean growWhenFull = false; // if true, buffer will grow when it
+
+ // is full
+
+ /**
+ * Creates a timeout wrapper for an input stream.
+ *
+ * @param in
+ * the underlying input stream
+ * @param bufferSize
+ * the buffer size in bytes; should be large enough to mitigate
+ * Thread synchronization and context switching overhead
+ * @param readTimeout
+ * the number of milliseconds to block for a read() or skip()
+ * before throwing an InterruptedIOException; 0 blocks
+ * indefinitely
+ * @param closeTimeout
+ * the number of milliseconds to block for a close() before
+ * throwing an InterruptedIOException; 0 blocks indefinitely, -1
+ * closes the stream in the background
+ */
+ public TimeoutInputStream(InputStream in, int bufferSize, long readTimeout, long closeTimeout) {
+ super(in);
+ this.readTimeout = readTimeout;
+ this.closeTimeout = closeTimeout;
+ this.iobuffer = new byte[bufferSize];
+ thread = new Thread(new Runnable() {
+ public void run() {
+ runThread();
+ }
+ }, "TimeoutInputStream");//$NON-NLS-1$
+ thread.setDaemon(true);
+ thread.start();
+ }
+
+ public TimeoutInputStream(InputStream in, int bufferSize, long readTimeout, long closeTimeout, boolean growWhenFull) {
+ this(in, bufferSize, readTimeout, closeTimeout);
+ this.growWhenFull = growWhenFull;
+ }
+
+ /**
+ * Wraps the underlying stream's method. It may be important to wait for a
+ * stream to actually be closed because it holds an implicit lock on a
+ * system resoure (such as a file) while it is open. Closing a stream may
+ * take time if the underlying stream is still servicing a previous request.
+ *
+ * @throws InterruptedIOException
+ * if the timeout expired
+ * @throws IOException
+ * if an i/o error occurs
+ */
+ public void close() throws IOException {
+ Thread oldThread;
+ synchronized (this) {
+ if (thread == null)
+ return;
+ oldThread = thread;
+ closeRequested = true;
+ thread.interrupt();
+ checkError();
+ }
+ if (closeTimeout == -1)
+ return;
+ try {
+ oldThread.join(closeTimeout);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt(); // we weren't expecting to be
+ // interrupted
+ }
+ synchronized (this) {
+ checkError();
+ if (thread != null)
+ throw new InterruptedIOException();
+ }
+ }
+
+ /**
+ * Returns the number of unread bytes in the buffer.
+ *
+ * @throws IOException
+ * if an i/o error occurs
+ */
+ public synchronized int available() throws IOException {
+ if (length == 0)
+ checkError();
+ return length > 0 ? length : 0;
+ }
+
+ /**
+ * Reads a byte from the stream.
+ *
+ * @throws InterruptedIOException
+ * if the timeout expired and no data was received,
+ * bytesTransferred will be zero
+ * @throws IOException
+ * if an i/o error occurs
+ */
+ public synchronized int read() throws IOException {
+ if (!syncFill())
+ return -1; // EOF reached
+ int b = iobuffer[head++] & 255;
+ if (head == iobuffer.length)
+ head = 0;
+ length--;
+ notify();
+ return b;
+ }
+
+ /**
+ * Reads multiple bytes from the stream.
+ *
+ * @throws InterruptedIOException
+ * if the timeout expired and no data was received,
+ * bytesTransferred will be zero
+ * @throws IOException
+ * if an i/o error occurs
+ */
+ public synchronized int read(byte[] buffer, int off, int len) throws IOException {
+ if (!syncFill())
+ return -1; // EOF reached
+ int pos = off;
+ if (len > length)
+ len = length;
+ while (len-- > 0) {
+ buffer[pos++] = iobuffer[head++];
+ if (head == iobuffer.length)
+ head = 0;
+ length--;
+ }
+ notify();
+ return pos - off;
+ }
+
+ /**
+ * Skips multiple bytes in the stream.
+ *
+ * @throws InterruptedIOException
+ * if the timeout expired before all of the bytes specified have
+ * been skipped, bytesTransferred may be non-zero
+ * @throws IOException
+ * if an i/o error occurs
+ */
+ public synchronized long skip(long count) throws IOException {
+ long amount = 0;
+ try {
+ do {
+ if (!syncFill())
+ break; // EOF reached
+ int skip = (int) Math.min(count - amount, length);
+ head = (head + skip) % iobuffer.length;
+ length -= skip;
+ amount += skip;
+ } while (amount < count);
+ } catch (InterruptedIOException e) {
+ e.bytesTransferred = (int) amount; // assumes amount <
+ // Integer.MAX_INT
+ throw e;
+ }
+ notify();
+ return amount;
+ }
+
+ /**
+ * Mark is not supported by the wrapper even if the underlying stream does,
+ * returns false.
+ */
+ public boolean markSupported() {
+ return false;
+ }
+
+ /**
+ * Waits for the buffer to fill if it is empty and the stream has not
+ * reached EOF.
+ *
+ * @return true if bytes are available, false if EOF has been reached
+ * @throws InterruptedIOException
+ * if EOF not reached but no bytes are available
+ */
+ private boolean syncFill() throws IOException {
+ if (length != 0)
+ return true;
+ checkError(); // check errors only after we have read all remaining
+ // bytes
+ if (waitingForClose)
+ return false;
+ notify();
+ try {
+ wait(readTimeout);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt(); // we weren't expecting to be
+ // interrupted
+ }
+ if (length != 0)
+ return true;
+ checkError(); // check errors only after we have read all remaining
+ // bytes
+ if (waitingForClose)
+ return false;
+ throw new InterruptedIOException();
+ }
+
+ /**
+ * If an exception is pending, throws it.
+ */
+ private void checkError() throws IOException {
+ if (ioe != null) {
+ IOException e = ioe;
+ ioe = null;
+ throw e;
+ }
+ }
+
+ /**
+ * Runs the thread in the background.
+ */
+ void runThread() {
+ try {
+ readUntilDone();
+ } catch (IOException e) {
+ synchronized (this) {
+ ioe = e;
+ }
+ } finally {
+ waitUntilClosed();
+ try {
+ in.close();
+ } catch (IOException e) {
+ synchronized (this) {
+ ioe = e;
+ }
+ } finally {
+ synchronized (this) {
+ thread = null;
+ notify();
+ }
+ }
+ }
+ }
+
+ /**
+ * Waits until we have been requested to close the stream.
+ */
+ private synchronized void waitUntilClosed() {
+ waitingForClose = true;
+ notify();
+ while (!closeRequested) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ closeRequested = true; // alternate quit signal
+ }
+ }
+ }
+
+ /**
+ * Reads bytes into the buffer until EOF, closed, or error.
+ */
+ private void readUntilDone() throws IOException {
+ for (;;) {
+ int off, len;
+ synchronized (this) {
+ while (isBufferFull()) {
+ if (closeRequested)
+ return; // quit signal
+ waitForRead();
+ }
+ off = (head + length) % iobuffer.length;
+ len = ((head > off) ? head : iobuffer.length) - off;
+ }
+ int count;
+ try {
+ // the i/o operation might block without releasing the lock,
+ // so we do this outside of the synchronized block
+ count = in.read(iobuffer, off, len);
+ if (count == -1)
+ return; // EOF encountered
+ } catch (InterruptedIOException e) {
+ count = e.bytesTransferred; // keep partial transfer
+ }
+ synchronized (this) {
+ length += count;
+ notify();
+ }
+ }
+ }
+
+ /*
+ * Wait for a read when the buffer is full (with the implication that space
+ * will become available in the buffer after the read takes place).
+ */
+ private synchronized void waitForRead() {
+ try {
+ if (growWhenFull) {
+ // wait a second before growing to let reads catch up
+ wait(readTimeout);
+ } else {
+ wait();
+ }
+ } catch (InterruptedException e) {
+ closeRequested = true; // alternate quit signal
+ }
+ // If the buffer is still full, give it a chance to grow
+ if (growWhenFull && isBufferFull()) {
+ growBuffer();
+ }
+ }
+
+ private synchronized void growBuffer() {
+ int newSize = 2 * iobuffer.length;
+ if (newSize > iobuffer.length) {
+ byte[] newBuffer = new byte[newSize];
+ int pos = 0;
+ int len = length;
+ while (len-- > 0) {
+ newBuffer[pos++] = iobuffer[head++];
+ if (head == iobuffer.length)
+ head = 0;
+ }
+ iobuffer = newBuffer;
+ head = 0;
+ // length instance variable was not changed by this method
+ }
+ }
+
+ private boolean isBufferFull() {
+ return length == iobuffer.length;
+ }
+}
From 4026e9cd9c003f44e9819b5c4946e8a9ce1e5a78 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 13 Dec 2025 16:02:46 +0000
Subject: [PATCH 4/4] Remove P2SSLContextFactory that depends on ECF interface
Co-authored-by: laeubi <1331477+laeubi@users.noreply.github.com>
---
.../p2/transport/ecf/P2SSLContextFactory.java | 52 -------------------
1 file changed, 52 deletions(-)
delete mode 100644 bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/P2SSLContextFactory.java
diff --git a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/P2SSLContextFactory.java b/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/P2SSLContextFactory.java
deleted file mode 100644
index 4cfd64597c..0000000000
--- a/bundles/org.eclipse.equinox.p2.transport.native/src/org/eclipse/equinox/internal/p2/transport/ecf/P2SSLContextFactory.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2025 Christoph Läubrich and others.
- * The code, documentation and other materials contained herein have been
- * licensed under the Eclipse Public License - v 1.0 by the copyright holder
- * listed above, as the Initial Contributor under such license. The text of
- * such license is available at www.eclipse.org.
- * Contributors:
- * Christoph Läubrich - initial implementation
- ******************************************************************************/
-package org.eclipse.equinox.internal.p2.transport.ecf;
-
-import java.security.*;
-import javax.net.ssl.SSLContext;
-import org.eclipse.ecf.core.security.SSLContextFactory;
-import org.osgi.framework.Constants;
-import org.osgi.service.component.annotations.Component;
-
-@Component(property = Constants.SERVICE_RANKING + ":Integer=100")
-public class P2SSLContextFactory implements SSLContextFactory {
-
- @Override
- public SSLContext getDefault() throws NoSuchAlgorithmException {
- // the default is guaranteed to be initialized always
- return SSLContext.getDefault();
- }
-
- @Override
- public SSLContext getInstance(String protocol) throws NoSuchAlgorithmException, NoSuchProviderException {
- SSLContext context = SSLContext.getInstance(protocol);
- try {
- // init it as we have a new context here
- context.init(null, null, null);
- } catch (KeyManagementException e) {
- throw new NoSuchProviderException();
- }
- return context;
- }
-
- @Override
- public SSLContext getInstance(String protocol, String providerName)
- throws NoSuchAlgorithmException, NoSuchProviderException {
- SSLContext context = SSLContext.getInstance(protocol, providerName);
- try {
- // init it as we have a new context here
- context.init(null, null, null);
- } catch (KeyManagementException e) {
- throw new NoSuchProviderException();
- }
- return context;
- }
-
-}