javacommons/utils/src.s60/javaoslayer.cpp
branchRCL_3
changeset 14 04becd199f91
child 24 6c158198356e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javacommons/utils/src.s60/javaoslayer.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,688 @@
+/*
+* Copyright (c) 2007-2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+#include <dirent.h>
+#include <memory>
+#include <string.h> // Needed for strcmp
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <sstream>
+#include <e32err.h>
+#include <f32file.h>
+#include <hal.h>
+#include <flogger.h>
+#include "logger.h"
+#include "javaoslayer.h"
+#include "javasymbianoslayer.h"
+#include "libraryloaderexception.h"
+#include "dynamiclibloader.h"
+#include "javacommonutils.h"
+#include "s60commonutils.h"
+
+using namespace java::util;
+
+const char * const BOOT_CLASSPATH_MIDP_FILE = "midpodclist";
+const char * const BOOT_CLASSPATH_INSTALLER_FILE = "installerodclist";
+const char * const BOOT_CLASSPATH_TCKRUNNER_FILE = "tckrunnerodclist";
+
+_LIT(KStartUpTraceDir, "java\\full");
+_LIT(KStartUpTraceFile, "startup.txt");
+_LIT(KTraceSpaceExtra, "                                         ");
+
+OS_EXPORT void JavaOsLayer::startUpTrace(const std::string& header,
+        int freeMem, int totalMem)
+{
+    if (header.length() == 0)
+    {
+        _LIT(KDash, "-");
+        RFileLogger::Write(KStartUpTraceDir, KStartUpTraceFile,
+                           EFileLoggingModeAppend, KDash);
+    }
+    else
+    {
+        TTime time;
+        time.HomeTime();
+        const int maxStrLen = 41;
+        TBuf<maxStrLen>  str;
+        _LIT(KFormatStr, "%-B%:0%J%:1%T%:2%S%.%*C2%:3%+B");
+        TRAP_IGNORE(time.FormatL(str, KFormatStr));
+        int mem = 0;
+        int err = HAL::Get(HALData::EMemoryRAMFree, mem);
+        if (err != KErrNone)
+        {
+            mem = err;
+        }
+        HBufC* buf = stringToDes(header.c_str());
+        const int maxLen = 41;
+        int headerLen = Min(buf->Length(), maxLen);
+        TPtrC headerPtr = buf->Left(headerLen);
+        TPtrC spacePtr = KTraceSpaceExtra().Right(maxLen - headerLen);
+
+        int heapUsageTotal;
+        User::AllocSize(heapUsageTotal);
+
+        _LIT(KOutStr, "%S%S Time(%S), SysMem(%d), pUsedHeap(%d), free(%d), total(%d)");
+        RFileLogger::WriteFormat(KStartUpTraceDir, KStartUpTraceFile,
+                                 EFileLoggingModeAppend,
+                                 KOutStr,
+                                 &headerPtr, &spacePtr, &str, mem, heapUsageTotal, freeMem, totalMem);
+        delete buf;
+    }
+}
+
+
+OS_EXPORT void JavaOsLayer::getOsSpecificLibName(std::string& result,
+        const char* libName)
+{
+//    JELOG2(EUtils);
+    if (libName)
+    {
+        result = libName;
+    }
+    else
+    {
+        ELOG(EUtils, "JavaOsLayer::getOsSpecificLibName() libname was null");
+    }
+}
+
+OS_EXPORT void JavaOsLayer::getOsSpecificJavaRootPath(std::string& path)
+{
+//    JELOG2(EUtils);
+    path = "c:\\java";
+}
+
+OS_EXPORT std::string& JavaOsLayer::getBinRoot(std::string& path, bool append)
+{
+//    JELOG2(EUtils);
+    const char* start = ":\\sys\\bin\\";
+    if (append)
+    {
+        path += start;
+    }
+    else
+    {
+        path = start+1;
+    }
+    return path;
+}
+
+OS_EXPORT std::string& JavaOsLayer::getResRoot(std::string& path, bool append)
+{
+//    JELOG2(EUtils);
+    const char* start = ":\\resource\\java\\";
+    if (append)
+    {
+        path += start;
+    }
+    else
+    {
+        path = start+1;
+    }
+    return path;
+}
+
+OS_EXPORT std::string& JavaOsLayer::getMidpRoot(std::string& path, bool append)
+{
+//    JELOG2(EUtils);
+    const char* start = ":\\private\\102033E6\\";
+//    const char* start = ":\\private\\200211D9\\";
+    if (append)
+    {
+        path += start;
+    }
+    else
+    {
+        path = start+1;
+    }
+    /*
+        TUint32 uid = RProcess().SecureId().iId;
+        std::ostringstream oss;
+        oss<<std::hex<<uid;
+        path += oss.str();
+        path += "]\\";
+    */
+    return path;
+}
+
+OS_EXPORT std::string& JavaOsLayer::getJavaCaptainRoot(std::string& path, bool append)
+{
+//    JELOG2(EUtils);
+    const char* start = ":\\private\\200211DC\\";
+    if (append)
+    {
+        path += start;
+    }
+    else
+    {
+        path = start+1;
+    }
+    return path;
+}
+
+OS_EXPORT DriveId JavaOsLayer::getMidpDrive()
+{
+//    JELOG2(EUtils);
+    int driveNum = 1;
+    TUint16 driveLetter = RProcess().FileName()[0];
+    RFs::CharToDrive(driveLetter, driveNum);
+    char* drive = new char[2];
+    drive[0] = *((char*)&driveLetter);
+    drive[1] = 0;
+    return DriveId(drive, driveNum);
+}
+
+
+OS_EXPORT void* JavaOsLayer::dlopen(const char* libName)
+{
+    JELOG2(EUtils);
+    RLibrary* libAccess = 0;
+    if (libName)
+    {
+        libAccess = new RLibrary();
+        if (libAccess)
+        {
+            HBufC* buf = stringToDes(libName);
+            if (buf)
+            {
+                int status = libAccess->Load(*buf);
+                LOG2(EUtils, EInfo, "JavaOsLayer::dlopen(%s), Handle: %X",
+                     libName, libAccess);
+                delete buf;
+                if (status != KErrNone)
+                {
+                    delete libAccess;
+                    libAccess = 0;
+                    throw LibraryLoaderException(OPENING_LIBRARY_FAILED, status,
+                                                 "Error opening Symbian lib.",
+                                                 __FILE__, __FUNCTION__, __LINE__);
+
+                }
+                else
+                {
+                    //The code below makes RLibrary accessible from any thread.
+                    // copies the handle without doing Open()
+                    RLibrary duplicate=*libAccess;
+                    // overwrite the original
+                    status = libAccess->Duplicate(RThread());
+                    duplicate.Close(); // close the original
+                }
+            }
+        }
+    }
+    else
+    {
+        ELOG(EUtils, "JavaOsLayer::dlopen() libname was null");
+    }
+    return libAccess;
+}
+
+OS_EXPORT void* JavaOsLayer::dlsym(void* handle, const char* name,
+                                   bool containsByteCode)
+{
+    JELOG2(EUtils);
+    void* func = 0;
+    if (handle && name)
+    {
+        RLibrary*  libAccess = reinterpret_cast<RLibrary*>(handle);
+        LookupFunc lookup = (LookupFunc)libAccess->Lookup(containsByteCode?2:1);
+        if (lookup)
+        {
+            func = (void*) lookup(name);
+            LOG2(EUtils, EInfo, "JavaOsLayer::dlsym() fuction name: %s, "
+                 "fPtr: %X", name, func);
+            if (func == 0)
+            {
+                ELOG1(EUtils, "dlsym failed for %s.", name);
+            }
+        }
+        else
+        {
+            ELOG1(EUtils,
+                  "No lookup method in ordinal 1 when looking for %s.", name);
+        }
+    }
+    else
+    {
+        ELOG2(EUtils, "JavaOsLayer::dlsym() null argument handle: %X, name %X",
+              handle, name);
+    }
+    return func;
+}
+
+OS_EXPORT int JavaOsLayer::dlclose(void* handle)
+{
+    JELOG2(EUtils);
+    if (handle)
+    {
+        RLibrary*  libAccess = reinterpret_cast<RLibrary*>(handle);
+        libAccess->Close();
+        delete libAccess;
+    }
+    else
+    {
+        ELOG(EUtils, "dlclose failed, null handle");
+    }
+    return 0;
+}
+OS_EXPORT void JavaOsLayer::bootClassPath(std::list<std::wstring>& odcFiles,
+        std::list<std::wstring>& bcpEntites,
+        const int pathType)
+{
+    /*
+     * getResRoot requires drive letter but VerifiedFileNameL adds correct one.
+     * C drive used that it is checked first and if file is found that is used
+     * after that z is checked.
+     */
+    std::string path = "c";
+    JavaOsLayer::getResRoot(path, true);
+
+    if (BOOT_CLASSPATH_MIDP == pathType)
+    {
+        path.append(BOOT_CLASSPATH_MIDP_FILE);
+    }
+    else if (BOOT_CLASSPATH_INSTALLER == pathType)
+    {
+        path.append(BOOT_CLASSPATH_INSTALLER_FILE);
+    }
+    else if (BOOT_CLASSPATH_TCKRUNNER == pathType)
+    {
+        path.append(BOOT_CLASSPATH_TCKRUNNER_FILE);
+    }
+    else
+    {
+        path.append(BOOT_CLASSPATH_MIDP_FILE);
+    }
+
+    std::auto_ptr<HBufC>pathDes(stringToDes(path.c_str()));
+    TFileName realPathName;
+    TRAPD(err, realPathName = S60CommonUtils::VerifiedFileNameL(*pathDes));
+
+    if (KErrNone == err)
+    {
+        std::wstring temp((wchar_t*)realPathName.PtrZ());
+        std::string odcFileName(temp.begin(), temp.end());
+
+        std::vector<std::string> romClasspathEntries;
+        std::string dir_path("Z:\\resource\\java\\jvm\\lib\\jrt");
+
+        listDirectory(dir_path, romClasspathEntries);  // This is always needed.
+
+        if (odcFileName[0] == 'c' || odcFileName[0] == 'C')  // IAD deployed
+        {
+            std::vector<std::string> updatedClasspathEntries;
+            listOdcFile(path, updatedClasspathEntries);  // Read all ODC files from odc file
+
+            std::string::size_type const delimiter = path.rfind("\\");
+            path = path.substr(0, delimiter);  // IAD ODC file directory
+
+            populateCPEntries((path + "\\jvm\\lib\\jrt\\"), updatedClasspathEntries, odcFiles, bcpEntites);
+
+            std::vector<std::string> romDeltaEntries;
+
+            // Add all ROM entries that are not deployed using IAD.
+            deltaCPEntries(romClasspathEntries, updatedClasspathEntries, romDeltaEntries);
+
+            // Add ROM only entries
+            populateCPEntries((dir_path + "\\"), romDeltaEntries, odcFiles, bcpEntites);
+        }
+        else  // Classpath only at ROM so using dir listing.
+        {
+            populateCPEntries((dir_path + "\\"), romClasspathEntries, odcFiles, bcpEntites);
+        }
+    }
+    else
+    {
+        ELOG1(EUtils, "Cannot get real path name for: '%s'", path.c_str());
+    }
+}
+
+void JavaOsLayer::listDirectory(std::string& aDirPath, std::vector<std::string>& aEntries)
+{
+    DIR *pDIR = opendir(aDirPath.c_str());    // open directory
+
+    if (pDIR == NULL)
+    {
+        std::string errorMsg("Cannot read ROM ODC files: ");
+        errorMsg.append(strerror(errno));
+        errorMsg.append(" : dir: ");
+        errorMsg.append(aDirPath.c_str());
+        ELOG(EUtils, errorMsg.c_str());
+        // Suppres error if no Java at all on device ROM.
+    }
+
+    struct dirent* pDirEnt = readdir(pDIR);
+    while (pDirEnt != NULL)
+    {
+        aEntries.push_back(std::string(pDirEnt->d_name));
+        pDirEnt = readdir(pDIR);
+    }
+
+    closedir(pDIR);    // Release the open directory
+}
+
+void JavaOsLayer::listOdcFile(std::string& filePath, std::vector<std::string>& entries)
+{
+    std::ifstream odcFile;
+    odcFile.open(filePath.c_str(), std::ifstream::in);
+
+    if (odcFile)
+    {
+        std::string line;
+        while (std::getline(odcFile, line))
+        {
+            // Trim enter if exists.
+            std::string::size_type const enter = line.find_last_not_of("\n");
+            entries.push_back(line.substr(0, enter));
+        }
+        odcFile.close();
+    }
+    else
+    {
+        ELOG1(EUtils, "Cannot read file: '%s'", filePath.c_str());
+    }
+}
+
+void JavaOsLayer::populateCPEntries(const std::string& pathPrefix,
+                                    const std::vector<std::string>& entries,
+                                    std::list<std::wstring>& odcFiles,
+                                    std::list<std::wstring>& bcpEntites)
+{
+    std::vector<std::string>::const_iterator iter;
+
+    for (iter = entries.begin(); iter != entries.end(); ++iter)
+    {
+        std::string entryName((*iter));
+        entryName.insert(0, pathPrefix);    // Full path needed.
+
+        std::wstring wideEntryName = L"";
+
+        try
+        {
+            wideEntryName = JavaCommonUtils::utf8ToWstring(entryName.c_str());
+        }
+        catch (ExceptionBase& eb)
+        {
+            // Suppress error to skip invalid ones.
+            ELOG2(EUtils, "utf8->wstring failed on cp entry: '%s' exp: %s ",
+                  entryName.c_str(), eb.toString().c_str());
+        }
+        size_t pos = wideEntryName.rfind(L".odc");
+        bool isOdcFile = (pos != std::string::npos) &&
+                         (pos == (wideEntryName.length() - 4));
+        if (isOdcFile)
+        {
+            odcFiles.push_back(wideEntryName);
+        }
+        else
+        {
+            bcpEntites.push_back(wideEntryName);
+        }
+    }
+}
+
+void JavaOsLayer::deltaCPEntries(const std::vector<std::string>& romEntries,
+                                 const std::vector<std::string>& iadEntries,
+                                 std::vector<std::string>& deltaEntries)
+{
+    std::vector<std::string>::const_iterator iter;  // ROM CP iter
+    std::vector<std::string>::const_iterator matchIter; // IAD CP iter
+    std::vector<std::string> romDeltaEntries;
+
+    // Iterate through all rom entries
+    for (iter = romEntries.begin(); iter != romEntries.end(); ++iter)
+    {
+        bool match = false;
+        // and check if they do not match to IAD ones add to romDeltaEntries.
+        for (matchIter = iadEntries.begin(); matchIter != iadEntries.end(); ++matchIter)
+        {
+            if ((*matchIter) == (*iter))
+            {
+                match = true;
+                break;
+            }
+        }
+
+        if (!match)
+        {
+            deltaEntries.push_back((*iter));
+        }
+    }
+}
+
+OS_EXPORT FuncPtr findMethod(const char* funcName,
+                             const FuncTable funcTable[],
+                             int tableSize)
+{
+//    JELOG2(EUtils);
+    int       res = 0;
+    int       mid = 0;
+    int       top = 0;
+    int       bottom = tableSize-1;
+
+    if (funcName == 0)
+    {
+        ELOG(EUtils, "findMethod failed, null funcName");
+        return 0;
+    }
+    if (funcTable == 0)
+    {
+        ELOG(EUtils, "findMethod failed, null funcTable");
+        return 0;
+    }
+
+    // Loop while the number of the items left in the list is greater
+    // than 2.  Each iteration will split the number of items left to search
+    // in half
+    while ((bottom - top) > 1)
+    {
+        // This case handles the normal serach case where the number of
+        // items left to search is greater than 2
+        mid = (top + bottom) / 2;
+        res = strcmp(funcName, funcTable[mid].mFuncName);
+        if (res == 0)
+        {
+            return((FuncPtr) funcTable[mid].mFuncAddr);
+        }
+        if (res > 0)
+        {
+            top = mid;
+        }
+        else
+        {
+            bottom = mid;
+        }
+    }
+
+    // If there are two items left in the list then the bottom item should be
+    // checked for a match
+    if (bottom != top)
+    {
+        // Check the bottom item to see if it is a match
+        res=strcmp(funcName, funcTable[bottom].mFuncName);
+        if (res == 0)
+        {
+            return ((FuncPtr) funcTable[bottom].mFuncAddr);
+        }
+    }
+
+    // Check the top item to see if it is a match
+    res=strcmp(funcName, funcTable[top].mFuncName);
+
+    if (res == 0)
+    {
+        return ((FuncPtr) funcTable[top].mFuncAddr);
+    }
+
+    // Neither the top or bottom items were a match so the
+    // method must not exist in the file
+    return 0;
+}
+
+OS_EXPORT HBufC* stringToDes(const char* str)
+{
+//    JELOG2(EUtils);
+    HBufC* resultBuf = 0;
+    try
+    {
+        if (str)
+        {
+            int len = strlen(str);
+            resultBuf = HBufC::New(len + 1);
+            TPtr ptr = resultBuf->Des();
+            TPtr8 ptr8((TUint8 *)str, len);
+            ptr8.SetLength(len);
+            ptr.Copy(ptr8);
+            ptr.ZeroTerminate();
+        }
+    }
+    catch (...)
+    {
+        ELOG(EUtils, "stringToDes, exception");
+    }
+    return resultBuf;
+}
+
+OS_EXPORT wchar_t* desToWstring(TPtr16& aDes)
+{
+    return (wchar_t*) aDes.PtrZ();
+}
+
+OS_EXPORT TAppVersion wstringToAppVersion(const std::wstring& aVersionString)
+{
+    TAppVersion appVersion;
+    char* temp = JavaCommonUtils::wstringToUtf8(aVersionString);
+    std::string versionStr = temp;
+
+    std::string::size_type idx = 0;
+    idx = versionStr.find(".", idx);
+
+    // 00.00.00 --> 00 00.00
+    if (idx != std::string::npos)
+    {
+        versionStr.replace(idx, 1, " ");
+    }
+
+    idx = versionStr.find(".", idx + 1);
+
+    // 00 00.00 --> 00 00 00
+    if (idx != std::string::npos)
+    {
+        versionStr.replace(idx, 1, " ");
+    }
+
+    int major = 0;
+    int minor = 0;
+    int build = 0;
+    int result = sscanf(
+                     versionStr.c_str(), "%d %d %d", &major, &minor, &build);
+
+    if (major > 0)
+    {
+        appVersion.iMajor = major;
+    }
+
+    if (minor > 0)
+    {
+        appVersion.iMinor = minor;
+    }
+
+    if (build > 0)
+    {
+        appVersion.iBuild = build;
+    }
+    delete[] temp;
+
+    return appVersion;
+}
+
+OS_EXPORT HBufC* wstringToBuf(const std::wstring& aString)
+{
+    HBufC* stringBuf = HBufC::New(aString.size());
+    if (stringBuf != 0)
+    {
+        TPtr16 namePtr(stringBuf->Des());
+        namePtr.Append((const TUint16*)aString.c_str(), aString.size());
+    }
+    return stringBuf;
+}
+
+/**
+ *
+ */
+OS_EXPORT java::util::Uid& TUidToUid(const TUid& aId,java::util::Uid& aOutUid)
+{
+//  JELOG2(EUtils);
+    if (0 == aId.iUid)
+        return aOutUid;
+
+    std::wstringstream stream;
+    stream.fill('0');
+    stream << std::setw(8) << std::hex << (int)aId.iUid; // codescanner::leave
+
+    std::wstring idAsStr;
+    idAsStr.reserve(11);
+    idAsStr.append(L"[");
+    idAsStr.append(stream.str());
+    idAsStr.append(L"]");
+    Uid tmpUid(idAsStr);
+    aOutUid = tmpUid;
+    return aOutUid;
+}
+
+/**
+ *
+ */
+OS_EXPORT TInt uidToTUid(const java::util::Uid& aUid,TUid& aOutId)
+{
+//  JELOG2(EUtils);
+    long long tmpInt = 0;
+    std::wstring uidAsStr = aUid.toString();
+    if (0 == uidAsStr.size())
+        return KErrArgument;
+
+    JavaCommonUtils::trimWstring(uidAsStr,L'\n');
+    JavaCommonUtils::trimWstring(uidAsStr,L'\t');
+    JavaCommonUtils::trimWstring(uidAsStr,L' ');
+
+    if ((10 != uidAsStr.size()) && (8 != uidAsStr.size()))
+        return KErrArgument;
+
+    if (('[' == uidAsStr.at(0)) && (']' == uidAsStr.at(uidAsStr.size()-1)))
+    {
+        if (10 != uidAsStr.size())
+            return KErrArgument;
+        std::wstring plainNumStr = uidAsStr.substr(1,uidAsStr.size()-2);
+        std::wstringstream stream(plainNumStr);
+        stream >> std::hex >> tmpInt; // codescanner::leave
+        if ((false == stream.eof()) || (stream.fail()))
+            return KErrArgument;
+    }
+    else
+    {
+        std::wstringstream stream(uidAsStr);
+        stream >> std::hex >> tmpInt; // codescanner::leave
+        if ((false == stream.eof()) || (stream.fail()))
+            return KErrArgument;
+    }
+
+    if ((tmpInt > 0xEFFFFFFF) || (tmpInt < 0))
+        return KErrArgument;
+    aOutId.iUid = tmpInt;
+    return KErrNone;
+}
+