### Eclipse Workspace Patch 1.0 #P org.eclipse.tm.rapi Index: native/org_eclipse_tm_internal_rapi_RapiSession.h =================================================================== RCS file: /cvsroot/dsdp/org.eclipse.tm.core/wince/org.eclipse.tm.rapi/native/org_eclipse_tm_internal_rapi_RapiSession.h,v retrieving revision 1.2 diff -u -r1.2 org_eclipse_tm_internal_rapi_RapiSession.h --- native/org_eclipse_tm_internal_rapi_RapiSession.h 3 Apr 2008 15:58:54 -0000 1.2 +++ native/org_eclipse_tm_internal_rapi_RapiSession.h 7 Apr 2008 20:15:03 -0000 @@ -1,3 +1,13 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ /* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class org_eclipse_tm_internal_rapi_RapiSession */ @@ -177,6 +187,22 @@ /* * Class: org_eclipse_tm_internal_rapi_RapiSession + * Method: CeSetFileAttributes + * Signature: (ILjava/lang/String;I)Z + */ +JNIEXPORT jboolean JNICALL Java_org_eclipse_tm_internal_rapi_RapiSession_CeSetFileAttributes + (JNIEnv *, jobject, jint, jstring, jint); + +/* + * Class: org_eclipse_tm_internal_rapi_RapiSession + * Method: CeSetFileTime + * Signature: (II[J[J[J)Z + */ +JNIEXPORT jboolean JNICALL Java_org_eclipse_tm_internal_rapi_RapiSession_CeSetFileTime + (JNIEnv *, jobject, jint, jint, jlongArray, jlongArray, jlongArray); + +/* + * Class: org_eclipse_tm_internal_rapi_RapiSession * Method: CeCreateProcess * Signature: (ILjava/lang/String;Ljava/lang/String;ILorg/eclipse/tm/rapi/ProcessInformation;)Z */ Index: native/RapiSession.cpp =================================================================== RCS file: /cvsroot/dsdp/org.eclipse.tm.core/wince/org.eclipse.tm.rapi/native/RapiSession.cpp,v retrieving revision 1.2 diff -u -r1.2 RapiSession.cpp --- native/RapiSession.cpp 3 Apr 2008 15:58:54 -0000 1.2 +++ native/RapiSession.cpp 7 Apr 2008 20:15:02 -0000 @@ -258,6 +258,14 @@ return res; } +LPFILETIME jlong2FILETIME(jlong jl, LPFILETIME ft) +{ + ft->dwLowDateTime = (DWORD)jl; + jl >>= 32; + ft->dwHighDateTime = (DWORD)jl; + return ft; +} + void setFIND_DATAFields(JNIEnv *env, jobject lpObject, CE_FIND_DATA *pFindData) { if (!FIND_DATAFc.cached) cacheFIND_DATAFields(env, lpObject); @@ -437,6 +445,58 @@ return rc; } +JNIEXPORT jboolean JNICALL RAPI_NATIVE(CeSetFileAttributes) + (JNIEnv *env, jobject that, jint arg0, jstring arg1, jint arg2) +{ + jboolean rc = 0; + const jchar *lparg1 = NULL; + + if (arg0 == 0) return rc; + if (arg1) { + lparg1 = env->GetStringChars(arg1, NULL); + if (lparg1 == NULL) goto fail; + } + IRAPISession *pSession = (IRAPISession*) arg0; + rc = pSession->CeSetFileAttributes((LPCWSTR)lparg1, arg2); +fail: + if (arg1 && lparg1) env->ReleaseStringChars(arg1, lparg1); + return rc; +} + +JNIEXPORT jboolean JNICALL RAPI_NATIVE(CeSetFileTime) + (JNIEnv *env, jobject that, jint arg0, jint arg1, jlongArray arg2, jlongArray arg3, jlongArray arg4) +{ + jboolean rc = 0; + FILETIME crTime, laTime, lwTime; + LPFILETIME pcrTime = NULL, plaTime = NULL, plwTime = NULL; + jlong *lparg2 = NULL, *lparg3 = NULL, *lparg4 = NULL; + + if (arg0 == 0) return 0; + if (arg2) { + lparg2 = env->GetLongArrayElements(arg2, NULL); + if (lparg2 == NULL) goto fail; + pcrTime = jlong2FILETIME(lparg2[0], &crTime); + } + if (arg3) { + lparg3 = env->GetLongArrayElements(arg3, NULL); + if (lparg3 == NULL) goto fail; + plaTime = jlong2FILETIME(lparg3[0], &laTime); + } + if (arg4) { + lparg4 = env->GetLongArrayElements(arg4, NULL); + if (lparg4 == NULL) goto fail; + plwTime = jlong2FILETIME(lparg4[0], &lwTime); + } + + IRAPISession *pSession = (IRAPISession*) arg0; + rc = pSession->CeSetFileTime((HANDLE)arg1, pcrTime, plaTime, plwTime); +fail: + if (arg2 && lparg2) env->ReleaseLongArrayElements(arg2, lparg2, 0); + if (arg3 && lparg3) env->ReleaseLongArrayElements(arg3, lparg3, 0); + if (arg4 && lparg4) env->ReleaseLongArrayElements(arg4, lparg4, 0); + return rc; +} + struct PROCESS_INFORMATION_FID_CACHE { int cached; Index: src/org/eclipse/tm/rapi/IRapiSession.java =================================================================== RCS file: /cvsroot/dsdp/org.eclipse.tm.core/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/rapi/IRapiSession.java,v retrieving revision 1.2 diff -u -r1.2 IRapiSession.java --- src/org/eclipse/tm/rapi/IRapiSession.java 3 Apr 2008 15:58:54 -0000 1.2 +++ src/org/eclipse/tm/rapi/IRapiSession.java 7 Apr 2008 20:15:05 -0000 @@ -10,8 +10,6 @@ *******************************************************************************/ 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. @@ -208,33 +206,67 @@ 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 + * Returns the time when the file was created. + *

