/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package java.util.logging; import java.io.PrintWriter; import java.io.StringWriter; /*-[ // TODO(tball): update ASL use to iOS 10's os_log and remove clang pragmas. #pragma clang diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #import "NSException+JavaThrowable.h" #import <asl.h> // Simple value holder, so aslclient is closed when thread dictionary is deallocated. @interface ASLClientHolder : NSObject { @public aslclient _client; } @end @implementation ASLClientHolder - (instancetype)initWithClient:(aslclient)client { self = [super init]; if (self) { _client = client; } return self; } - (void)dealloc { asl_close(_client); #if !__has_feature(objc_arc) [super dealloc]; #endif } @end ]-*/ /** * Handler implementation that calls iOS asl_log(). * * @author Tom Ball */ class IOSLogHandler extends Handler { static class IOSLogFormatter extends Formatter { /** * Very simple formatter, since asl_log adds its own text. */ @Override public String format(LogRecord record) { return formatMessage(record); } } static final String IOS_LOG_MANAGER_DEFAULTS = ".level=INFO\nhandlers=java.util.logging.IOSLogHandler\n"; private static final String ASLCLIENT = "IOSLogHandler-aslclient"; public IOSLogHandler() { setFormatter(new IOSLogFormatter()); } @Override public void close() { // No action needed } @Override public void flush() { // No action needed } @Override public void publish(LogRecord record) { if (!isLoggable(record)) { return; } StringBuilder sb = new StringBuilder(getFormatter().format(record)); int aslLevel; switch (record.getLevel().intValue()) { case 1000: // Level.SEVERE aslLevel = 3; // ASL_LEVEL_ERR break; case 900: // Level.WARNING aslLevel = 4; // ASL_LEVEL_WARNING break; case 800: // Level.INFO case 700: // Level.CONFIG aslLevel = 5; // ASL_LEVEL_NOTICE break; default: aslLevel = 6; // ASL_LEVEL_INFO } if (record.getThrown() != null) { sb.append('\n'); StringWriter stringWriter = new StringWriter(); record.getThrown().printStackTrace(new PrintWriter(stringWriter)); sb.append(stringWriter.toString()); } log(sb.toString(), aslLevel); } private native void log(String logMessage, int aslLevel) /*-[ // Add stderr as a log file, so that log messages are seen on the debug log, // and not just the device log. static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ asl_add_log_file(NULL, STDERR_FILENO); }); NSThread *currentThread = [NSThread currentThread]; NSMutableDictionary *threadData = [currentThread threadDictionary]; ASLClientHolder *logClient = [threadData objectForKey:JavaUtilLoggingIOSLogHandler_ASLCLIENT]; if (!logClient) { aslclient aslClient = asl_open([[currentThread name] UTF8String], [[[NSBundle mainBundle] bundleIdentifier] UTF8String], ASL_OPT_NO_DELAY | ASL_OPT_STDERR); logClient = AUTORELEASE([[ASLClientHolder alloc] initWithClient:aslClient]); [threadData setObject:logClient forKey:JavaUtilLoggingIOSLogHandler_ASLCLIENT]; } asl_log(logClient->_client, NULL, aslLevel, "%s", [logMessage UTF8String]); ]-*/; /*-[ #pragma clang diagnostic pop ]-*/ }