WinCEConnectorService
.
+ *
+ * By implementing this interface, subsystems can be recognized
+ * as being able to share a single WinCE connector service between
+ * multiple different subsystems.
+ */
+public interface IWinCESubSystem {
+
+}
diff --git a/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/connectorservice/wince/Messages.java b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/connectorservice/wince/Messages.java
new file mode 100644
index 00000000000..40cd19dff16
--- /dev/null
+++ b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/connectorservice/wince/Messages.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.rse.internal.connectorservice.wince;
+
+import org.eclipse.osgi.util.NLS;
+
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.rse.internal.connectorservice.wince.messages"; //$NON-NLS-1$
+ public static String WinCEConnectorService_0;
+ public static String WinCEConnectorService_1;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ }
+}
diff --git a/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/connectorservice/wince/WinCEConnectorService.java b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/connectorservice/wince/WinCEConnectorService.java
new file mode 100644
index 00000000000..d824cb33f70
--- /dev/null
+++ b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/connectorservice/wince/WinCEConnectorService.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.rse.internal.connectorservice.wince;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.rse.core.model.IHost;
+import org.eclipse.rse.core.subsystems.BasicConnectorService;
+import org.eclipse.rse.core.subsystems.CommunicationsEvent;
+import org.eclipse.rse.internal.services.wince.IRapiSessionProvider;
+import org.eclipse.tm.rapi.IRapiDesktop;
+import org.eclipse.tm.rapi.IRapiDevice;
+import org.eclipse.tm.rapi.IRapiEnumDevices;
+import org.eclipse.tm.rapi.IRapiSession;
+import org.eclipse.tm.rapi.OS;
+import org.eclipse.tm.rapi.RapiException;
+
+
+/**
+ * Creates ActiveSync/RAPI2 connections to WinCE-based device.
+ */
+public class WinCEConnectorService extends BasicConnectorService implements IRapiSessionProvider {
+
+ IRapiDesktop desktop = null;
+ IRapiEnumDevices enumDevices = null;
+ IRapiDevice device = null;
+ IRapiSession session = null;
+
+ public WinCEConnectorService(IHost host) {
+ super(Messages.WinCEConnectorService_0, Messages.WinCEConnectorService_1, host, 0);
+ }
+
+ protected void internalConnect(IProgressMonitor monitor) throws Exception {
+ fireCommunicationsEvent(CommunicationsEvent.BEFORE_CONNECT);
+ OS.CoInitializeEx(0, OS.COINIT_MULTITHREADED);
+ desktop = IRapiDesktop.getInstance();
+ enumDevices = desktop.enumDevices();
+ device = enumDevices.next();
+ session = device.createSession();
+ session.init();
+ }
+
+ protected void internalDisconnect(IProgressMonitor monitor) throws Exception {
+ fireCommunicationsEvent(CommunicationsEvent.BEFORE_DISCONNECT);
+ if (session != null) {
+ session.uninit();
+ session.release();
+ session = null;
+ }
+ if (device != null) {
+ device.release();
+ device = null;
+ }
+ if (enumDevices != null) {
+ enumDevices.release();
+ enumDevices = null;
+ }
+ if (desktop != null) {
+ desktop.release();
+ desktop = null;
+ }
+ }
+
+ public boolean isConnected() {
+ if (device != null) {
+ try {
+ return device.isConnected();
+ } catch (RapiException e) {
+ //ignore
+ }
+ }
+ return false;
+ }
+
+ public IRapiSession getSession() {
+ return session;
+ }
+
+}
diff --git a/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/connectorservice/wince/WinCEConnectorServiceManager.java b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/connectorservice/wince/WinCEConnectorServiceManager.java
new file mode 100644
index 00000000000..cd4c3e12995
--- /dev/null
+++ b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/connectorservice/wince/WinCEConnectorServiceManager.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.rse.internal.connectorservice.wince;
+
+import org.eclipse.rse.core.model.IHost;
+import org.eclipse.rse.core.subsystems.AbstractConnectorServiceManager;
+import org.eclipse.rse.core.subsystems.IConnectorService;
+import org.eclipse.rse.core.subsystems.ISubSystem;
+
+public class WinCEConnectorServiceManager extends AbstractConnectorServiceManager {
+
+ private static WinCEConnectorServiceManager inst = null;
+
+ private WinCEConnectorServiceManager() {
+ super();
+ }
+
+ public static WinCEConnectorServiceManager getInstance() {
+ if (inst == null) {
+ inst = new WinCEConnectorServiceManager();
+ }
+ return inst;
+ }
+
+ public IConnectorService createConnectorService(IHost host) {
+ IConnectorService connectorService = new WinCEConnectorService(host);
+ return connectorService;
+ }
+
+ public Class getSubSystemCommonInterface(ISubSystem subsystem) {
+ return IWinCESubSystem.class;
+ }
+
+ public boolean sharesSystem(ISubSystem otherSubSystem) {
+ return (otherSubSystem instanceof IWinCESubSystem);
+ }
+
+}
diff --git a/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/connectorservice/wince/messages.properties b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/connectorservice/wince/messages.properties
new file mode 100644
index 00000000000..ea4ff0c151c
--- /dev/null
+++ b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/connectorservice/wince/messages.properties
@@ -0,0 +1,2 @@
+WinCEConnectorService_0=WinCE Connector Service
+WinCEConnectorService_1=The WinCE Connector Service uses ActiveSync/RAPI2 to connect to the device.
diff --git a/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/IRapiSessionProvider.java b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/IRapiSessionProvider.java
new file mode 100644
index 00000000000..8fec7f8d73e
--- /dev/null
+++ b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/IRapiSessionProvider.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.rse.internal.services.wince;
+
+import org.eclipse.tm.rapi.IRapiSession;
+
+public interface IRapiSessionProvider {
+
+ /**
+ * Returns an active RAPI2 session from a ConnectorService.
+ */
+ public IRapiSession getSession();
+
+}
diff --git a/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/IWinCEService.java b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/IWinCEService.java
new file mode 100644
index 00000000000..6f00956cc70
--- /dev/null
+++ b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/IWinCEService.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.rse.internal.services.wince;
+
+/**
+ * Markup Interface for services using the WinCEConnectorService
.
+ *
+ * By implementing this interface, services can be recognized
+ * as operating against an WinCEConnectorService
.
+ * The interface is used as the key in a table for looking up the connector
+ * service when needed.
+ */
+public interface IWinCEService {
+
+}
diff --git a/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/files/Messages.java b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/files/Messages.java
new file mode 100644
index 00000000000..bbc8934a6f1
--- /dev/null
+++ b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/files/Messages.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.rse.internal.services.wince.files;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class Messages {
+ private static final String BUNDLE_NAME = "org.eclipse.rse.internal.services.wince.files.messages"; //$NON-NLS-1$
+
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+ .getBundle(BUNDLE_NAME);
+
+ private Messages() {
+ }
+
+ public static String getString(String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
+ }
+ }
+}
diff --git a/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/files/WinCEFileService.java b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/files/WinCEFileService.java
new file mode 100644
index 00000000000..96dcf06e9af
--- /dev/null
+++ b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/files/WinCEFileService.java
@@ -0,0 +1,502 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.rse.internal.services.wince.files;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.rse.internal.services.wince.IRapiSessionProvider;
+import org.eclipse.rse.internal.services.wince.IWinCEService;
+import org.eclipse.rse.services.clientserver.FileTypeMatcher;
+import org.eclipse.rse.services.clientserver.IMatcher;
+import org.eclipse.rse.services.clientserver.NamePatternMatcher;
+import org.eclipse.rse.services.clientserver.messages.SystemMessageException;
+import org.eclipse.rse.services.files.AbstractFileService;
+import org.eclipse.rse.services.files.IFileService;
+import org.eclipse.rse.services.files.IHostFile;
+import org.eclipse.rse.services.files.RemoteFileException;
+import org.eclipse.tm.rapi.IRapiSession;
+import org.eclipse.tm.rapi.OS;
+import org.eclipse.tm.rapi.RapiException;
+import org.eclipse.tm.rapi.RapiFindData;
+
+public class WinCEFileService extends AbstractFileService implements IWinCEService {
+
+ IRapiSessionProvider sessionProvider;
+
+ public WinCEFileService(IRapiSessionProvider sessionProvider) {
+ this.sessionProvider = sessionProvider;
+ }
+
+ String concat(String parentDir, String fileName) {
+ String result = parentDir;
+ if (!result.endsWith("\\")) { //$NON-NLS-1$
+ result += "\\"; //$NON-NLS-1$
+ }
+ result += fileName;
+ return result;
+ }
+
+ protected IHostFile[] internalFetch(String parentPath, String fileFilter,
+ int fileType, IProgressMonitor monitor) throws SystemMessageException {
+ if (fileFilter == null) {
+ fileFilter = "*"; //$NON-NLS-1$
+ }
+ IMatcher fileMatcher = null;
+ if (fileFilter.endsWith(",")) { //$NON-NLS-1$
+ String[] types = fileFilter.split(","); //$NON-NLS-1$
+ fileMatcher = new FileTypeMatcher(types, true);
+ } else {
+ fileMatcher = new NamePatternMatcher(fileFilter, true, true);
+ }
+ List results = new ArrayList();
+ try {
+ IRapiSession session = sessionProvider.getSession();
+ RapiFindData[] foundFiles = session.findAllFiles(concat(parentPath,"*"), //$NON-NLS-1$
+ OS.FAF_NAME | OS.FAF_ATTRIBUTES | OS.FAF_LASTWRITE_TIME |
+ OS.FAF_SIZE_HIGH | OS.FAF_SIZE_LOW);
+ for (int i = 0 ; i < foundFiles.length ; i++) {
+ String fileName = foundFiles[i].fileName;
+ if (fileMatcher.matches(fileName)) {
+ WinCEHostFile hostFile = makeHostFile(parentPath, fileName, foundFiles[i]);
+ if (isRightType(fileType, hostFile)) {
+ results.add(hostFile);
+ }
+ }
+ }
+ } catch (RapiException e) {
+ //FIXME error handling
+ throw new RemoteFileException(e.getMessage());
+ }
+ return (IHostFile[]) results.toArray(new IHostFile[results.size()]);
+ }
+
+ private WinCEHostFile makeHostFile(String parentPath, String fileName, RapiFindData findData) {
+ boolean isDirectory = (findData.fileAttributes & OS.FILE_ATTRIBUTE_DIRECTORY) != 0;
+ boolean isRoot = "\\".equals(parentPath) && "\\".equals(fileName); //$NON-NLS-1$ //$NON-NLS-2$
+ long lastModified = (findData.lastWriteTime / 10000) - OS.TIME_DIFF;
+ long size = findData.fileSize;
+ return new WinCEHostFile(parentPath, fileName, isDirectory, isRoot, lastModified, size);
+ }
+
+ private boolean isDirectory(IRapiSession session, String fullPath) {
+ int attr = session.getFileAttributes(fullPath);
+ if (attr == -1) {
+ return false;
+ }
+ return (attr & OS.FILE_ATTRIBUTE_DIRECTORY) != 0;
+ }
+
+ private boolean exist(IRapiSession session, String fileName) {
+ return session.getFileAttributes(fileName) != -1;
+ }
+
+ public boolean copy(String srcParent, String srcName, String tgtParent,
+ String tgtName, IProgressMonitor monitor) throws SystemMessageException {
+ String srcFullPath = concat(srcParent, srcName);
+ String tgtFullPath = concat(tgtParent, tgtName);
+ if (srcFullPath.equals(tgtFullPath)) {
+ // prevent copying file/folder to itself
+ return false;
+ }
+ IRapiSession session = sessionProvider.getSession();
+ try {
+ if (isDirectory(session, srcFullPath)) {
+ if (tgtFullPath.startsWith(srcFullPath + "\\")) { //$NON-NLS-1$
+ // prevent copying \a to \a\b\c
+ return false;
+ }
+ if (exist(session, tgtFullPath)) {
+ // we are doing overwrite,
+ // if the target file or folder already exist - delete it
+ delete(tgtParent, tgtName, monitor);
+ }
+ session.createDirectory(tgtFullPath);
+ RapiFindData[] allFiles = session.findAllFiles(concat(srcFullPath,"*"), OS.FAF_NAME); //$NON-NLS-1$
+ for (int i = 0 ; i < allFiles.length ; i++) {
+ String fileName = allFiles[i].fileName;
+ copy(srcFullPath, fileName, tgtFullPath, fileName, monitor);
+ }
+ } else {
+ session.copyFile(srcFullPath, tgtFullPath);
+ }
+ } catch (RapiException e) {
+ //FIXME error handling
+ throw new RemoteFileException(e.getMessage());
+ }
+ return true;
+ }
+
+ public boolean copyBatch(String[] srcParents, String[] srcNames,
+ String tgtParent, IProgressMonitor monitor) throws SystemMessageException {
+ boolean ok = true;
+ for (int i = 0 ; i < srcParents.length ; i++) {
+ ok = ok && copy(srcParents[i], srcNames[i], tgtParent, srcNames[i], monitor);
+ }
+ return ok;
+ }
+
+ public IHostFile createFile(String remoteParent, String fileName, IProgressMonitor monitor) throws SystemMessageException {
+ String fullPath = concat(remoteParent, fileName);
+ IRapiSession session = sessionProvider.getSession();
+ try {
+ int handle = session.createFile(fullPath, OS.GENERIC_WRITE, OS.FILE_SHARE_READ,
+ OS.CREATE_ALWAYS, OS.FILE_ATTRIBUTE_NORMAL);
+ session.closeHandle(handle);
+ RapiFindData findData = new RapiFindData();
+ handle = session.findFirstFile(fullPath, findData);
+ session.findClose(handle);
+ return makeHostFile(remoteParent, fileName, findData);
+ } catch (RapiException e) {
+ //FIXME error handling
+ throw new RemoteFileException(e.getMessage());
+ }
+ }
+
+ public IHostFile createFolder(String remoteParent, String folderName, IProgressMonitor monitor) throws SystemMessageException {
+ String fullPath = concat(remoteParent, folderName);
+ IRapiSession session = sessionProvider.getSession();
+ try {
+ session.createDirectory(fullPath);
+ RapiFindData findData = new RapiFindData();
+ int handle = session.findFirstFile(fullPath, findData);
+ session.findClose(handle);
+ return makeHostFile(remoteParent, folderName, findData);
+ } catch (RapiException e) {
+ //FIXME error handling
+ throw new RemoteFileException(e.getMessage());
+ }
+ }
+
+ public boolean delete(String remoteParent, String fileName, IProgressMonitor monitor) throws SystemMessageException {
+ String fullPath = concat(remoteParent, fileName);
+ IRapiSession session = sessionProvider.getSession();
+ try {
+ if (isDirectory(session, fullPath)) {
+ // recursive delete if it is a directory
+ RapiFindData[] allFiles = session.findAllFiles(concat(fullPath, "*"), OS.FAF_NAME); //$NON-NLS-1$
+ for (int i = 0 ; i < allFiles.length ; i++) {
+ delete(fullPath, allFiles[i].fileName, monitor);
+ }
+ session.removeDirectory(fullPath);
+ } else {
+ // it is a file
+ session.deleteFile(fullPath);
+ }
+ } catch (RapiException e) {
+ //FIXME error handling
+ throw new RemoteFileException(e.getMessage());
+ }
+ return true;
+ }
+
+ public boolean download(String remoteParent, String remoteFile, File localFile, boolean isBinary, String hostEncoding,
+ IProgressMonitor monitor) throws SystemMessageException {
+
+ if (!localFile.exists()) {
+ File localParentFile = localFile.getParentFile();
+ if (!localParentFile.exists()) {
+ localParentFile.mkdirs();
+ }
+ }
+ String fullPath = concat(remoteParent, remoteFile);
+ IRapiSession session = sessionProvider.getSession();
+ int handle = OS.INVALID_HANDLE_VALUE;
+ BufferedOutputStream bos = null;
+ try {
+ handle = session.createFile(fullPath, OS.GENERIC_READ,
+ OS.FILE_SHARE_READ, OS.OPEN_EXISTING, OS.FILE_ATTRIBUTE_NORMAL);
+ bos = new BufferedOutputStream(new FileOutputStream(localFile));
+ // TODO: find the optimal buffer size
+ byte[] buffer = new byte[8 * 1024];
+ while (true) {
+ int bytesRead = session.readFile(handle, buffer);
+ if (bytesRead == -1) {
+ break;
+ }
+ bos.write(buffer, 0, bytesRead);
+ }
+ bos.flush();
+ } catch (RapiException e) {
+ //FIXME error handling
+ throw new RemoteFileException(e.getMessage());
+ } catch (IOException e) {
+ //FIXME error handling
+ throw new RemoteFileException(e.getMessage());
+ } finally {
+ if (handle != OS.INVALID_HANDLE_VALUE) {
+ try {
+ session.closeHandle(handle);
+ } catch (RapiException e) {
+ // ignore
+ }
+ }
+ if (bos != null) {
+ try {
+ bos.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+ return true;
+ }
+
+ public IHostFile getFile(String remoteParent, String name, IProgressMonitor monitor) throws SystemMessageException {
+ IRapiSession session = sessionProvider.getSession();
+ try {
+ RapiFindData findData = new RapiFindData();
+ int h = session.findFirstFile(concat(remoteParent, name), findData);
+ session.findClose(h);
+ return makeHostFile(remoteParent, name, findData);
+ } catch (RapiException e) {
+ // ignore the exception and return dummy
+ }
+ // return dummy if the file doesn't exist
+ WinCEHostFile dummy = new WinCEHostFile(remoteParent, name, false, false, 0, 0);
+ dummy.setExists(false);
+ return dummy;
+ }
+
+ public IHostFile[] getRoots(IProgressMonitor monitor) throws SystemMessageException {
+ return new WinCEHostFile[] { new WinCEHostFile("\\", "\\", true, true, 0, 0) }; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public IHostFile getUserHome() {
+ return new WinCEHostFile("\\", "My Documents", true, false, 0, 0); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public boolean isCaseSensitive() {
+ return false;
+ }
+
+ public boolean move(String srcParent, String srcName, String tgtParent, String tgtName,
+ IProgressMonitor monitor) throws SystemMessageException {
+ boolean ok = copy(srcParent, srcName, tgtParent, tgtName, monitor);
+ ok = ok && delete(srcParent, srcName, monitor);
+ return ok;
+ }
+
+ public boolean rename(String remoteParent, String oldName, String newName,
+ IProgressMonitor monitor) throws SystemMessageException {
+ String oldFullPath = concat(remoteParent, oldName);
+ String newFullPath = concat(remoteParent, newName);
+ IRapiSession session = sessionProvider.getSession();
+ try {
+ session.moveFile(oldFullPath, newFullPath);
+ } catch (RapiException e) {
+ //FIXME error handling
+ throw new RemoteFileException(e.getMessage());
+ }
+ return true;
+ }
+
+ public boolean rename(String remoteParent, String oldName, String newName, IHostFile oldFile,
+ IProgressMonitor monitor) throws SystemMessageException {
+ boolean retVal = rename(remoteParent, oldName, newName, monitor);
+ String newFullPath = concat(remoteParent, newName);
+ oldFile.renameTo(newFullPath);
+ return retVal;
+ }
+
+ public boolean setLastModified(String parent, String name, long timestamp, IProgressMonitor monitor) throws SystemMessageException {
+ return false;
+ }
+
+ public boolean setReadOnly(String parent, String name, boolean readOnly, IProgressMonitor monitor) throws SystemMessageException {
+ return false;
+ }
+
+ public boolean upload(InputStream stream, String remoteParent, String remoteFile, boolean isBinary,
+ String hostEncoding, IProgressMonitor monitor) throws SystemMessageException {
+ BufferedInputStream bis = new BufferedInputStream(stream);
+ IRapiSession session = sessionProvider.getSession();
+ String fullPath = concat(remoteParent, remoteFile);
+ int handle = OS.INVALID_HANDLE_VALUE;
+ try {
+ handle = session.createFile(fullPath, OS.GENERIC_WRITE,
+ OS.FILE_SHARE_READ, OS.CREATE_ALWAYS, OS.FILE_ATTRIBUTE_NORMAL);
+ // TODO: find the optimal buffer size
+ byte[] buffer = new byte[8 * 1024];
+ while (true) {
+ int bytesRead = bis.read(buffer);
+ if (bytesRead == -1) {
+ break;
+ }
+ session.writeFile(handle, buffer, 0, bytesRead);
+ }
+ } catch (RapiException e) {
+ //FIXME error handling
+ throw new RemoteFileException(e.getMessage());
+ } catch (IOException e) {
+ //FIXME error handling
+ throw new RemoteFileException(e.getMessage());
+ } finally {
+ if (handle != OS.INVALID_HANDLE_VALUE) {
+ try {
+ session.closeHandle(handle);
+ } catch (RapiException e) {
+ // ignore
+ }
+ }
+ try {
+ bis.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ return true;
+ }
+
+ public boolean upload(File localFile, String remoteParent, String remoteFile, boolean isBinary,
+ String srcEncoding, String hostEncoding, IProgressMonitor monitor) throws SystemMessageException {
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(localFile);
+ } catch (FileNotFoundException e) {
+ //FIXME error handling
+ throw new RemoteFileException(e.getMessage());
+ }
+ //FIXME what to do with srcEncoding ?
+ return upload(fis, remoteParent, remoteFile, isBinary, hostEncoding, monitor);
+ }
+
+ public InputStream getInputStream(String remoteParent, String remoteFile,
+ boolean isBinary, IProgressMonitor monitor) throws SystemMessageException {
+ String fullPath = concat(remoteParent, remoteFile);
+ IRapiSession session = sessionProvider.getSession();
+ try {
+ int handle = session.createFile(fullPath, OS.GENERIC_READ,
+ OS.FILE_SHARE_READ, OS.OPEN_EXISTING, OS.FILE_ATTRIBUTE_NORMAL);
+ return new BufferedInputStream(new WinCEInputStream(session, handle));
+ } catch (RapiException e) {
+ //FIXME error handling
+ throw new RemoteFileException(e.getMessage());
+ }
+ }
+
+ public OutputStream getOutputStream(String remoteParent, String remoteFile,
+ int options, IProgressMonitor monitor) throws SystemMessageException {
+ String fullPath = concat(remoteParent, remoteFile);
+ IRapiSession session = sessionProvider.getSession();
+ try {
+ int cd = OS.CREATE_ALWAYS;
+ if ((options & IFileService.APPEND) == 0) {
+ cd = OS.CREATE_ALWAYS;
+ } else {
+ cd = OS.OPEN_EXISTING;
+ }
+ int handle = session.createFile(fullPath, OS.GENERIC_WRITE,
+ OS.FILE_SHARE_READ, cd, OS.FILE_ATTRIBUTE_NORMAL);
+ return new BufferedOutputStream(new WinCEOutputStream(session, handle));
+ } catch (RapiException e) {
+ //FIXME error handling
+ throw new RemoteFileException(e.getMessage());
+ }
+ }
+
+ public String getDescription() {
+ return Messages.getString("WinCEFileService.12"); //$NON-NLS-1$
+ }
+
+ public String getName() {
+ return Messages.getString("WinCEFileService.13"); //$NON-NLS-1$
+ }
+
+ public void initService(IProgressMonitor monitor) {
+ }
+
+ public void uninitService(IProgressMonitor monitor) {
+ }
+
+ private static class WinCEInputStream extends InputStream {
+
+ private int handle;
+ private IRapiSession session;
+
+ public WinCEInputStream(IRapiSession session, int handle) {
+ this.handle = handle;
+ this.session = session;
+ }
+
+ public int read() throws IOException {
+ byte[] b = new byte[1];
+ try {
+ int br = session.readFile(handle, b);
+ return (br == -1) ? -1 : b[0];
+ } catch (RapiException e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException {
+ try {
+ return session.readFile(handle, b, off, len);
+ } catch (RapiException e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ public void close() throws IOException {
+ try {
+ session.closeHandle(handle);
+ } catch (RapiException e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ }
+
+ private static class WinCEOutputStream extends OutputStream {
+
+ private int handle;
+ private IRapiSession session;
+
+ public WinCEOutputStream(IRapiSession session, int handle) {
+ this.session = session;
+ this.handle = handle;
+ }
+
+ public void write(int b) throws IOException {
+ try {
+ session.writeFile(handle, new byte[] {(byte)b});
+ } catch (RapiException e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ public void write(byte[] b, int off, int len) throws IOException {
+ try {
+ session.writeFile(handle, b, off, len);
+ } catch (RapiException e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+
+ public void close() throws IOException {
+ try {
+ session.closeHandle(handle);
+ } catch (RapiException e) {
+ throw new IOException(e.getMessage());
+ }
+ }
+ }
+}
diff --git a/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/files/WinCEHostFile.java b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/files/WinCEHostFile.java
new file mode 100644
index 00000000000..2002310cc6b
--- /dev/null
+++ b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/files/WinCEHostFile.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.rse.internal.services.wince.files;
+
+import org.eclipse.rse.services.files.IHostFile;
+
+public class WinCEHostFile implements IHostFile {
+
+ String name;
+ String parentPath;
+ boolean isDirectory;
+ boolean isRoot;
+ boolean isArchive = false;
+ boolean isReadable = true;
+ boolean isWritable = true;
+ boolean exists = true;
+ long lastModified = 0;
+ long size = 0;
+
+ public WinCEHostFile(String parentPath, String name, boolean isDirectory, boolean isRoot, long lastModified, long size) {
+ this.parentPath = parentPath;
+ this.name = name;
+ this.isDirectory = isDirectory;
+ this.isRoot = isRoot;
+ this.lastModified = lastModified;
+ this.size = size;
+ }
+
+ public boolean canRead() {
+ return isReadable;
+ }
+
+ public boolean canWrite() {
+ return isWritable;
+ }
+
+ public boolean exists() {
+ return exists;
+ }
+
+ public void setExists(boolean exists) {
+ this.exists = exists;
+ }
+
+ public String getAbsolutePath() {
+ if (isRoot()) {
+ return getName();
+ }
+ String path = parentPath;
+ if (!parentPath.endsWith("\\")) { //$NON-NLS-1$
+ path += "\\"; //$NON-NLS-1$
+ }
+ path += name;
+ return path;
+ }
+
+ public long getModifiedDate() {
+ return lastModified;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getParentPath() {
+ return parentPath;
+ }
+
+ public long getSize() {
+ return size;
+ }
+
+ public boolean isArchive() {
+ return isArchive;
+ }
+
+ public boolean isDirectory() {
+ return isDirectory;
+ }
+
+ public boolean isFile() {
+ return !(isDirectory || isRoot);
+ }
+
+ public boolean isHidden() {
+ return false;
+ }
+
+ public boolean isRoot() {
+ return isRoot;
+ }
+
+ public void renameTo(String newAbsolutePath) {
+ int ind = newAbsolutePath.lastIndexOf("\\"); //$NON-NLS-1$
+ if (ind == -1) {
+ name = newAbsolutePath;
+ } else {
+ parentPath = newAbsolutePath.substring(0, ind);
+ name = newAbsolutePath.substring(ind+1);
+ }
+ }
+
+}
diff --git a/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/files/messages.properties b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/files/messages.properties
new file mode 100644
index 00000000000..7a9b556b6d9
--- /dev/null
+++ b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/services/wince/files/messages.properties
@@ -0,0 +1,2 @@
+WinCEFileService.12=The WinCE File Service uses ActiveSync/RAPI2 to provide service to the Files subsystem on the device.
+WinCEFileService.13=WinCE File Service
diff --git a/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/subsystems/files/wince/Activator.java b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/subsystems/files/wince/Activator.java
new file mode 100644
index 00000000000..19bb77a30a4
--- /dev/null
+++ b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/subsystems/files/wince/Activator.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.rse.internal.subsystems.files.wince;
+
+import org.eclipse.rse.ui.SystemBasePlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends SystemBasePlugin {
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+ protected void initializeImageRegistry() {
+ //TODO
+ }
+
+}
diff --git a/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/subsystems/files/wince/WinCEFileAdapter.java b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/subsystems/files/wince/WinCEFileAdapter.java
new file mode 100644
index 00000000000..8c5518b68a1
--- /dev/null
+++ b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/subsystems/files/wince/WinCEFileAdapter.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.rse.internal.subsystems.files.wince;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.rse.internal.services.wince.files.WinCEHostFile;
+import org.eclipse.rse.services.files.IHostFile;
+import org.eclipse.rse.subsystems.files.core.servicesubsystem.FileServiceSubSystem;
+import org.eclipse.rse.subsystems.files.core.subsystems.IHostFileToRemoteFileAdapter;
+import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile;
+import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileContext;
+
+
+public class WinCEFileAdapter implements IHostFileToRemoteFileAdapter {
+
+ public IRemoteFile convertToRemoteFile(FileServiceSubSystem ss,
+ IRemoteFileContext context, IRemoteFile parent, IHostFile node) {
+
+ IRemoteFile remoteFile = new WinCERemoteFile(ss, context, parent, (WinCEHostFile)node);
+ ss.cacheRemoteFile(remoteFile);
+ return remoteFile;
+ }
+
+ public IRemoteFile[] convertToRemoteFiles(FileServiceSubSystem ss,
+ IRemoteFileContext context, IRemoteFile parent, IHostFile[] nodes) {
+
+ List results = new ArrayList();
+ if (nodes != null) {
+ for (int i = 0 ; i < nodes.length ; i++) {
+ WinCEHostFile node = (WinCEHostFile) nodes[i];
+ IRemoteFile remoteFile = new WinCERemoteFile(ss, context, parent, node);
+ results.add(remoteFile);
+ ss.cacheRemoteFile(remoteFile);
+ }
+ }
+ return (IRemoteFile[])results.toArray(new IRemoteFile[results.size()]);
+ }
+
+}
diff --git a/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/subsystems/files/wince/WinCERemoteFile.java b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/subsystems/files/wince/WinCERemoteFile.java
new file mode 100644
index 00000000000..54481e70cd6
--- /dev/null
+++ b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/internal/subsystems/files/wince/WinCERemoteFile.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.rse.internal.subsystems.files.wince;
+
+import org.eclipse.rse.internal.services.wince.files.WinCEHostFile;
+import org.eclipse.rse.subsystems.files.core.servicesubsystem.AbstractRemoteFile;
+import org.eclipse.rse.subsystems.files.core.servicesubsystem.FileServiceSubSystem;
+import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile;
+import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileContext;
+
+
+public class WinCERemoteFile extends AbstractRemoteFile {
+
+ public WinCERemoteFile(FileServiceSubSystem subSystem,
+ IRemoteFileContext context, IRemoteFile parent, WinCEHostFile hostFile) {
+ super(subSystem, context, parent, hostFile);
+ }
+
+ public String getCanonicalPath() {
+ return getAbsolutePath();
+ }
+
+ public String getClassification() {
+ // TODO
+ return "unknown"; //$NON-NLS-1$
+ }
+
+ public String getEncoding() {
+ // override the default implementation because it causes
+ // infinite loop on WinCE, see bug #218947
+ return getParentRemoteFileSubSystem().getRemoteEncoding();
+ }
+
+}
diff --git a/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/subsystems/files/wince/WinCEFileServiceSubSystem.java b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/subsystems/files/wince/WinCEFileServiceSubSystem.java
new file mode 100644
index 00000000000..a92f5202342
--- /dev/null
+++ b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/subsystems/files/wince/WinCEFileServiceSubSystem.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.rse.subsystems.files.wince;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.rse.core.model.IHost;
+import org.eclipse.rse.core.subsystems.IConnectorService;
+import org.eclipse.rse.services.clientserver.messages.SystemMessage;
+import org.eclipse.rse.services.clientserver.messages.SystemMessageException;
+import org.eclipse.rse.services.files.IFileService;
+import org.eclipse.rse.services.files.IHostFile;
+import org.eclipse.rse.services.search.ISearchService;
+import org.eclipse.rse.subsystems.files.core.servicesubsystem.FileServiceSubSystem;
+import org.eclipse.rse.subsystems.files.core.subsystems.IHostFileToRemoteFileAdapter;
+import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFile;
+import org.eclipse.rse.ui.ISystemMessages;
+import org.eclipse.rse.ui.RSEUIPlugin;
+
+public class WinCEFileServiceSubSystem extends FileServiceSubSystem {
+
+ public WinCEFileServiceSubSystem(IHost host, IConnectorService connectorService, IFileService hostFileService,
+ IHostFileToRemoteFileAdapter fileAdapter, ISearchService searchService) {
+ super(host, connectorService, hostFileService, fileAdapter, searchService);
+ }
+
+ public IRemoteFile getRemoteFileObject(String folderOrFileName, IProgressMonitor monitor) throws SystemMessageException {
+ String fofName = folderOrFileName.replace('/', '\\');
+ IRemoteFile file = getCachedRemoteFile(fofName);
+ if (file != null && !file.isStale()) {
+ return file;
+ }
+
+ // for bug 207095, implicit connect if the connection is not connected
+ checkIsConnected(monitor);
+
+ if (fofName.equals("\\")) { //$NON-NLS-1$
+ try {
+ return listRoots(null)[0];
+ } catch (Exception e) {
+ }
+ }
+
+ if (fofName.equals(".")) { //$NON-NLS-1$
+ IRemoteFile userHome = getUserHome();
+ if (userHome == null){
+ // with 207095, it's possible that we could be trying to get user home when not connected
+ SystemMessage msg = RSEUIPlugin.getPluginMessage(ISystemMessages.MSG_ERROR_UNEXPECTED);
+ throw new SystemMessageException(msg);
+ }
+ return userHome;
+ }
+
+ if (fofName.endsWith("\\")) { //$NON-NLS-1$
+ fofName = fofName.substring(0, fofName.length() - 1);
+ }
+
+ int lastSep = fofName.lastIndexOf("\\"); //$NON-NLS-1$
+ if (lastSep > -1) {
+ String parentPath = fofName.substring(0, lastSep);
+ if (parentPath.length() == 0) {
+ parentPath = "\\"; //$NON-NLS-1$
+ }
+ String name = fofName.substring(lastSep + 1, fofName.length());
+
+ IHostFile node = getFile(parentPath, name, monitor);
+ if (node != null) {
+ IRemoteFile parent = null;
+ if (!node.isRoot()) {
+ //parent = getRemoteFileObject(parentPath);
+ }
+ return getHostFileToRemoteFileAdapter().convertToRemoteFile(this, getDefaultContext(), parent, node);
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/subsystems/files/wince/WinCEFileSubSystemConfiguration.java b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/subsystems/files/wince/WinCEFileSubSystemConfiguration.java
new file mode 100644
index 00000000000..98b8c20828c
--- /dev/null
+++ b/wince/org.eclipse.rse.subsystems.wince/src/org/eclipse/rse/subsystems/files/wince/WinCEFileSubSystemConfiguration.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.rse.subsystems.files.wince;
+
+import java.util.Vector;
+
+import org.eclipse.rse.core.filters.ISystemFilterPool;
+import org.eclipse.rse.core.filters.ISystemFilterPoolManager;
+import org.eclipse.rse.core.model.IHost;
+import org.eclipse.rse.core.subsystems.IConnectorService;
+import org.eclipse.rse.core.subsystems.ISubSystem;
+import org.eclipse.rse.internal.connectorservice.wince.WinCEConnectorService;
+import org.eclipse.rse.internal.connectorservice.wince.WinCEConnectorServiceManager;
+import org.eclipse.rse.internal.services.wince.IWinCEService;
+import org.eclipse.rse.internal.services.wince.files.WinCEFileService;
+import org.eclipse.rse.internal.subsystems.files.wince.WinCEFileAdapter;
+import org.eclipse.rse.services.clientserver.SystemSearchString;
+import org.eclipse.rse.services.files.IFileService;
+import org.eclipse.rse.services.search.IHostSearchResultConfiguration;
+import org.eclipse.rse.services.search.IHostSearchResultSet;
+import org.eclipse.rse.services.search.ISearchService;
+import org.eclipse.rse.subsystems.files.core.ILanguageUtilityFactory;
+import org.eclipse.rse.subsystems.files.core.model.RemoteFileFilterString;
+import org.eclipse.rse.subsystems.files.core.servicesubsystem.FileServiceSubSystemConfiguration;
+import org.eclipse.rse.subsystems.files.core.subsystems.IHostFileToRemoteFileAdapter;
+import org.eclipse.rse.subsystems.files.core.subsystems.IRemoteFileSubSystem;
+import org.eclipse.rse.ui.SystemBasePlugin;
+
+public class WinCEFileSubSystemConfiguration extends FileServiceSubSystemConfiguration {
+
+ IHostFileToRemoteFileAdapter hostFileAdapter;
+
+ public IFileService createFileService(IHost host) {
+ WinCEConnectorService connectorService = (WinCEConnectorService) getConnectorService(host);
+ return new WinCEFileService(connectorService);
+ }
+
+ public ISubSystem createSubSystemInternal(IHost host) {
+ WinCEConnectorService connectorService = (WinCEConnectorService) getConnectorService(host);
+ return new WinCEFileServiceSubSystem(host, connectorService, getFileService(host), getHostFileAdapter(), getSearchService(host));
+ }
+
+ public IHostSearchResultConfiguration createSearchConfiguration(IHost host,
+ IHostSearchResultSet resultSet, Object searchTarget,
+ SystemSearchString searchString) {
+ return null;
+ }
+
+ public ISearchService createSearchService(IHost host) {
+ return null;
+ }
+
+ protected ISystemFilterPool createDefaultFilterPool(ISystemFilterPoolManager mgr) {
+ ISystemFilterPool pool = null;
+ try {
+ pool = mgr.createSystemFilterPool(getDefaultFilterPoolName(mgr.getName(), getId()), true);
+ Vector filterStrings = new Vector();
+
+ // "My Home" filter
+ filterStrings = new Vector();
+ RemoteFileFilterString myHomeFilterString = new RemoteFileFilterString(this);
+ myHomeFilterString.setPath("\\My Documents\\"); //$NON-NLS-1$
+ filterStrings.add(myHomeFilterString.toString());
+ mgr.createSystemFilter(pool, "My Home", filterStrings);
+ //filter.setNonChangable(true);
+ //filter.setSingleFilterStringOnly(true);
+
+ // "Root Files" filter
+ filterStrings = new Vector();
+ RemoteFileFilterString rootFilesFilterString = new RemoteFileFilterString(this);
+ filterStrings.add(rootFilesFilterString.toString());
+ mgr.createSystemFilter(pool, "Root", filterStrings);
+ } catch (Exception exc) {
+ SystemBasePlugin.logError("Error creating default filter pool",exc); //$NON-NLS-1$
+ }
+ return pool;
+ }
+
+ public IHostFileToRemoteFileAdapter getHostFileAdapter() {
+ if (hostFileAdapter == null) {
+ hostFileAdapter = new WinCEFileAdapter();
+ }
+ return hostFileAdapter;
+ }
+
+ public ILanguageUtilityFactory getLanguageUtilityFactory(
+ IRemoteFileSubSystem ss) {
+ return null;
+ }
+
+ public boolean supportsSearch() {
+ return false;
+ }
+
+ public boolean supportsArchiveManagement() {
+ return false;
+ }
+
+ public IConnectorService getConnectorService(IHost host) {
+ return WinCEConnectorServiceManager.getInstance().getConnectorService(host, getServiceImplType());
+ }
+
+ public Class getServiceImplType() {
+ return IWinCEService.class;
+ }
+
+ public void setConnectorService(IHost host, IConnectorService connectorService) {
+ WinCEConnectorServiceManager.getInstance().setConnectorService(host, getServiceImplType(), connectorService);
+ }
+
+}
diff --git a/wince/org.eclipse.tm.rapi.examples/.classpath b/wince/org.eclipse.tm.rapi.examples/.classpath
new file mode 100644
index 00000000000..751c8f2e504
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi.examples/.classpath
@@ -0,0 +1,7 @@
+
+RapiFindData
+ * describes a directory.
+ */
+ boolean isDirectory(RapiFindData findData) {
+ return (findData.fileAttributes & OS.FILE_ATTRIBUTE_DIRECTORY) != 0;
+ }
+
+ /**
+ * Utility method used for printing RapiFindData
on the console.
+ */
+ void printFindData(RapiFindData findData, int indent) {
+ for (int i = 0 ; i < indent ; i++) {
+ System.out.print(" ");
+ }
+ String fileName = findData.fileName;
+ if (isDirectory(findData)) {
+ System.out.println("[" + fileName + "]");
+ } else {
+ System.out.println(fileName + " (" + findData.fileSize + ")");
+ }
+ }
+
+ /**
+ * List all files in the specified directory using
+ * IRapiSession.findFirstFile
and
+ * IRapiSession.findNextFile
+ */
+ public void listFiles(String dir) throws RapiException {
+ System.out.println(">>> listFiles()");
+ RapiFindData findData = new RapiFindData();;
+ int fh = session.findFirstFile(dir + "*", findData);
+ while (findData != null) {
+ printFindData(findData, 0);
+ findData = session.findNextFile(fh);
+ }
+ session.findClose(fh);
+ }
+
+ /**
+ * List all files in the specified directory using
+ * IRapiSession.findAllFiles
+ */
+ public void listFiles2(String dir) throws RapiException {
+ System.out.println(">>> listFiles2()");
+ RapiFindData[] fdArr = session.findAllFiles(dir + "*",
+ OS.FAF_ATTRIBUTES | OS.FAF_NAME | OS.FAF_SIZE_LOW);
+ for (int i = 0 ; i < fdArr.length ; i++) {
+ printFindData(fdArr[i], 0);
+ }
+ }
+
+ /**
+ * Prints various information about the specified file.
+ */
+ public void statFile(String fileName) throws RapiException {
+ System.out.println(">>> statFile()");
+ int handle = session.createFile(fileName, OS.GENERIC_READ,
+ OS.FILE_SHARE_READ, OS.OPEN_EXISTING, OS.FILE_ATTRIBUTE_NORMAL);
+ int fileAttributes = session.getFileAttributes(fileName);
+ System.out.println("fileAttributes: " + fileAttributes);
+ long fileSize = session.getFileSize(handle);
+ System.out.println("fileSize: " + fileSize);
+ System.out.println("creationTime: " + session.getFileCreationTime(handle));
+ System.out.println("lastAccessTime: " + session.getFileLastAccessTime(handle));
+ System.out.println("lastWriteTime: " + session.getFileLastWriteTime(handle));
+ session.closeHandle(handle);
+ }
+
+ /**
+ * Recursively print the whole device tree on the console.
+ */
+ void printDeviceTree(String dir, int indent) throws RapiException {
+ RapiFindData[] fdArr = session.findAllFiles(dir + "*",
+ OS.FAF_ATTRIBUTES | OS.FAF_NAME | OS.FAF_SIZE_LOW);
+ if (fdArr == null) {
+ return;
+ }
+ for (int i = 0 ; i < fdArr.length ; i++) {
+ if (isDirectory(fdArr[i])) {
+ printDeviceTree(dir + fdArr[i].fileName + "\\", indent + 1);
+ } else {
+ printFindData(fdArr[i], indent);
+ }
+ }
+ }
+
+ void runExamples() {
+ try {
+ initRapi();
+ desktop = IRapiDesktop.getInstance();
+ enumDevices = desktop.enumDevices();
+ // get the first device
+ device = enumDevices.next();
+ printDeviceInfo();
+ printConnectionInfo();
+ // create session
+ session = device.createSession();
+ session.init();
+ createFile("\\foo.txt");
+ readFile("\\foo.txt");
+ session.copyFile("\\foo.txt", "\\bar.txt");
+ listFiles("\\");
+ session.moveFile("\\bar.txt", "\\spam.txt");
+ listFiles2("\\");
+ session.deleteFile("\\spam.txt");
+ statFile("\\foo.txt");
+ System.out.println(">>> printDeviceTree()");
+ printDeviceTree("\\", 0);
+ session.uninit();
+ } catch (RapiException e) {
+ e.printStackTrace();
+ } finally {
+ uninitRapi();
+ }
+ }
+}
diff --git a/wince/org.eclipse.tm.rapi.tests/.classpath b/wince/org.eclipse.tm.rapi.tests/.classpath
new file mode 100644
index 00000000000..751c8f2e504
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi.tests/.classpath
@@ -0,0 +1,7 @@
+
+len
bytes of the specified arrays
+ * are equal.
+ */
+ boolean arraysEqual(byte[] arr1, byte[] arr2, int len) {
+ for (int i = 0 ; i < len ; i++) {
+ if (arr1[i] != arr2[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns true if the specified path
exists and it is a directory.
+ */
+ boolean isDirectory(String path) {
+ int attr = session.getFileAttributes(path);
+ if (attr == -1) {
+ return false;
+ }
+ return (attr & OS.FILE_ATTRIBUTE_DIRECTORY) != 0;
+ }
+
+ /**
+ * Returns true if the specified path
exists and it is a file.
+ */
+ boolean isFile(String path) {
+ int attr = session.getFileAttributes(path);
+ if (attr == -1) {
+ return false;
+ }
+ return (attr & OS.FILE_ATTRIBUTE_DIRECTORY) == 0;
+ }
+
+ /**
+ * Tests reading and writing files on the device.
+ */
+ public void testReadWriteFiles() throws RapiException {
+ createInitSession();
+
+ // generate random file content
+ byte[] content = new byte[TEST_FILE_SIZE];
+ for (int i = 0 ; i < content.length ; i++) {
+ content[i] = (byte)(Math.random() * 131);
+ }
+
+ // write the test file at once
+ int handle = session.createFile(TEST_FILE_NAME, OS.GENERIC_WRITE,
+ OS.FILE_SHARE_READ, OS.CREATE_ALWAYS, OS.FILE_ATTRIBUTE_NORMAL);
+ session.writeFile(handle, content);
+ session.closeHandle(handle);
+
+ // try to read the whole file
+ handle = session.createFile(TEST_FILE_NAME, OS.GENERIC_READ,
+ OS.FILE_SHARE_READ, OS.OPEN_EXISTING, OS.FILE_ATTRIBUTE_NORMAL);
+ byte[] contentRead = new byte[TEST_FILE_SIZE];
+ int br = session.readFile(handle, contentRead);
+ session.closeHandle(handle);
+ assertTrue("Different file content", arraysEqual(content, contentRead, br));
+
+ // write the test file by chunks
+ handle = session.createFile(TEST_FILE_NAME, OS.GENERIC_WRITE,
+ OS.FILE_SHARE_READ, OS.CREATE_ALWAYS, OS.FILE_ATTRIBUTE_NORMAL);
+ int off = 0;
+ for (int i = 0 ; i < TEST_FILE_SIZE / CHUNK_SIZE ; i++) {
+ session.writeFile(handle, content, off, CHUNK_SIZE);
+ off += CHUNK_SIZE;
+ }
+ session.closeHandle(handle);
+
+ // read the test file by chunks
+ handle = session.createFile(TEST_FILE_NAME, OS.GENERIC_READ,
+ OS.FILE_SHARE_READ, OS.OPEN_EXISTING, OS.FILE_ATTRIBUTE_NORMAL);
+ byte[] contentRead2 = new byte[TEST_FILE_SIZE];
+ off = 0;
+ int bytesToRead = TEST_FILE_SIZE;
+ while (bytesToRead > 0) {
+ int len = CHUNK_SIZE < bytesToRead ? CHUNK_SIZE : bytesToRead;
+ br = session.readFile(handle, contentRead2, off, len);
+ off += br;
+ bytesToRead -= br;
+ }
+ session.closeHandle(handle);
+ assertTrue("Different file content", arraysEqual(content, contentRead2, TEST_FILE_SIZE));
+
+ // delete the test file
+ session.deleteFile(TEST_FILE_NAME);
+ }
+
+ /**
+ * Tests creating and removing directories on the device.
+ */
+ public void testCreateRemoveDirectories() throws RapiException {
+ createInitSession();
+ try {
+ session.removeDirectory(TEST_DIR_NAME);
+ } catch (RapiException re) {
+ // ignore
+ }
+ session.createDirectory(TEST_DIR_NAME);
+ assertTrue("Failed to create directory", isDirectory(TEST_DIR_NAME));
+ session.removeDirectory(TEST_DIR_NAME);
+ assertFalse("Failed to remove directory", isDirectory(TEST_DIR_NAME));
+ }
+
+ /**
+ * Tests copying, moving and deleting files on the device.
+ */
+ public void testCopyMoveDeleteFiles() throws RapiException {
+ createInitSession();
+
+ // create test file
+ int handle = session.createFile(TEST_FILE_NAME, OS.GENERIC_WRITE,
+ OS.FILE_SHARE_READ, OS.CREATE_ALWAYS, OS.FILE_ATTRIBUTE_NORMAL);
+ session.writeFile(handle, "spam".getBytes());
+ session.closeHandle(handle);
+
+ // make a copy
+ String copy = TEST_FILE_NAME + "1";
+ session.copyFile(TEST_FILE_NAME, copy);
+ assertTrue("Failed to copy file", isFile(copy));
+
+ // delete the test file
+ session.deleteFile(TEST_FILE_NAME);
+ assertFalse("Failed to delete file", isFile(TEST_FILE_NAME));
+
+ // rename the copy
+ session.moveFile(copy, TEST_FILE_NAME);
+ assertTrue("Failed to move file", isFile(TEST_FILE_NAME));
+ assertFalse("Failed to move file", isFile(copy));
+
+ // delete test file
+ session.deleteFile(TEST_FILE_NAME);
+ }
+
+ /**
+ * Utility method for creating a bunch of files.
+ */
+ void createTempFiles() throws RapiException {
+ for (int i = 0 ; i < TEMP_FILES_COUNT ; i++) {
+ int handle = session.createFile(TEST_FILE_NAME + i, OS.GENERIC_WRITE,
+ OS.FILE_SHARE_READ, OS.CREATE_ALWAYS, OS.FILE_ATTRIBUTE_NORMAL);
+ session.writeFile(handle, "spam".getBytes());
+ session.closeHandle(handle);
+ }
+ }
+
+ /**
+ * Tests finding files using {@link IRapiSession#findFirstFile(String, RapiFindData)}
+ */
+ public void testFindFiles() throws RapiException {
+ createInitSession();
+ createTempFiles();
+ int filesFound = 0;
+ RapiFindData findData = new RapiFindData();
+ int fh = session.findFirstFile(TEST_FILE_NAME + "?", findData);
+ while (findData != null) {
+ filesFound++;
+ findData = session.findNextFile(fh);
+ }
+ session.findClose(fh);
+ assertTrue("Found " + filesFound + " , expected " + TEMP_FILES_COUNT,
+ filesFound == TEMP_FILES_COUNT);
+ // clean up
+ for (int i = 0 ; i < TEMP_FILES_COUNT ; i++) {
+ session.deleteFile(TEST_FILE_NAME + i);
+ }
+ }
+
+ /**
+ * Tests finding files using {@link IRapiSession#findAllFiles(String, int)}
+ */
+ public void testFindAllFiles() throws RapiException {
+ createInitSession();
+ createTempFiles();
+ RapiFindData[] faf = session.findAllFiles(TEST_FILE_NAME + "?", OS.FAF_NAME);
+ int filesFound = faf.length;
+ assertTrue("Found " + filesFound + " , expected " + TEMP_FILES_COUNT,
+ filesFound == TEMP_FILES_COUNT);
+ // clean up
+ for (int i = 0 ; i < TEMP_FILES_COUNT ; i++) {
+ session.deleteFile(TEST_FILE_NAME + i);
+ }
+ }
+
+ /**
+ * Tests getting file attributes, size, etc.
+ */
+ public void testStatFiles() throws RapiException {
+ createInitSession();
+ // create test file
+ int handle = session.createFile(TEST_FILE_NAME, OS.GENERIC_WRITE,
+ OS.FILE_SHARE_READ, OS.CREATE_ALWAYS, OS.FILE_ATTRIBUTE_NORMAL);
+ session.writeFile(handle, "spam".getBytes());
+ assertTrue("Wrong file size", 4 == session.getFileSize(handle));
+ //TODO: add some checks for file times (creation, last modified, etc)
+ session.closeHandle(handle);
+ int attr = session.getFileAttributes(TEST_FILE_NAME);
+ assertTrue("Wrong file attributes", (attr & OS.FILE_ATTRIBUTE_ARCHIVE) != 0);
+ //clean up
+ session.deleteFile(TEST_FILE_NAME);
+ }
+
+ protected void tearDown() throws Exception {
+ if (session != null) {
+ session.uninit();
+ }
+ super.tearDown();
+ }
+
+}
diff --git a/wince/org.eclipse.tm.rapi.tests/src/org/eclipse/tm/rapi/tests/RapiTestCase.java b/wince/org.eclipse.tm.rapi.tests/src/org/eclipse/tm/rapi/tests/RapiTestCase.java
new file mode 100644
index 00000000000..d83f2c91852
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi.tests/src/org/eclipse/tm/rapi/tests/RapiTestCase.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.rapi.tests;
+
+import org.eclipse.tm.rapi.IRapiDesktop;
+import org.eclipse.tm.rapi.IRapiDevice;
+import org.eclipse.tm.rapi.IRapiEnumDevices;
+import org.eclipse.tm.rapi.IRapiSession;
+import org.eclipse.tm.rapi.OS;
+
+import junit.framework.TestCase;
+
+public class RapiTestCase extends TestCase {
+
+ protected IRapiDesktop desktop = null;
+ protected IRapiEnumDevices enumDevices = null;
+ protected IRapiDevice device = null;
+ protected IRapiSession session = null;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ desktop = null;
+ enumDevices = null;
+ device = null;
+ session = null;
+ OS.CoInitializeEx(0, OS.COINIT_MULTITHREADED);
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (desktop != null) {
+ desktop.release();
+ }
+ if (enumDevices != null) {
+ enumDevices.release();
+ }
+ if (device != null) {
+ device.release();
+ }
+ if (session != null) {
+ session.release();
+ }
+ OS.CoUninitialize();
+ }
+
+}
diff --git a/wince/org.eclipse.tm.rapi/.classpath b/wince/org.eclipse.tm.rapi/.classpath
new file mode 100644
index 00000000000..751c8f2e504
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi/.classpath
@@ -0,0 +1,7 @@
+
+IRapiDesktop
.
+ *
+ * @author Radoslav Gerganov
+ */
+public class RapiDesktop extends IRapiDesktop {
+
+ public RapiDesktop(int addr) {
+ super(addr);
+ }
+
+ public IRapiEnumDevices enumDevices() throws RapiException {
+ int[] ppIEnum = new int[1];
+ int rc = EnumDevices(addr, ppIEnum);
+ if (rc != OS.NOERROR) {
+ throw new RapiException("EnumDevices failed", rc);
+ }
+ return new RapiEnumDevices(ppIEnum[0]);
+ }
+
+ public String toString() {
+ return "[RapiDesktop] addr: " + Integer.toHexString(addr);
+ }
+
+ private final native int EnumDevices(int addr, int[] ppIEnum);
+}
diff --git a/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/internal/rapi/RapiDevice.java b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/internal/rapi/RapiDevice.java
new file mode 100644
index 00000000000..621fda2d2e4
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/internal/rapi/RapiDevice.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.internal.rapi;
+
+import org.eclipse.tm.rapi.IRapiDevice;
+import org.eclipse.tm.rapi.IRapiSession;
+import org.eclipse.tm.rapi.OS;
+import org.eclipse.tm.rapi.RapiConnectionInfo;
+import org.eclipse.tm.rapi.RapiDeviceInfo;
+import org.eclipse.tm.rapi.RapiException;
+
+/**
+ * Implementation of IRapiDevice
.
+ *
+ * @author Radoslav Gerganov
+ */
+public class RapiDevice extends IRapiDevice {
+
+ public RapiDevice(int addr) {
+ super(addr);
+ }
+
+ public IRapiSession createSession() throws RapiException {
+ int[] ppISession = new int[1];
+ int rc = CreateSession(addr, ppISession);
+ if (rc != OS.NOERROR) {
+ throw new RapiException("CreateSession failed", rc);
+ }
+ return new RapiSession(ppISession[0]);
+ }
+
+ public RapiConnectionInfo getConnectionInfo() throws RapiException {
+ RapiConnectionInfo connInfo = new RapiConnectionInfo();
+ int rc = GetConnectionInfo(addr, connInfo);
+ if (rc != OS.NOERROR) {
+ throw new RapiException("GetConnectionInfo failed", rc);
+ }
+ return connInfo;
+ }
+
+ public RapiDeviceInfo getDeviceInfo() throws RapiException {
+ RapiDeviceInfo devInfo = new RapiDeviceInfo();
+ int rc = GetDeviceInfo(addr, devInfo);
+ if (rc != OS.NOERROR) {
+ throw new RapiException("GetDeviceInfo failed", rc);
+ }
+ return devInfo;
+ }
+
+ public boolean isConnected() throws RapiException {
+ int[] status = new int[1];
+ int rc = GetConnectStat(addr, status);
+ if (rc != OS.NOERROR) {
+ throw new RapiException("GetConnectStat failed", rc);
+ }
+ return status[0] == 1;
+ }
+
+ public String toString() {
+ return "[RapiDevice] addr: " + Integer.toHexString(addr);
+ }
+
+ private final native int CreateSession(int addr, int[] ppISession);
+ private final native int GetConnectionInfo(int addr, RapiConnectionInfo pConnInfo);
+ private final native int GetDeviceInfo(int addr, RapiDeviceInfo pDevInfo);
+ private final native int GetConnectStat(int addr, int[] status);
+}
diff --git a/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/internal/rapi/RapiEnumDevices.java b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/internal/rapi/RapiEnumDevices.java
new file mode 100644
index 00000000000..8f9c1e26b40
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/internal/rapi/RapiEnumDevices.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.internal.rapi;
+
+import org.eclipse.tm.rapi.IRapiDevice;
+import org.eclipse.tm.rapi.IRapiEnumDevices;
+import org.eclipse.tm.rapi.OS;
+import org.eclipse.tm.rapi.RapiException;
+
+/**
+ * Implementation of IRapiEnumDevices
.
+ *
+ * @author Radoslav Gerganov
+ */
+public class RapiEnumDevices extends IRapiEnumDevices {
+
+ public RapiEnumDevices(int addr) {
+ super(addr);
+ }
+
+ public IRapiDevice next() throws RapiException {
+ int[] ppIDevice = new int[1];
+ int rc = Next(addr, ppIDevice);
+ if (rc != OS.NOERROR) {
+ throw new RapiException("Next failed", rc);
+ }
+ return new RapiDevice(ppIDevice[0]);
+ }
+
+ public String toString() {
+ return "[RapiEnumDevices] addr: " + Integer.toHexString(addr);
+ }
+
+ private final native int Next(int addr, int[] ppIDevice);
+}
diff --git a/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/internal/rapi/RapiSession.java b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/internal/rapi/RapiSession.java
new file mode 100644
index 00000000000..f8cf86a59ef
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/internal/rapi/RapiSession.java
@@ -0,0 +1,310 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.internal.rapi;
+
+import java.util.Date;
+
+import org.eclipse.tm.rapi.IRapiSession;
+import org.eclipse.tm.rapi.OS;
+import org.eclipse.tm.rapi.RapiException;
+import org.eclipse.tm.rapi.RapiFindData;
+
+
+/**
+ * Implementation of IRapiSession
.
+ *
+ * @author Radoslav Gerganov
+ */
+public class RapiSession extends IRapiSession {
+
+ private RapiFindData[] EMPTY_FIND_DATA_ARR = new RapiFindData[0];
+
+ public RapiSession(int addr) {
+ super(addr);
+ }
+
+ private int getError() {
+ int err = CeRapiGetError(addr);
+ if (err >= 0) {
+ err = CeGetLastError(addr);
+ }
+ return err;
+ }
+
+ public void init() throws RapiException {
+ int rc = CeRapiInit(addr);
+ if (rc != OS.NOERROR) {
+ throw new RapiException("CeRapiInit failed", rc);
+ }
+ }
+
+ public void uninit() throws RapiException {
+ int rc = CeRapiUninit(addr);
+ if (rc != OS.NOERROR) {
+ throw new RapiException("CeRapiUninit failed", rc);
+ }
+ }
+
+ public int createFile(String fileName, int desiredAccess, int shareMode,
+ int creationDisposition, int flagsAndAttributes) throws RapiException {
+
+ int handle = CeCreateFile(addr, fileName, desiredAccess, shareMode,
+ creationDisposition, flagsAndAttributes);
+ if (handle == OS.INVALID_HANDLE_VALUE) {
+ throw new RapiException("CeCreateFile failed", getError());
+ }
+ return handle;
+ }
+
+ public int readFile(int handle, byte[] b) throws RapiException {
+ if (b.length == 0) {
+ return 0;
+ }
+ int[] bytesRead = new int[1];
+ boolean res = CeReadFile(addr, handle, b, b.length, bytesRead);
+ if (!res) {
+ throw new RapiException("CeReadFile failed", getError());
+ }
+ return bytesRead[0] > 0 ? bytesRead[0] : -1;
+ }
+
+ public int readFile(int handle, byte[] b, int off, int len)
+ throws RapiException {
+ if (off < 0 || len < 0 || off + len > b.length) {
+ throw new IndexOutOfBoundsException("Incorrect offset/length");
+ }
+ if (len == 0) {
+ return 0;
+ }
+ //TODO: add support for setting offset in the native code and remove this tmp array
+ byte[] tmp = new byte[len];
+ int[] bytesRead = new int[1];
+ boolean res = CeReadFile(addr, handle, tmp, tmp.length, bytesRead);
+ if (!res) {
+ throw new RapiException("CeReadFile failed", getError());
+ }
+ System.arraycopy(tmp, 0, b, off, len);
+ return bytesRead[0] > 0 ? bytesRead[0] : -1;
+ }
+
+ public void writeFile(int handle, byte[] b) throws RapiException {
+ int[] bytesWritten = new int[1];
+ boolean res = CeWriteFile(addr, handle, b, b.length, bytesWritten);
+ if (!res) {
+ throw new RapiException("CeWriteFile failed", getError());
+ }
+ }
+
+ public void writeFile(int handle, byte[] b, int off, int len)
+ throws RapiException {
+
+ if (off < 0 || len < 0 || off + len > b.length) {
+ throw new IndexOutOfBoundsException("Incorrect offset/length");
+ }
+ //TODO: add support for setting offset in the native code and remove this tmp array
+ byte[] tmp = new byte[len];
+ System.arraycopy(b, off, tmp, 0, len);
+ int[] bytesWritten = new int[1];
+ boolean res = CeWriteFile(addr, handle, tmp, tmp.length, bytesWritten);
+ if (!res) {
+ throw new RapiException("CeWriteFile failed", getError());
+ }
+ }
+
+ public void closeHandle(int handle) throws RapiException {
+ boolean res = CeCloseHandle(addr, handle);
+ if (!res) {
+ throw new RapiException("CeCloseHandle failed", getError());
+ }
+ }
+
+ public void copyFile(String existingFile, String newFile) throws RapiException {
+ //overwrite by default
+ boolean res = CeCopyFile(addr, existingFile, newFile, false);
+ if (!res) {
+ throw new RapiException("CeCopyFile failed", getError());
+ }
+ }
+
+ public void deleteFile(String fileName) throws RapiException {
+ boolean res = CeDeleteFile(addr, fileName);
+ if (!res) {
+ throw new RapiException("CeDeleteFile failed", getError());
+ }
+ }
+
+ public void moveFile(String existingFileName, String newFileName) throws RapiException {
+ boolean res = CeMoveFile(addr, existingFileName, newFileName);
+ if (!res) {
+ throw new RapiException("CeMoveFile failed", getError());
+ }
+ }
+
+ public void createDirectory(String pathName) throws RapiException {
+ boolean res = CeCreateDirectory(addr, pathName);
+ if (!res) {
+ throw new RapiException("CeCreateDirectory failed", getError());
+ }
+ }
+
+ public void removeDirectory(String pathName) throws RapiException {
+ boolean res = CeRemoveDirectory(addr, pathName);
+ if (!res) {
+ throw new RapiException("CeRemoveDirectory failed", getError());
+ }
+ }
+
+ public int findFirstFile(String fileName, RapiFindData findData) throws RapiException {
+ int handle = CeFindFirstFile(addr, fileName, findData);
+ if (handle == OS.INVALID_HANDLE_VALUE) {
+ throw new RapiException("CeFindFirstFile failed", getError());
+ }
+ return handle;
+ }
+
+ public RapiFindData findNextFile(int handle) {
+ RapiFindData findData = new RapiFindData();
+ boolean res = CeFindNextFile(addr, handle, findData);
+ // just return null if findNext fail
+ return res ? findData : null;
+ }
+
+ public void findClose(int handle) throws RapiException {
+ boolean res = CeFindClose(addr, handle);
+ if (!res) {
+ throw new RapiException("CeFindClose failed", getError());
+ }
+ }
+
+ public RapiFindData[] findAllFiles(String path, int flags) throws RapiException {
+ int[] foundCount = new int[1];
+ int[] dataArr = new int[1];
+ boolean res = CeFindAllFiles(addr, path, flags, foundCount, dataArr);
+ int count = foundCount[0];
+ if (!res || count == 0) {
+ // nothing found
+ return EMPTY_FIND_DATA_ARR;
+ }
+ RapiFindData[] findDataArr = new RapiFindData[count];
+ for (int i = 0 ; i < count ; i++) {
+ findDataArr[i] = new RapiFindData();
+ }
+ int hRes = CeFindAllFilesEx(addr, count, dataArr[0], findDataArr);
+ if (hRes != OS.NOERROR) {
+ throw new RapiException("CeFindAllFilesEx failed", hRes);
+ }
+ return findDataArr;
+ }
+
+ public int getFileAttributes(String fileName) {
+ int attributes = CeGetFileAttributes(addr, fileName);
+// if (attributes == 0xFFFFFFFF) {
+// throw new RapiException("CeGetFileAttributes failed", getError());
+// }
+ return attributes;
+ }
+
+ public long getFileSize(int handle) {
+ int[] sizeHigh = new int[] {1};
+ int sizeLow = CeGetFileSize(addr, handle, sizeHigh);
+ return ( ((long)sizeHigh[0] << 32) | (sizeLow & 0xFFFFFFFF));
+ }
+
+ public Date getFileCreationTime(int handle) throws RapiException {
+ long[] crTime = new long[1];
+ long[] laTime = new long[1];
+ long[] lwTime = new long[1];
+ boolean res = CeGetFileTime(addr, handle, crTime, laTime, lwTime);
+ if (!res) {
+ throw new RapiException("CeGetFileTime failed", getError());
+ }
+ return new Date((crTime[0] / 10000) - OS.TIME_DIFF);
+ }
+
+ public Date getFileLastAccessTime(int handle) throws RapiException {
+ long[] crTime = new long[1];
+ long[] laTime = new long[1];
+ long[] lwTime = new long[1];
+ boolean res = CeGetFileTime(addr, handle, crTime, laTime, lwTime);
+ if (!res) {
+ throw new RapiException("CeGetFileTime failed", getError());
+ }
+ return new Date((laTime[0] / 10000) - OS.TIME_DIFF);
+ }
+
+ public Date getFileLastWriteTime(int handle) throws RapiException {
+ long[] crTime = new long[1];
+ long[] laTime = new long[1];
+ long[] lwTime = new long[1];
+ boolean res = CeGetFileTime(addr, handle, crTime, laTime, lwTime);
+ if (!res) {
+ throw new RapiException("CeGetFileTime failed", getError());
+ }
+ return new Date((lwTime[0] / 10000) - OS.TIME_DIFF);
+ }
+
+ public String toString() {
+ return "[RapiSession] addr: " + Integer.toHexString(addr);
+ }
+
+ private final native int CeRapiInit(int addr);
+
+ private final native int CeRapiUninit(int addr);
+
+ private final native int CeRapiGetError(int addr);
+
+ private final native int CeGetLastError(int addr);
+
+ private final native int CeCreateFile(int addr, String lpFileName,
+ int dwDesiredAccess, int dwShareMode, int dwCreationDisposition,
+ int dwFlagsAndAttributes);
+
+ private final native boolean CeReadFile(int addr, int hFile, byte[] lpBuffer,
+ int nNumberOfBytesToRead, int[] lpNumberOfBytesRead);
+
+ private final native boolean CeWriteFile(int addr, int hFile, byte[] lpBuffer,
+ int nNumberOfBytesToWrite, int[] lpNumberOfBytesWritten);
+
+ private final native boolean CeCloseHandle(int addr, int hObject);
+
+ private final native boolean CeCopyFile(int addr, String lpExistingFileName,
+ String lpNewFileName, boolean bFailIfExists);
+
+ private final native boolean CeDeleteFile(int addr, String lpFileName);
+
+ private final native boolean CeMoveFile(int addr, String lpExistingFileName,
+ String lpNewFileName);
+
+ private final native boolean CeCreateDirectory(int addr, String lpPathName);
+
+ private final native boolean CeRemoveDirectory(int addr, String lpPathName);
+
+ private final native int CeFindFirstFile(int addr, String lpFileName,
+ RapiFindData lpFindFileData);
+
+ private final native boolean CeFindNextFile(int addr, int hFindFile,
+ RapiFindData lpFindFileData);
+
+ private final native boolean CeFindClose(int addr, int hFindFile);
+
+ private final native boolean CeFindAllFiles(int addr, String szPath,
+ int dwFlags, int[] lpdwFoundCount, int[] ppFindDataArray);
+
+ private final native int CeFindAllFilesEx(int addr, int foundCount,
+ int dataArr, RapiFindData[] findDataArr);
+
+ private final native int CeGetFileAttributes(int addr, String lpFileName);
+
+ private final native int CeGetFileSize(int addr, int hFile, int[] lpFileSizeHigh);
+
+ private final native boolean CeGetFileTime(int addr, int hFile,
+ long[] lpCreationTime, long[] lpLastAccessTime, long[] lpLastWriteTime);
+}
diff --git a/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/IRapiDesktop.java b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/IRapiDesktop.java
new file mode 100644
index 00000000000..b79be90f5a9
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/IRapiDesktop.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.rapi;
+
+import org.eclipse.tm.internal.rapi.RapiDesktop;
+
+/**
+ * This class is used to find connected WinCE-based remote devices.
+ * Use IRapiDesktop.getInstance()
to obtain an instance.
+ *
+ * @author Radoslav Gerganov
+ */
+public abstract class IRapiDesktop extends IUnknown {
+
+ public IRapiDesktop(int addr) {
+ super(addr);
+ }
+
+ /**
+ * Returns new instance of IRapiDesktop
.
+ * Use {@link IRapiDesktop#release()} to release this instance when it is
+ * no longer needed.
+ * @return new instance of IRapiDesktop
+ * @throws RapiException if an error occurs.
+ */
+ public synchronized static IRapiDesktop getInstance() throws RapiException {
+ int[] rapiDesktop = new int[1];
+ int rc = OS.CreateRapiDesktop(rapiDesktop);
+ if (rc != OS.NOERROR) {
+ throw new RapiException("CreateRapiDesktop failed", rc);
+ }
+ return new RapiDesktop(rapiDesktop[0]);
+ }
+
+ /**
+ * Returns an instance of IRapiEnumDevices
.
+ * Use {@link IRapiEnumDevices#release()} to release this instance when it is
+ * no longer needed.
+ * @return an instance of IRapiEnumDevices
+ * @throws RapiException if an error occurs.
+ */
+ public abstract IRapiEnumDevices enumDevices() throws RapiException;
+
+}
diff --git a/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/IRapiDevice.java b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/IRapiDevice.java
new file mode 100644
index 00000000000..4c5d9be0737
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/IRapiDevice.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.rapi;
+
+/**
+ * This class represents a connected WinCE-based remote device.
+ *
+ * @author Radoslav Gerganov
+ */
+public abstract class IRapiDevice extends IUnknown {
+
+ public IRapiDevice(int addr) {
+ super(addr);
+ }
+
+ /**
+ * Returns an instance of IRapiSession
for this remote device.
+ * Use {@link IRapiSession#release()} to release this instance when it is
+ * no longer needed.
+ * @return an instance of IRapiSession
+ * @throws RapiException if an error occurs.
+ */
+ public abstract IRapiSession createSession() throws RapiException;
+
+ /**
+ * Returns information about the connection between this remote device and the desktop.
+ * @return RapiConnectionInfo
object containing information about
+ * the connection between this remote device and the desktop.
+ * @throws RapiException if an error occurs.
+ */
+ public abstract RapiConnectionInfo getConnectionInfo() throws RapiException;
+
+ /**
+ * Returns information about this remote device.
+ * @return RapiDeviceInfo
object containing information about this remote
+ * device.
+ * @throws RapiException if an error occurs.
+ */
+ public abstract RapiDeviceInfo getDeviceInfo() throws RapiException;
+
+ /**
+ * Tests whether this device is connected.
+ * @return true
if this device is connected;false
otherwise.
+ * @throws RapiException if an error occurs.
+ */
+ public abstract boolean isConnected() throws RapiException;
+
+}
\ No newline at end of file
diff --git a/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/IRapiEnumDevices.java b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/IRapiEnumDevices.java
new file mode 100644
index 00000000000..f3a33704a55
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/IRapiEnumDevices.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.rapi;
+
+/**
+ * This class is used to enumerate the set of connected WinCE-based
+ * remote devices which are represented by IRapiDevice
+ * objects.
+ *
+ * @author Radoslav Gerganov
+ */
+public abstract class IRapiEnumDevices extends IUnknown {
+
+ public IRapiEnumDevices(int addr) {
+ super(addr);
+ }
+
+ /**
+ * Returns an instance of IRapiDevice
.
+ * Use {@link IRapiDevice#release()} to release this instance when it is
+ * no longer needed.
+ * @return an instance of IRapiDevice
+ * @throws RapiException if an error occurs.
+ */
+ public abstract IRapiDevice next() throws RapiException;
+
+}
\ No newline at end of file
diff --git a/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/IRapiSession.java b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/IRapiSession.java
new file mode 100644
index 00000000000..ee87c7c13ce
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/IRapiSession.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.rapi;
+
+import java.util.Date;
+
+/**
+ * This class is used to perform Remote API 2 operations on a connected
+ * WinCE-based remote device.
+ *
+ * @author Radoslav Gerganov
+ */
+public abstract class IRapiSession extends IUnknown {
+
+ public IRapiSession(int addr) {
+ super(addr);
+ }
+
+ /**
+ * Initializes (synchronously) the communication layers between the desktop
+ * and the target remote device. This method must be called before calling any
+ * of the other IRapiSession
methods. Use {@link IRapiSession#uninit()}
+ * to uninitialize the session.
+ * @throws RapiException if an error occurs.
+ */
+ public abstract void init() throws RapiException;
+
+ /**
+ * Uninitializes the session. This method should be called last.
+ * @throws RapiException if an error occurs.
+ */
+ public abstract void uninit() throws RapiException;
+
+ /**
+ * Creates, opens, or truncates a file on the remote device.
+ * @param fileName file name on the remote device
+ * @param desiredAccess specifies the type of access to the file
+ * @param shareMode specifies how the file can be shared
+ * @param creationDisposition specifies which action to take on
+ * files that exist, and which action to take when files do not exist
+ * @param flagsAndAttributes specifies the file attributes and flags
+ * for the file
+ * @return integer representing a valid handle that can be used to access the file
+ * @throws RapiException if an error occurs.
+ */
+ public abstract int createFile(String fileName, int desiredAccess,
+ int shareMode, int creationDisposition,
+ int flagsAndAttributes) throws RapiException;
+
+ /**
+ * Reads up to b.length
bytes of data from a remote file
+ * into an array of bytes.
+ * @param handle handle to the file to be read
+ * @param b the buffer into which the data is read
+ * @return the total number of bytes read into the buffer, or
+ * -1
if there is no more data because the end of
+ * the file has been reached
+ * @throws RapiException if an error occurs.
+ */
+ public abstract int readFile(int handle, byte[] b) throws RapiException;
+
+ /**
+ * Reads up to len
bytes of data from a remote file
+ * into an array of bytes.
+ * @param handle handle to the file to be read
+ * @param b 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 file has been reached
+ * @throws RapiException if an error occurs.
+ */
+ public abstract int readFile(int handle, byte[] b, int off, int len)
+ throws RapiException;
+
+ /**
+ * Writes b.length
bytes from the specified byte array
+ * to a remote file.
+ * @param handle handle to the file to which bytes will be written
+ * @param b the data
+ * @throws RapiException if an error occurs.
+ */
+ public abstract void writeFile(int handle, byte[] b) throws RapiException;
+
+ /**
+ * Writes len
bytes from the specified byte array
+ * starting at offset off
to a remote file.
+ * @param handle handle to the file to which bytes will be written
+ * @param b the data
+ * @param off the start offset in the data
+ * @param len the number of bytes to write
+ * @throws RapiException if an error occurs.
+ */
+ public abstract void writeFile(int handle, byte[] b, int off, int len)
+ throws RapiException;
+
+ /**
+ * Closes an open file handle.
+ * @param handle handle to an open file
+ * @throws RapiException if an error occurs.
+ */
+ public abstract void closeHandle(int handle) throws RapiException;
+
+ /**
+ * Copies an existing file on the remote device to a new file on the
+ * remote device.
+ * @param existingFile the file name of the existing file
+ * @param newFile the file name of the new file
+ * @throws RapiException if an error occurs.
+ */
+ public abstract void copyFile(String existingFile, String newFile)
+ throws RapiException;
+
+ /**
+ * Deletes the specified file on the remote device.
+ * @param fileName the file to be deleted
+ * @throws RapiException if an error occurs.
+ */
+ public abstract void deleteFile(String fileName) throws RapiException;
+
+ /**
+ * Renames existing file or directory on the remote device.
+ * @param existingFileName the existing name
+ * @param newFileName the new name
+ * @throws RapiException if an error occurs.
+ */
+ public abstract void moveFile(String existingFileName,
+ String newFileName) throws RapiException;
+
+ /**
+ * Creates a new directory on the remote device.
+ * @param pathName the path of the directory to be created
+ * @throws RapiException if an error occurs.
+ */
+ public abstract void createDirectory(String pathName) throws RapiException;
+
+ /**
+ * Deletes an existing empty directory on the remote device.
+ * @param pathName the path of the directory to be deleted
+ * @throws RapiException if an error occurs.
+ */
+ public abstract void removeDirectory(String pathName) throws RapiException;
+
+ /**
+ * Searches for a file or sub-directory in a directory on the remote device.
+ * Use {@link IRapiSession#findNextFile(int)} to get the next found file.
+ * Finally, call {@link IRapiSession#findClose(int)} to close the returned search handle.
+ * @param fileName string that specifies a valid directory or path and file name.
+ * This string can contain wildcard characters (* and ?)
+ * @param findData [out] this object receives information about the found file
+ * or sub-directory
+ * @return integer representing valid search handle
+ * @throws RapiException if an error occurs.
+ */
+ public abstract int findFirstFile(String fileName,
+ RapiFindData findData) throws RapiException;
+
+ /**
+ * Retrieves the next file in an enumeration context.
+ * @param handle search handle obtained with a call to
+ * {@link IRapiSession#findFirstFile(String, RapiFindData)}
+ * @return RapiFindData
object containing information about the
+ * next file/sub-directory or null
if no matching files can be found
+ */
+ public abstract RapiFindData findNextFile(int handle);
+
+ /**
+ * Closes the specified search handle on the remote device.
+ * @param handle the search handle to close
+ * @throws RapiException if an error occurs.
+ */
+ public abstract void findClose(int handle) throws RapiException;
+
+ /**
+ * Retrieves information about all files and directories in the given directory on
+ * the remote device.
+ * @param path string containing the path in which to search for files
+ * @param flags combination of filter and retrieval flags
+ * @return an array of RapiFindData
objects containing the information
+ * about the found items
+ * @throws RapiException if an error occurs.
+ */
+ public abstract RapiFindData[] findAllFiles(String path,
+ int flags) throws RapiException;
+
+ /**
+ * Returns attributes for the specified file or directory on the remote device.
+ * @param fileName string that specifies the name of a file or directory
+ * @return attributes for the specified file or -1
+ * if an error has occurred
+ */
+ public abstract int getFileAttributes(String fileName);
+
+ /**
+ * Returns the size, in bytes, of the specified file on the remote device.
+ * @param handle open handle of the file whose size is being returned
+ * @return the file size in bytes
+ */
+ public abstract long getFileSize(int handle);
+
+ /**
+ * Returns when the file was created.
+ * @param handle handle to the file for which to get dates and times
+ * @return Date
object representing the date and time when
+ * the file was created
+ * @throws RapiException if an error occurs.
+ */
+ public abstract Date getFileCreationTime(int handle) throws RapiException;
+
+ /**
+ * Returns when the file was last accessed.
+ * @param handle handle to the file for which to get dates and times
+ * @return Date
object representing the date and time when
+ * the file was last accessed
+ * @throws RapiException if an error occurs.
+ */
+ public abstract Date getFileLastAccessTime(int handle) throws RapiException;
+
+ /**
+ * Returns when the file was last written to.
+ * @param handle handle to the file for which to get dates and times
+ * @return Date
object representing the date and time when
+ * the file was last written to
+ * @throws RapiException if an error occurs.
+ */
+ public abstract Date getFileLastWriteTime(int handle) throws RapiException;
+
+}
diff --git a/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/IUnknown.java b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/IUnknown.java
new file mode 100644
index 00000000000..1d5b0163436
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/IUnknown.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.rapi;
+
+/**
+ * Java wrapper for the native IUnknown interface.
+ *
+ * @author Radoslav Gerganov
+ */
+public abstract class IUnknown {
+
+ /**
+ * Pointer to the underlying IUnknown
object.
+ */
+ protected int addr;
+
+ public IUnknown(int addr) {
+ this.addr = addr;
+ }
+
+ /**
+ * Releases the underlying IUnknown
object.
+ */
+ public void release() {
+ OS.ReleaseIUnknown(addr);
+ }
+
+}
diff --git a/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/OS.java b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/OS.java
new file mode 100644
index 00000000000..d0333d44c22
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/OS.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.rapi;
+
+/**
+ * This class provides access to some native Win32 APIs and constants.
+ *
+ * @author Radoslav Gerganov
+ */
+public class OS {
+
+ static {
+ System.loadLibrary("lib/os/win32/x86/jrapi");
+ }
+
+ public static final int NOERROR = 0;
+ //TODO: add more error codes
+
+ public static final int GENERIC_READ = 0x80000000;
+ public static final int GENERIC_WRITE = 0x40000000;
+ public static final int FILE_SHARE_READ = 0x00000001;
+ public static final int FILE_SHARE_WRITE = 0x00000002;
+
+ public static final int CREATE_NEW = 1;
+ public static final int CREATE_ALWAYS = 2;
+ public static final int OPEN_EXISTING = 3;
+ public static final int OPEN_ALWAYS = 4;
+ public static final int TRUNCATE_EXISTING = 5;
+
+ public static final int FILE_ATTRIBUTE_ARCHIVE = 0x00000020;
+ public static final int FILE_ATTRIBUTE_COMPRESSED = 0x00000800;
+ public static final int FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
+ public static final int FILE_ATTRIBUTE_ENCRYPTED = 0x00004000;
+ public static final int FILE_ATTRIBUTE_HIDDEN = 0x00000002;
+ public static final int FILE_ATTRIBUTE_INROM = 0x00000040;
+ public static final int FILE_ATTRIBUTE_NORMAL = 0x00000080;
+ public static final int FILE_ATTRIBUTE_READONLY = 0x00000001;
+ public static final int FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400;
+ public static final int FILE_ATTRIBUTE_ROMMODULE = 0x00002000;
+ public static final int FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200;
+ public static final int FILE_ATTRIBUTE_SYSTEM = 0x00000004;
+ public static final int FILE_ATTRIBUTE_TEMPORARY = 0x00000100;
+
+ public static final int FILE_FLAG_WRITE_THROUGH = 0x80000000;
+ public static final int FILE_FLAG_OVERLAPPED = 0x40000000;
+ public static final int FILE_FLAG_RANDOM_ACCESS = 0x10000000;
+ public static final int FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000;
+
+ public static final int FAF_ATTRIB_CHILDREN = 0x01000;
+ public static final int FAF_ATTRIB_NO_HIDDEN = 0x02000;
+ public static final int FAF_FOLDERS_ONLY = 0x04000;
+ public static final int FAF_NO_HIDDEN_SYS_ROMMODULES = 0x08000;
+ public static final int FAF_GETTARGET = 0x10000;
+
+ public static final int FAF_ATTRIBUTES = 0x01;
+ public static final int FAF_CREATION_TIME = 0x02;
+ public static final int FAF_LASTACCESS_TIME = 0x04;
+ public static final int FAF_LASTWRITE_TIME = 0x08;
+ public static final int FAF_SIZE_HIGH = 0x10;
+ public static final int FAF_SIZE_LOW = 0x20;
+ public static final int FAF_OID = 0x40;
+ public static final int FAF_NAME = 0x80;
+
+ public static final int INVALID_HANDLE_VALUE = -1;
+
+ public static final long TIME_DIFF = 11644473600000L;
+
+ public static final int COINIT_MULTITHREADED = 0x0;
+ public static final int COINIT_APARTMENTTHREADED = 0x2;
+ public static final int COINIT_DISABLE_OLE1DDE = 0x4;
+ public static final int COINIT_SPEED_OVER_MEMORY = 0x8;
+
+ /**
+ * Initializes the COM library.
+ */
+ public static final native int CoInitializeEx(int pvReserved, int dwCoInit);
+
+ /**
+ * Closes the COM library on the current thread.
+ */
+ public static final native void CoUninitialize();
+
+ final static native int CreateRapiDesktop(int[] pIRAPIDesktop);
+ final static native void ReleaseIUnknown(int addr);
+}
diff --git a/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/RapiConnectionInfo.java b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/RapiConnectionInfo.java
new file mode 100644
index 00000000000..e2ecd877678
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/RapiConnectionInfo.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.rapi;
+
+/**
+ * This class contains information that describes the connection between
+ * a WinCE device and a host computer.
+ *
+ * @author Radoslav Gerganov
+ */
+public class RapiConnectionInfo {
+
+ public static final int RAPI_CONNECTION_USB = 0;
+ public static final int RAPI_CONNECTION_IR = 1;
+ public static final int RAPI_CONNECTION_SERIAL = 2;
+ public static final int RAPI_CONNECTION_NETWORK = 3;
+
+ //FIXME
+ //SOCKADDR_STORAGE ipaddr;
+ //SOCKADDR_STORAGE hostIpaddr;
+
+ public int connectionType;
+
+ public String toString() {
+ switch (connectionType) {
+ case RAPI_CONNECTION_USB: return "USB";
+ case RAPI_CONNECTION_IR: return "IR";
+ case RAPI_CONNECTION_SERIAL: return "Serial";
+ case RAPI_CONNECTION_NETWORK: return "Network";
+ }
+ return "Unknown";
+ }
+
+}
diff --git a/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/RapiDeviceInfo.java b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/RapiDeviceInfo.java
new file mode 100644
index 00000000000..c280fde386a
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/RapiDeviceInfo.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.rapi;
+
+/**
+ * This class contains information that identifies a particular WinCE device.
+ *
+ * @author Radoslav Gerganov
+ */
+public class RapiDeviceInfo {
+
+ public String id;
+ public int versionMajor;
+ public int versionMinor;
+ public String name;
+ public String platform;
+}
diff --git a/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/RapiException.java b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/RapiException.java
new file mode 100644
index 00000000000..fadd9b713cb
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/RapiException.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.rapi;
+
+/**
+ * Signals that an error has occurred during execution of RAPI2 call.
+ *
+ * @author Radoslav Gerganov
+ */
+public class RapiException extends Exception {
+
+ private static final long serialVersionUID = -1833456445593343458L;
+
+ private int errorCode;
+
+ public RapiException(String msg) {
+ super(msg);
+ }
+
+ public RapiException(String msg, int errCode) {
+ super(msg + " errorCode: 0x" + Integer.toHexString(errCode));
+ this.errorCode = errCode;
+ }
+
+ /**
+ * Returns the error code associated with this exception.
+ */
+ public int getErrorCode() {
+ return errorCode;
+ }
+}
diff --git a/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/RapiFindData.java b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/RapiFindData.java
new file mode 100644
index 00000000000..390e1968c2f
--- /dev/null
+++ b/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/RapiFindData.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Radoslav Gerganov
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Radoslav Gerganov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.rapi;
+
+import java.util.Date;
+
+/**
+ * This class describes a file found by
CeFindFirstFile
+ * or CeFindAllFiles
+ *
+ * @author Radoslav Gerganov
+ */
+public class RapiFindData {
+ public int fileAttributes;
+ public long creationTime;
+ public long lastAccessTime;
+ public long lastWriteTime;
+ public long fileSize;
+ public int oid;
+ public String fileName;
+
+ public Date getCreationTime() {
+ return new Date((creationTime / 10000) - OS.TIME_DIFF);
+ }
+
+ public Date getLastAccessTime() {
+ return new Date((lastAccessTime / 10000) - OS.TIME_DIFF);
+ }
+
+ public Date getLastWriteTime() {
+ return new Date((lastWriteTime / 10000) - OS.TIME_DIFF);
+ }
+}