+ * The time is represented as the number of Universal Time (UT) + * milliseconds since the epoch (00:00:00 GMT, January 1, 1970). + *

+ * @param handle handle to the file for which to get creation time + * @return the creation time for this file * @throws RapiException if an error occurs. */ - public abstract Date getFileCreationTime(int handle) throws RapiException; + public abstract long 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 + * Returns the time when the file was last accessed. + *

+ * The time is represented as the number of Universal Time (UT) + * milliseconds since the epoch (00:00:00 GMT, January 1, 1970). + *

+ * @param handle handle to the file for which to get last access time + * @return the last access time for this file * @throws RapiException if an error occurs. */ - public abstract Date getFileLastAccessTime(int handle) throws RapiException; + public abstract long 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 + * Returns the time when the file was last written to. + *

+ * The time is represented as the number of Universal Time (UT) + * milliseconds since the epoch (00:00:00 GMT, January 1, 1970). + *

+ * @param handle handle to the file for which to get last write time + * @return the last write time for this file * @throws RapiException if an error occurs. */ - public abstract Date getFileLastWriteTime(int handle) throws RapiException; + public abstract long getFileLastWriteTime(int handle) throws RapiException; /** + * Sets the attributes of the specified file on the remote device. + * @param fileName the target file + * @param fileAttributes the new attributes; this parameter is combination of the + * following values: {@link OS#FILE_ATTRIBUTE_ARCHIVE}, {@link OS#FILE_ATTRIBUTE_HIDDEN}, + * {@link OS#FILE_ATTRIBUTE_NORMAL}, {@link OS#FILE_ATTRIBUTE_READONLY}, + * {@link OS#FILE_ATTRIBUTE_SYSTEM}, {@link OS#FILE_ATTRIBUTE_TEMPORARY} + * @throws RapiException if an error occurs. + */ + public abstract void setFileAttributes(String fileName, int fileAttributes) throws RapiException; + + /** + * Sets the last write time of the specified file. + *

+ * The time is represented as the number of Universal Time (UT) + * milliseconds since the epoch (00:00:00 GMT, January 1, 1970). + *

+ * The specified time will be truncated to fit the supported precision. + * @param handle handle to the target file + * @param lastWriteTime the new last write time for this file + * @throws IllegalArgumentException if the specified time is negative + * @throws RapiException if an error occurs. + */ + public abstract void setFileLastWriteTime(int handle, long lastWriteTime) throws RapiException; + + /** * Creates new process on the remote device. * @param appName module to execute * @param commandLine command line arguments Index: src/org/eclipse/tm/internal/rapi/RapiSession.java =================================================================== RCS file: /cvsroot/dsdp/org.eclipse.tm.core/wince/org.eclipse.tm.rapi/src/org/eclipse/tm/internal/rapi/RapiSession.java,v retrieving revision 1.3 diff -u -r1.3 RapiSession.java --- src/org/eclipse/tm/internal/rapi/RapiSession.java 3 Apr 2008 15:58:54 -0000 1.3 +++ src/org/eclipse/tm/internal/rapi/RapiSession.java 7 Apr 2008 20:15:04 -0000 @@ -10,8 +10,6 @@ *******************************************************************************/ 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.ProcessInformation; @@ -219,7 +217,7 @@ return ( ((long)sizeHigh[0] << 32) | (sizeLow & 0xFFFFFFFF)); } - public Date getFileCreationTime(int handle) throws RapiException { + public long getFileCreationTime(int handle) throws RapiException { long[] crTime = new long[1]; long[] laTime = new long[1]; long[] lwTime = new long[1]; @@ -227,10 +225,10 @@ if (!res) { throw new RapiException("CeGetFileTime failed", getError()); //$NON-NLS-1$ } - return new Date((crTime[0] / 10000) - OS.TIME_DIFF); + return (crTime[0] / 10000) - OS.TIME_DIFF; } - public Date getFileLastAccessTime(int handle) throws RapiException { + public long getFileLastAccessTime(int handle) throws RapiException { long[] crTime = new long[1]; long[] laTime = new long[1]; long[] lwTime = new long[1]; @@ -238,10 +236,10 @@ if (!res) { throw new RapiException("CeGetFileTime failed", getError()); //$NON-NLS-1$ } - return new Date((laTime[0] / 10000) - OS.TIME_DIFF); + return (laTime[0] / 10000) - OS.TIME_DIFF; } - public Date getFileLastWriteTime(int handle) throws RapiException { + public long getFileLastWriteTime(int handle) throws RapiException { long[] crTime = new long[1]; long[] laTime = new long[1]; long[] lwTime = new long[1]; @@ -249,7 +247,25 @@ if (!res) { throw new RapiException("CeGetFileTime failed", getError()); //$NON-NLS-1$ } - return new Date((lwTime[0] / 10000) - OS.TIME_DIFF); + return (lwTime[0] / 10000) - OS.TIME_DIFF; + } + + public void setFileAttributes(String fileName, int fileAttributes) throws RapiException { + boolean res = CeSetFileAttributes(addr, fileName, fileAttributes); + if (!res) { + throw new RapiException("CeSetFileAttributes failed", getError()); //$NON-NLS-1$ + } + } + + public void setFileLastWriteTime(int handle, long lastWriteTime) throws RapiException { + if (lastWriteTime < 0) { + throw new IllegalArgumentException("Time cannot be negative"); //$NON-NLS-1$ + } + long[] lwTime = new long[] {(lastWriteTime + OS.TIME_DIFF) * 10000}; + boolean res = CeSetFileTime(addr, handle, null, null, lwTime); + if (!res) { + throw new RapiException("CeSetFileTime failed", getError()); //$NON-NLS-1$ + } } public ProcessInformation createProcess(String appName, String commandLine, int creationFlags) throws RapiException { @@ -317,6 +333,11 @@ private final native boolean CeGetFileTime(int addr, int hFile, long[] lpCreationTime, long[] lpLastAccessTime, long[] lpLastWriteTime); + private final native boolean CeSetFileAttributes(int addr, String lpFileName, int dwFileAttributes); + + private final native boolean CeSetFileTime(int addr, int hFile, long[] lpCreationTime, + long[] lpLastAccessTime, long[] lpLastWriteTime); + private final native boolean CeCreateProcess(int addr, String lpApplicationName, String lpCommandLine, int dwCreationFlags, ProcessInformation lpProcessInformation); } #P org.eclipse.tm.rapi.tests Index: src/org/eclipse/tm/rapi/tests/RapiSessionTest.java =================================================================== RCS file: /cvsroot/dsdp/org.eclipse.tm.core/wince/org.eclipse.tm.rapi.tests/src/org/eclipse/tm/rapi/tests/RapiSessionTest.java,v retrieving revision 1.2 diff -u -r1.2 RapiSessionTest.java --- src/org/eclipse/tm/rapi/tests/RapiSessionTest.java 31 Mar 2008 12:34:08 -0000 1.2 +++ src/org/eclipse/tm/rapi/tests/RapiSessionTest.java 7 Apr 2008 20:15:18 -0000 @@ -141,9 +141,19 @@ // ignore } session.createDirectory(TEST_DIR_NAME); - assertTrue("Failed to create directory", isDirectory(TEST_DIR_NAME)); + assertTrue("Failed to create directory: " + TEST_DIR_NAME, isDirectory(TEST_DIR_NAME)); session.removeDirectory(TEST_DIR_NAME); - assertFalse("Failed to remove directory", isDirectory(TEST_DIR_NAME)); + assertFalse("Failed to remove directory: " + TEST_DIR_NAME, isDirectory(TEST_DIR_NAME)); + } + + /** + * Utility method for creating files. + */ + void createFile(IRapiSession session, String fileName) throws RapiException { + int handle = session.createFile(fileName, OS.GENERIC_WRITE, + OS.FILE_SHARE_READ, OS.CREATE_ALWAYS, OS.FILE_ATTRIBUTE_NORMAL); + session.writeFile(handle, "spam".getBytes()); + session.closeHandle(handle); } /** @@ -153,24 +163,23 @@ 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); + createFile(session, TEST_FILE_NAME); // make a copy String copy = TEST_FILE_NAME + "1"; session.copyFile(TEST_FILE_NAME, copy); - assertTrue("Failed to copy file", isFile(copy)); + assertTrue("The copied file doesn't exist: " + copy, isFile(copy)); // delete the test file session.deleteFile(TEST_FILE_NAME); - assertFalse("Failed to delete file", isFile(TEST_FILE_NAME)); + assertFalse("Failed to delete file: " + TEST_FILE_NAME, 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)); + assertTrue("Failed to move file, existing file: " + copy + " new file: " + TEST_FILE_NAME, + isFile(TEST_FILE_NAME)); + assertFalse("Failed to move file, existing file: " + copy + " new file: " + TEST_FILE_NAME, + isFile(copy)); // delete test file session.deleteFile(TEST_FILE_NAME); @@ -181,10 +190,7 @@ */ 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); + createFile(session, TEST_FILE_NAME + i); } } @@ -227,19 +233,66 @@ } /** - * Tests getting file attributes, size, etc. + * Tests getting and setting file attributes + */ + public void testGetSetFileAttributes() throws RapiException { + createInitSession(); + // create test file + createFile(session, TEST_FILE_NAME); + + session.setFileAttributes(TEST_FILE_NAME, OS.FILE_ATTRIBUTE_READONLY); + int attr = session.getFileAttributes(TEST_FILE_NAME); + assertTrue("Wrong file attributes, expected FILE_ATTRIBUTE_READONLY", + (attr & OS.FILE_ATTRIBUTE_READONLY) != 0); + + session.setFileAttributes(TEST_FILE_NAME, OS.FILE_ATTRIBUTE_ARCHIVE); + attr = session.getFileAttributes(TEST_FILE_NAME); + assertTrue("Wrong file attributes, expected FILE_ATTRIBUTE_ARCHIVE", + (attr & OS.FILE_ATTRIBUTE_ARCHIVE) != 0); + + //clean up + session.deleteFile(TEST_FILE_NAME); + } + + /** + * Tests getting file size using {@link IRapiSession#getFileSize(int)} */ - public void testStatFiles() throws RapiException { + public void testGetFileSize() throws RapiException { createInitSession(); // create test file - int handle = session.createFile(TEST_FILE_NAME, OS.GENERIC_WRITE, + 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) + assertTrue("Wrong file size, expected size 4 bytes", 4 == session.getFileSize(handle)); 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); + } + + /** + * Tests getting and setting file times + */ + public void testGetSetFileTime() throws RapiException { + createInitSession(); + + // now + 1h + long d = System.currentTimeMillis() + 3600000; + + // create file and set last access time to d + 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.setFileLastWriteTime(handle, d); + session.closeHandle(handle); + // get file last write time and compare to d + handle = session.createFile(TEST_FILE_NAME, OS.GENERIC_READ, + OS.FILE_SHARE_READ, OS.OPEN_EXISTING, OS.FILE_ATTRIBUTE_NORMAL); + long lwTime = session.getFileLastWriteTime(handle); + // the precision of setLastWriteTime should be about 1-2sec + assertTrue("Too big difference for lastWriteTime, expected: " + d + + " returned: " + lwTime, Math.abs(lwTime - d) <= 5000); + session.closeHandle(handle); + //clean up session.deleteFile(TEST_FILE_NAME); }