javaAssertions.cpp revision 0:a61af66fc99e
133965Sjdp/* 278828Sobrien * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. 391041Sobrien * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 438889Sjdp * 533965Sjdp * This code is free software; you can redistribute it and/or modify it 633965Sjdp * under the terms of the GNU General Public License version 2 only, as 733965Sjdp * published by the Free Software Foundation. 833965Sjdp * 933965Sjdp * This code is distributed in the hope that it will be useful, but WITHOUT 1033965Sjdp * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1133965Sjdp * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1233965Sjdp * version 2 for more details (a copy is included in the LICENSE file that 1333965Sjdp * accompanied this code). 1433965Sjdp * 1533965Sjdp * You should have received a copy of the GNU General Public License version 1689857Sobrien * 2 along with this work; if not, write to the Free Software Foundation, 1789857Sobrien * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1889857Sobrien * 1933965Sjdp * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 2033965Sjdp * CA 95054 USA or visit www.sun.com if you need additional information or 2133965Sjdp * have any questions. 2233965Sjdp * 2360484Sobrien */ 2433965Sjdp 2589857Sobrien#include "incls/_precompiled.incl" 2689857Sobrien#include "incls/_javaAssertions.cpp.incl" 2789857Sobrien 2889857Sobrienbool JavaAssertions::_userDefault = false; 2989857Sobrienbool JavaAssertions::_sysDefault = false; 3089857SobrienJavaAssertions::OptionList* JavaAssertions::_classes = 0; 3189857SobrienJavaAssertions::OptionList* JavaAssertions::_packages = 0; 3291041Sobrien 3389857SobrienJavaAssertions::OptionList::OptionList(const char* name, bool enabled, 3489857Sobrien OptionList* next) { 3591041Sobrien assert(name != 0, "need a name"); 3689857Sobrien _name = name; 3789857Sobrien _enabled = enabled; 3889857Sobrien _next = next; 3989857Sobrien} 4089857Sobrien 4189857Sobrienint JavaAssertions::OptionList::count(OptionList* p) { 4289857Sobrien int rc; 4389857Sobrien for (rc = 0; p != 0; p = p->next(), ++rc) /* empty */; 4489857Sobrien return rc; 45104834Sobrien} 4689857Sobrien 4789857Sobrienvoid JavaAssertions::addOption(const char* name, bool enable) { 4889857Sobrien assert(name != 0, "must have a name"); 4989857Sobrien 5089857Sobrien // Copy the name. The storage needs to exist for the the lifetime of the vm; 5189857Sobrien // it is never freed, so will be leaked (along with other option strings - 5289857Sobrien // e.g., bootclasspath) if a process creates/destroys multiple VMs. 5389857Sobrien int len = (int)strlen(name); 5489857Sobrien char *name_copy = NEW_C_HEAP_ARRAY(char, len + 1); 5589857Sobrien strcpy(name_copy, name); 5689857Sobrien 5789857Sobrien // Figure out which list the new item should go on. Names that end in "..." 5889857Sobrien // go on the package tree list. 5989857Sobrien OptionList** head = &_classes; 6089857Sobrien if (len >= 3 && strcmp(name_copy + len - 3, "...") == 0) { 6189857Sobrien // Delete the "...". 6289857Sobrien len -= 3; 6333965Sjdp name_copy[len] = '\0'; 6433965Sjdp head = &_packages; 6533965Sjdp } 6633965Sjdp 6738889Sjdp // Convert class/package names to internal format. Will have to convert back 6838889Sjdp // when copying to java in createJavaAssertionStatusDirectives, but that 6938889Sjdp // should happen only once. Alternative would require that 7033965Sjdp // JVM_DesiredAssertionStatus pass the external_name() to 7133965Sjdp // JavaAssertion::enabled(), but that is done once per loaded class. 7233965Sjdp for (int i = 0; i < len; ++i) { 7333965Sjdp if (name_copy[i] == '.') name_copy[i] = '/'; 7433965Sjdp } 7533965Sjdp 7633965Sjdp if (TraceJavaAssertions) { 7733965Sjdp tty->print_cr("JavaAssertions: adding %s %s=%d", 7833965Sjdp head == &_classes ? "class" : "package", 7933965Sjdp name_copy[0] != '\0' ? name_copy : "'default'", 8033965Sjdp enable); 8133965Sjdp } 8233965Sjdp 8333965Sjdp // Prepend a new item to the list. Items added later take precedence, so 8433965Sjdp // prepending allows us to stop searching the list after the first match. 8533965Sjdp *head = new OptionList(name_copy, enable, *head); 8633965Sjdp} 8733965Sjdp 8833965Sjdpoop JavaAssertions::createAssertionStatusDirectives(TRAPS) { 8933965Sjdp symbolHandle asd_sym = vmSymbolHandles::java_lang_AssertionStatusDirectives(); 9033965Sjdp klassOop k = SystemDictionary::resolve_or_fail(asd_sym, true, CHECK_NULL); 9133965Sjdp instanceKlassHandle asd_klass (THREAD, k); 9233965Sjdp asd_klass->initialize(CHECK_NULL); 9333965Sjdp Handle h = asd_klass->allocate_instance_handle(CHECK_NULL); 9433965Sjdp 9533965Sjdp int len; 9633965Sjdp typeArrayOop t; 9733965Sjdp len = OptionList::count(_packages); 9833965Sjdp objArrayOop pn = oopFactory::new_objArray(SystemDictionary::string_klass(), len, CHECK_NULL); 9933965Sjdp objArrayHandle pkgNames (THREAD, pn); 10033965Sjdp t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL); 10133965Sjdp typeArrayHandle pkgEnabled(THREAD, t); 10233965Sjdp fillJavaArrays(_packages, len, pkgNames, pkgEnabled, CHECK_NULL); 10333965Sjdp 10433965Sjdp len = OptionList::count(_classes); 10533965Sjdp objArrayOop cn = oopFactory::new_objArray(SystemDictionary::string_klass(), len, CHECK_NULL); 10633965Sjdp objArrayHandle classNames (THREAD, cn); 10733965Sjdp t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL); 10833965Sjdp typeArrayHandle classEnabled(THREAD, t); 10933965Sjdp fillJavaArrays(_classes, len, classNames, classEnabled, CHECK_NULL); 11033965Sjdp 11133965Sjdp java_lang_AssertionStatusDirectives::set_packages(h(), pkgNames()); 11233965Sjdp java_lang_AssertionStatusDirectives::set_packageEnabled(h(), pkgEnabled()); 11333965Sjdp java_lang_AssertionStatusDirectives::set_classes(h(), classNames()); 11433965Sjdp java_lang_AssertionStatusDirectives::set_classEnabled(h(), classEnabled()); 11533965Sjdp java_lang_AssertionStatusDirectives::set_deflt(h(), userClassDefault()); 11633965Sjdp return h(); 11733965Sjdp} 11833965Sjdp 11933965Sjdpvoid JavaAssertions::fillJavaArrays(const OptionList* p, int len, 12033965SjdpobjArrayHandle names, typeArrayHandle enabled, TRAPS) { 12133965Sjdp // Fill in the parallel names and enabled (boolean) arrays. Start at the end 12291041Sobrien // of the array and work backwards, so the order of items in the arrays 12333965Sjdp // matches the order on the command line (the list is in reverse order, since 12433965Sjdp // it was created by prepending successive items from the command line). 12533965Sjdp int index; 12633965Sjdp for (index = len - 1; p != 0; p = p->next(), --index) { 12733965Sjdp assert(index >= 0, "length does not match list"); 12833965Sjdp Handle s = java_lang_String::create_from_str(p->name(), CHECK); 12933965Sjdp s = java_lang_String::char_converter(s, '/', '.', CHECK); 13033965Sjdp names->obj_at_put(index, s()); 13133965Sjdp enabled->bool_at_put(index, p->enabled()); 13233965Sjdp } 13389857Sobrien assert(index == -1, "length does not match list"); 13491041Sobrien} 13533965Sjdp 13689857Sobrieninline JavaAssertions::OptionList* 13789857SobrienJavaAssertions::match_class(const char* classname) { 13889857Sobrien for (OptionList* p = _classes; p != 0; p = p->next()) { 13989857Sobrien if (strcmp(p->name(), classname) == 0) { 14089857Sobrien return p; 14189857Sobrien } 14233965Sjdp } 14389857Sobrien return 0; 14489857Sobrien} 14533965Sjdp 14633965SjdpJavaAssertions::OptionList* 14733965SjdpJavaAssertions::match_package(const char* classname) { 14833965Sjdp // Search the package list for any items that apply to classname. Each 14933965Sjdp // sub-package in classname is checked, from most-specific to least, until one 15033965Sjdp // is found. 15133965Sjdp if (_packages == 0) return 0; 15233965Sjdp 15333965Sjdp // Find the length of the "most-specific" package in classname. If classname 15433965Sjdp // does not include a package, length will be 0 which will match items for the 15533965Sjdp // default package (from options "-ea:..." or "-da:..."). 15633965Sjdp size_t len = strlen(classname); 15733965Sjdp for (/* empty */; len > 0 && classname[len] != '/'; --len) /* empty */; 15833965Sjdp 15933965Sjdp do { 16033965Sjdp assert(len == 0 || classname[len] == '/', "not a package name"); 16160484Sobrien for (OptionList* p = _packages; p != 0; p = p->next()) { 16233965Sjdp if (strncmp(p->name(), classname, len) == 0 && p->name()[len] == '\0') { 16333965Sjdp return p; 16433965Sjdp } 16533965Sjdp } 16689857Sobrien 16733965Sjdp // Find the length of the next package, taking care to avoid decrementing 16833965Sjdp // past 0 (len is unsigned). 16933965Sjdp while (len > 0 && classname[--len] != '/') /* empty */; 17033965Sjdp } while (len > 0); 17133965Sjdp 17233965Sjdp return 0; 17333965Sjdp} 17433965Sjdp 17533965Sjdpinline void JavaAssertions::trace(const char* name, 17633965Sjdpconst char* typefound, const char* namefound, bool enabled) { 17733965Sjdp if (TraceJavaAssertions) { 17833965Sjdp tty->print_cr("JavaAssertions: search for %s found %s %s=%d", 17933965Sjdp name, typefound, namefound[0] != '\0' ? namefound : "'default'", enabled); 18033965Sjdp } 18133965Sjdp} 18233965Sjdp 18333965Sjdpbool JavaAssertions::enabled(const char* classname, bool systemClass) { 18433965Sjdp assert(classname != 0, "must have a classname"); 18533965Sjdp 18633965Sjdp // This will be slow if the number of assertion options on the command line is 18791041Sobrien // large--it traverses two lists, one of them multiple times. Could use a 18833965Sjdp // single n-ary tree instead of lists if someone ever notices. 18977298Sobrien 19077298Sobrien // First check options that apply to classes. If we find a match we're done. 19177298Sobrien OptionList* p; 19277298Sobrien if (p = match_class(classname)) { 19377298Sobrien trace(classname, "class", p->name(), p->enabled()); 19477298Sobrien return p->enabled(); 19533965Sjdp } 19633965Sjdp 19733965Sjdp // Now check packages, from most specific to least. 19892828Sobrien if (p = match_package(classname)) { 19933965Sjdp trace(classname, "package", p->name(), p->enabled()); 20033965Sjdp return p->enabled(); 20133965Sjdp } 20289857Sobrien 20360484Sobrien // No match. Return the default status. 20433965Sjdp bool result = systemClass ? systemClassDefault() : userClassDefault(); 20589857Sobrien trace(classname, systemClass ? "system" : "user", "default", result); 20633965Sjdp return result; 20733965Sjdp} 20877298Sobrien