// -*- c++ -*- /* * Jakelib2 - General purpose C++ library * Copyright (C) 2001 Florian Wolff (florian@donuz.de) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: System.jlc,v 1.33 2006-01-07 09:54:43 florian Exp $ */ #include "jakelib2.h" #include "jakelib2/lang/System.h" #include "jakelib2/io/PrintWriter.h" #include "jakelib2/io/File.h" #include "jakelib2/io/StandardOutputStream.h" #include "jakelib2/util/Properties.h" #include #include #include using namespace jakelib::lang; using namespace jakelib::io; using namespace jakelib::util; JAKELIB_IMPLEMENT_CLASS("jakelib.lang.System", System, Object) #ifdef HAVE_SYS_TIME_H # include #endif #ifdef HAVE_TIME_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_SYS_UTSNAME_H # include #endif #ifdef HAVE_PWD_H # include #endif #ifdef JAKELIB_WIN32API # include # include #endif String* System::eol = null; PrintWriter *System::out = null; PrintWriter *System::err = null; File *System::file = null; Properties *System::properties = null; Properties *System::defaultProperties = null; /*****************************************************************************\ * getEnv | *****************************************************************************/ String* System::getEnv(const char* name) { char* value = getenv(name); if (value == null) return null; else return new String(value); } String* System::getEnv(String* name) { return getEnv(JAKELIB_LATIN1(name)); } /*****************************************************************************\ * explainErrorCode | *****************************************************************************/ String* System::explainErrorCode(jint code) { switch (code) { #if defined(JAKELIB_WIN32API) case ERROR_FILE_NOT_FOUND: return `"File not found"`; case ERROR_PATH_NOT_FOUND: return `"Path not found"`; case ERROR_BROKEN_PIPE: return `"Broken pipe"`; case ERROR_INVALID_HANDLE: return `"Invalid handle"`; case WSAECONNREFUSED: return `"Connection refused"`; default: return `"Error code #"` .. code; #else default: return new String(strerror(code)); #endif } } /*****************************************************************************\ * currentTimeMillis | *****************************************************************************/ jlong System::currentTimeMillis() { #if defined(JAKELIB_WIN32API) SYSTEMTIME st; FILETIME ft; GetSystemTime(&st); SystemTimeToFileTime(&st, &ft); // Microsoft's millis start in the year 1601. // 11644473600000L = ((1970 - 1601) * 365 + 89) * 24 * 60 * 60 * 1000 return ((jlong)ft.dwLowDateTime | ((jlong)ft.dwHighDateTime << 32)) / LL(10000) - LL(11644473600000); #else struct timeval tv; struct timezone tz; gettimeofday(&tv, &tz); return ((jlong) tv.tv_sec) * 1000LL + tv.tv_usec / 1000LL; #endif } /*****************************************************************************\ * randomize | *****************************************************************************/ void System::randomize() { #ifdef WIN32 srand((unsigned int) currentTimeMillis()); #else srand(currentTimeMillis() + getpid()); #endif } /*****************************************************************************\ * random | *****************************************************************************/ int System::random(int max) { #ifdef BORLAND return ::random(max); #else return rand() % max; #endif } /*****************************************************************************\ * initSystem | *****************************************************************************/ void System::initSystemClass(int argc, char* argv[]) { out = new PrintWriter(new StandardOutputStream(stdout), true); err = new PrintWriter(new StandardOutputStream(stderr), true); #ifdef WIN32 eol = new String("\r\n"); #else eol = new String("\n"); #endif if (argv != null) { file = new File(argv[0]); } else { file = new File(""); } // Initialize System Properties: defaultProperties = new Properties(); properties = defaultProperties; properties->setProperty(`"file.separator"`, File::separator); properties->setProperty(`"path.separator"`, File::pathSeparator); properties->setProperty(`"line.separator"`, eol); properties->setProperty(`"os.version"`, `"unknown"`); properties->setProperty(`"os.name"`, `"unknown"`); properties->setProperty(`"os.arch"`, `"unknown"`); #if defined(POSIX) char cwd[JAKELIB_MAX_PATH]; if (getcwd(cwd, JAKELIB_MAX_PATH) != null) properties->setProperty(`"user.dir"`, `""` .. cwd); struct passwd *pw = getpwuid(getuid()); if (pw != null) properties->setProperty(`"user.home"`, `""` .. pw->pw_dir); properties->setProperty(`"user.name"`, `""` .. cuserid(null)); struct utsname un; if (uname(&un) >= 0) { properties->setProperty(`"os.version"`, `""` .. un.release); properties->setProperty(`"os.name"`, `""` .. un.sysname); properties->setProperty(`"os.arch"`, `""` .. un.machine); } String *tmpDir = getEnv(`"TMP"`); if (tmpDir != null) properties->setProperty(`"tmp.dir"`, tmpDir); else properties->setProperty(`"tmp.dir"`, `"/tmp"`); #elif defined(JAKELIB_WIN32API) char tmpbuf[MAX_PATH]; DWORD size; if (GetCurrentDirectory(JAKELIB_MAX_PATH, tmpbuf) != 0) properties->setProperty(`"user.dir"`, `""` .. tmpbuf); size = JAKELIB_MAX_PATH; if (SHGetSpecialFolderPath(NULL, tmpbuf, CSIDL_PERSONAL, false)) properties->setProperty(`"user.home"`, File(`""` .. tmpbuf .. `"\\.."`).getCanonicalPath()); DWORD bufLen = JAKELIB_MAX_PATH /2; if (GetUserName(tmpbuf, &bufLen)) properties->setProperty(`"user.name"`, `""` .. tmpbuf); OSVERSIONINFOEX osvi; osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (GetVersionEx((OSVERSIONINFO *) &osvi)) { switch(osvi.dwPlatformId) { case VER_PLATFORM_WIN32_NT: if (osvi.dwMajorVersion <= 4) properties->setProperty(`"os.name"`, `"Microsoft Windows NT"`); else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) properties->setProperty(`"os.name"`, `"Microsoft Windows 2000"`); else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 ) properties->setProperty(`"os.name"`, `"Microsoft Windows XP"`); break; case VER_PLATFORM_WIN32_WINDOWS: if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) properties->setProperty(`"os.name"`, `"Microsoft Windows 95"`); else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) properties->setProperty(`"os.name"`, `"Microsoft Windows 98"`); else if (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) properties->setProperty(`"os.name"`, `"Microsoft Windows Me"`); break; case VER_PLATFORM_WIN32s: properties->setProperty(`"os.name"`, `"Microsoft Win32s"`); break; } properties->setProperty(`"os.version"`, `""` .. (jlong)osvi.dwMajorVersion .. `"."` .. (jlong)osvi.dwMinorVersion); } properties->setProperty(`"os.arch"`, `"i386"`); if (GetTempPath(JAKELIB_MAX_PATH, tmpbuf) != 0) properties->setProperty(`"tmp.dir"`, `""` .. tmpbuf); #else #endif } /*****************************************************************************\ * getProperty | *****************************************************************************/ String* System::getProperty(String *key, String *def) { return properties->getProperty(key, def); } /*****************************************************************************\ * setProperties | *****************************************************************************/ void System::setProperties(Properties *props) { if (props != null) { properties = props; } else { properties = defaultProperties; } } /*****************************************************************************\ * getProperties | *****************************************************************************/ Properties* System::getProperties() { return properties; } /*****************************************************************************\ * arraycopy | *****************************************************************************/ //FIXME: check for compatible types void System::arraycopy(Array* src, jint srcStart, Array* dest, jint destStart, jint len) { if ((src == null) || (dest == null)) throw new NullPointerException(); /*should never happen, but just in case ...*/ /* Can never happen since Array has no Class object. */ if (src->getClass()->getName()->equals(`"jakelib::lang::Array"`) || dest->getClass()->getName()->equals(`"jakelib::lang::Array"`)) throw new IllegalArgumentException(`"It is illegal to use Array class."` .. JAKELIB_AT2(`"jakelib.lang.System.arraycopy"`)); Array& srcArr = *src; Array& destArr = *dest; if ((srcStart + len) > (srcArr.length())) throw new ArrayIndexOutOfBoundsException(`"Source array out of bounds: "` .. (srcStart + len) .. `" > "` .. (srcArr.length() - 1) .. JAKELIB_AT2(`"jakelib.lang.System.arraycopy"`)); else { if ((destStart + len) > (destArr.length())) throw new ArrayIndexOutOfBoundsException(`"Destination array out of bounds: "` .. (destStart + len) .. `" > "` .. (destArr.length() - 1) .. JAKELIB_AT2(`"jakelib.lang.System.arraycopy"`)); else if (len < 0) throw new ArrayIndexOutOfBoundsException(`"Negative length :"` .. len .. `" < 0 "` .. JAKELIB_AT2(`"jakelib.lang.System.arraycopy"`)); } if (srcArr.getClass()->getName() != destArr.getClass()->getName()) throw new IllegalArgumentException(`"Attempt to copy arrays of incompatible types."` .. JAKELIB_AT2(`"jakelib.lang.System.arraycopy"`)); // florian: Won't work! // "ANSI C++ forbids using pointer of type `void *' in arithmetic" // jint elemSize = src->sizeOfElement(); // memmove(dest->getRawData() + destStart * elemSize, // src->getRawData() + srcStart * elemSize, // elemSize * len); // jint idxSrc = srcStart; // jint idxDest = destStart; // for (; idxSrc < (srcStart + len); idxSrc++, idxDest++) { // if (src == dest && //copying inside the same array // ((idxSrc == destStart) || (idxDest == srcStart)))//and overlapping, give it up now // break; // destArr.set(idxDest, srcArr.get(idxSrc)); // } return; }