diff options
-rw-r--r-- | ChangeLog | 30 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/controlpanel/DebuggingPanel.java | 54 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/resources/Messages.properties | 4 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/util/logging/FileLog.java | 23 | ||||
-rw-r--r-- | plugin/icedteanp/IcedTeaNPPlugin.cc | 92 | ||||
-rw-r--r-- | plugin/icedteanp/IcedTeaNPPlugin.h | 3 | ||||
-rw-r--r-- | plugin/icedteanp/IcedTeaParseProperties.cc | 45 | ||||
-rw-r--r-- | plugin/icedteanp/IcedTeaParseProperties.h | 5 | ||||
-rw-r--r-- | plugin/icedteanp/IcedTeaPluginUtils.cc | 67 | ||||
-rw-r--r-- | plugin/icedteanp/IcedTeaPluginUtils.h | 84 | ||||
-rw-r--r-- | plugin/icedteanp/java/sun/applet/PluginMessageHandlerWorker.java | 2 | ||||
-rw-r--r-- | tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc | 12 |
12 files changed, 353 insertions, 68 deletions
@@ -1,3 +1,33 @@ +2013-11-29 Jiri Vanek <[email protected]> + + Enabled file logging in plugin, user enabled to choose logs dir. + * netx/net/sourceforge/jnlp/controlpanel/DebuggingPanel.java: added + text-field to show/edit logs' destination. Added reset to default button. + * netx/net/sourceforge/jnlp/resources/Messages.propertie: added proper + keys for new controls (CPFilesLogsDestDir) and (CPFilesLogsDestDirResert). + (DPEnableLogging) changed to "Enable debugging", as it is better. + * netx/net/sourceforge/jnlp/util/logging/FileLog.java: Filename of logs + changed to be human readable and to distinguish between c/java + * plugin/icedteanp/IcedTeaNPPlugin.cc: made aware of console (plugin_debug_to_console) + added stream to log into file (plugin_file_log) and holder of name (plugin_file_log_name) + Added various new lines to end of erorr/debug messages. Stream flushed, + not closed on plugin shutdown. + * plugin/icedteanp/IcedTeaNPPlugin.h: extern above three fields. + * plugin/icedteanp/IcedTeaParseProperties.cc: added functionality to provide + set or default log dir (get_log_dir), added (is_java_console_enabled) + to determine logging to console + * plugin/icedteanp/IcedTeaParseProperties.h: used glib.h, declared above functions + * plugin/icedteanp/IcedTeaPluginUtils.cc: added (initFileLog) function to open + correctly named, in proper palce and with correct permissions file for logging + (generateLogFileName) generate human readable file name, as java do. + (printDebugStatus) to debug status of logging + * plugin/icedteanp/IcedTeaPluginUtils.h: headers generated once, and reused + declared above functions. + * plugin/icedteanp/java/sun/applet/PluginMessageHandlerWorker.java: + commented out useless "woken" debug message + * tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc: made plugin_debug_to_console + aware. + 2013-11-27 Andrew Azores <[email protected]> Made JNLPClassLoaderDeadlock reproducer more reliable diff --git a/netx/net/sourceforge/jnlp/controlpanel/DebuggingPanel.java b/netx/net/sourceforge/jnlp/controlpanel/DebuggingPanel.java index bee0a53..68d34d9 100644 --- a/netx/net/sourceforge/jnlp/controlpanel/DebuggingPanel.java +++ b/netx/net/sourceforge/jnlp/controlpanel/DebuggingPanel.java @@ -23,13 +23,20 @@ import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import javax.swing.Box; +import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import net.sourceforge.jnlp.config.Defaults; import net.sourceforge.jnlp.config.DeploymentConfiguration; import net.sourceforge.jnlp.runtime.Translator; import net.sourceforge.jnlp.util.logging.LogConfig; @@ -74,7 +81,41 @@ public class DebuggingPanel extends NamedBorderPanel implements ItemListener { private void addComponents() { GridBagConstraints c = new GridBagConstraints(); - JLabel debuggingDescription = new JLabel("<html>" + Translator.R("CPDebuggingDescription") + "<hr /><br /></html>"); + + final JLabel debuggingDescription = new JLabel("<html>" + Translator.R("CPDebuggingDescription") + "<hr /><br /></html>"); + final JLabel logsDestinationTitle = new JLabel(Translator.R("CPFilesLogsDestDir")+": "); + final JTextField logsDestination = new JTextField(config.getProperty(DeploymentConfiguration.KEY_USER_LOG_DIR)); + logsDestination.getDocument().addDocumentListener(new DocumentListener() { + + + @Override + public void insertUpdate(DocumentEvent e) { + save(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + save(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + save(); + + } + + private void save() { + config.setProperty(DeploymentConfiguration.KEY_USER_LOG_DIR, logsDestination.getText()); + } + }); + final JButton logsDestinationReset = new JButton(Translator.R("CPFilesLogsDestDirResert")); + logsDestinationReset.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + logsDestination.setText(Defaults.getDefaults().get(DeploymentConfiguration.KEY_USER_LOG_DIR).getDefaultValue()); + } + }); JCheckBox[] debuggingOptions = { new JCheckBox(Translator.R("DPEnableLogging")), @@ -130,9 +171,18 @@ public class DebuggingPanel extends NamedBorderPanel implements ItemListener { debuggingOptions[i].addItemListener(this); add(debuggingOptions[i], c); - + if (i == 2) { + c.gridx++; + add(logsDestinationTitle, c); + c.gridx++; + add(logsDestination, c); + c.gridx++; + add(logsDestinationReset, c); + c.gridx-=3; + } } + for (int j = 0; j < javaConsoleItems.length; j++) { consoleComboBox.addItem(javaConsoleItems[j]); if (config.getProperty(DeploymentConfiguration.KEY_CONSOLE_STARTUP_MODE).equals(javaConsoleItems[j].getValue())) { diff --git a/netx/net/sourceforge/jnlp/resources/Messages.properties b/netx/net/sourceforge/jnlp/resources/Messages.properties index 5cea7d2..2e5fb82 100644 --- a/netx/net/sourceforge/jnlp/resources/Messages.properties +++ b/netx/net/sourceforge/jnlp/resources/Messages.properties @@ -402,11 +402,13 @@ APSExceptionInstruction=Separate each entry with a semicolon. # Control Panel - DebugginPanel CPDebuggingPossibilites=Logging outputs -DPEnableLogging=Enable logging +DPEnableLogging=Enable debugging DPEnableLoggingHint=When this switch is on, then also debug messages are logged. Same as -verbose or ICEDTEAPLUGIN_DEBUG=true DPEnableHeaders=Enable headers DPEnableHeadersHint=When this switch is on, each logged message have header with additional information like user, place in code and time DPEnableFile=Enable logging to file +CPFilesLogsDestDir=File logs directory +CPFilesLogsDestDirResert=Reset to default DPEnableFileHint=output messages will be saved to file in your {0} directory DPEnableStds=Enable logging to standard outputs DPEnableStdsHint=messages will be printed to standard outputs diff --git a/netx/net/sourceforge/jnlp/util/logging/FileLog.java b/netx/net/sourceforge/jnlp/util/logging/FileLog.java index 05b079a..3ac048b 100644 --- a/netx/net/sourceforge/jnlp/util/logging/FileLog.java +++ b/netx/net/sourceforge/jnlp/util/logging/FileLog.java @@ -38,6 +38,8 @@ package net.sourceforge.jnlp.util.logging; import java.io.File; import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.logging.FileHandler; import java.util.logging.Formatter; import java.util.logging.Level; @@ -50,17 +52,20 @@ import net.sourceforge.jnlp.util.FileUtils; * */ public final class FileLog implements SingleStreamLogger { + private static SimpleDateFormat fileLogNameFormatter = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss.S"); + /**"Tue Nov 19 09:43:50 CET 2013"*/ + private static SimpleDateFormat pluginSharedFormatter = new SimpleDateFormat("EEE MMM dd HH:mm:ss ZZZ yyyy"); private final Logger impl; private final FileHandler fh; private static final String defaultloggerName = "IcedTea-Web file-logger"; public FileLog() { - this(defaultloggerName, LogConfig.getLogConfig().getIcedteaLogDir() + "itw-" + java.lang.System.currentTimeMillis() + ".log", false); + this(false); } public FileLog(boolean append) { - this(defaultloggerName, LogConfig.getLogConfig().getIcedteaLogDir() + "itw-" + java.lang.System.currentTimeMillis() + ".log", append); + this(defaultloggerName, LogConfig.getLogConfig().getIcedteaLogDir() + "itw-javantx-" + getStamp() + ".log", append); } @@ -104,4 +109,18 @@ public final class FileLog implements SingleStreamLogger { public void close(){ fh.close(); } + + private static String getStamp() { + return fileLogNameFormatter.format(new Date()); + } + + public static SimpleDateFormat getFileLogNameFormatter() { + return fileLogNameFormatter; + } + + public static SimpleDateFormat getPluginSharedFormatter() { + return pluginSharedFormatter; + } + + } diff --git a/plugin/icedteanp/IcedTeaNPPlugin.cc b/plugin/icedteanp/IcedTeaNPPlugin.cc index c7318ef..30ab716 100644 --- a/plugin/icedteanp/IcedTeaNPPlugin.cc +++ b/plugin/icedteanp/IcedTeaNPPlugin.cc @@ -219,6 +219,10 @@ bool plugin_debug_headers = false; bool plugin_debug_to_file = false ; bool plugin_debug_to_streams = true ; bool plugin_debug_to_system = false; +bool plugin_debug_to_console = true; +FILE * plugin_file_log; +std::string plugin_file_log_name; + int plugin_debug_suspend = (getenv("ICEDTEAPLUGIN_DEBUG") != NULL) && (strcmp(getenv("ICEDTEAPLUGIN_DEBUG"), "suspend") == 0); @@ -330,7 +334,7 @@ ITNP_New (NPMIMEType pluginType, NPP instance, uint16_t mode, if (!instance) { - PLUGIN_ERROR ("Browser-provided instance pointer is NULL."); + PLUGIN_ERROR ("Browser-provided instance pointer is NULL.\n"); return NPERR_INVALID_INSTANCE_ERROR; } @@ -338,7 +342,7 @@ ITNP_New (NPMIMEType pluginType, NPP instance, uint16_t mode, ITNPPluginData* data = plugin_data_new (); if (data == NULL) { - PLUGIN_ERROR ("Failed to allocate plugin data."); + PLUGIN_ERROR ("Failed to allocate plugin data.\n"); return NPERR_OUT_OF_MEMORY_ERROR; } @@ -439,7 +443,7 @@ void start_jvm_if_needed() data_directory.c_str(), getpid()); if (!in_pipe_name) { - PLUGIN_ERROR ("Failed to create input pipe name."); + PLUGIN_ERROR ("Failed to create input pipe name.\n"); np_error = NPERR_OUT_OF_MEMORY_ERROR; // If in_pipe_name is NULL then the g_free at // cleanup_in_pipe_name will simply return. @@ -452,7 +456,7 @@ void start_jvm_if_needed() PLUGIN_DEBUG ("ITNP_New: creating input fifo: %s\n", in_pipe_name); if (mkfifo (in_pipe_name, 0600) == -1 && errno != EEXIST) { - PLUGIN_ERROR ("Failed to create input pipe", strerror (errno)); + PLUGIN_ERROR ("Failed to create input pipe\n", strerror (errno)); np_error = NPERR_GENERIC_ERROR; goto cleanup_in_pipe_name; } @@ -467,7 +471,7 @@ void start_jvm_if_needed() if (!out_pipe_name) { - PLUGIN_ERROR ("Failed to create output pipe name."); + PLUGIN_ERROR ("Failed to create output pipe name.\n"); np_error = NPERR_OUT_OF_MEMORY_ERROR; goto cleanup_out_pipe_name; } @@ -478,7 +482,7 @@ void start_jvm_if_needed() PLUGIN_DEBUG ("ITNP_New: creating output fifo: %s\n", out_pipe_name); if (mkfifo (out_pipe_name, 0600) == -1 && errno != EEXIST) { - PLUGIN_ERROR ("Failed to create output pipe", strerror (errno)); + PLUGIN_ERROR ("Failed to create output pipe\n", strerror (errno)); np_error = NPERR_GENERIC_ERROR; goto cleanup_out_pipe_name; } @@ -500,13 +504,13 @@ void start_jvm_if_needed() { if (channel_error) { - PLUGIN_ERROR ("Failed to create output channel", + PLUGIN_ERROR ("Failed to create output channel, '%s'\n", channel_error->message); g_error_free (channel_error); channel_error = NULL; } else - PLUGIN_ERROR ("Failed to create output channel"); + PLUGIN_ERROR ("Failed to create output channel\n"); np_error = NPERR_GENERIC_ERROR; goto cleanup_out_to_appletviewer; @@ -527,13 +531,13 @@ void start_jvm_if_needed() { if (channel_error) { - PLUGIN_ERROR ("Failed to create input channel", + PLUGIN_ERROR ("Failed to create input channel, '%s'\n", channel_error->message); g_error_free (channel_error); channel_error = NULL; } else - PLUGIN_ERROR ("Failed to create input channel"); + PLUGIN_ERROR ("Failed to create input channel\n"); np_error = NPERR_GENERIC_ERROR; goto cleanup_in_from_appletviewer; @@ -549,7 +553,7 @@ void start_jvm_if_needed() goto done; - // Free allocated data + // Free allocated data in case of error cleanup_in_watch_source: // Removing a source is harmless if it fails since it just means the @@ -593,6 +597,7 @@ void start_jvm_if_needed() done: + IcedTeaPluginUtilities::printDebugStatus(); // Now other threads may re-enter.. unlock the mutex g_mutex_unlock(vm_start_mutex); @@ -621,7 +626,7 @@ ITNP_GetValue (NPP instance, NPPVariable variable, void* value) } break; default: - PLUGIN_ERROR ("Unknown plugin value requested."); + PLUGIN_ERROR ("Unknown plugin value requested.\n"); np_error = NPERR_GENERIC_ERROR; break; } @@ -670,7 +675,7 @@ ITNP_SetWindow (NPP instance, NPWindow* window) if (instance == NULL) { - PLUGIN_ERROR ("Invalid instance."); + PLUGIN_ERROR ("Invalid instance.\n"); return NPERR_INVALID_INSTANCE_ERROR; } @@ -990,13 +995,13 @@ plugin_in_pipe_callback (GIOChannel* source, { if (channel_error) { - PLUGIN_ERROR ("Failed to read line from input channel", + PLUGIN_ERROR ("Failed to read line from input channel, %s\n", channel_error->message); g_error_free (channel_error); channel_error = NULL; } else - PLUGIN_ERROR ("Failed to read line from input channel"); + PLUGIN_ERROR ("Failed to read line from input channel\n"); } else { consume_message(message); @@ -1329,13 +1334,13 @@ plugin_test_appletviewer () { if (channel_error) { - PLUGIN_ERROR ("Failed to spawn applet viewer", + PLUGIN_ERROR ("Failed to spawn applet viewer %s\n", channel_error->message); g_error_free (channel_error); channel_error = NULL; } else - PLUGIN_ERROR ("Failed to spawn applet viewer"); + PLUGIN_ERROR ("Failed to spawn applet viewer\n"); error = NPERR_GENERIC_ERROR; } @@ -1409,13 +1414,13 @@ plugin_start_appletviewer (ITNPPluginData* data) { if (channel_error) { - PLUGIN_ERROR ("Failed to spawn applet viewer", + PLUGIN_ERROR ("Failed to spawn applet viewer %s\n", channel_error->message); g_error_free (channel_error); channel_error = NULL; } else - PLUGIN_ERROR ("Failed to spawn applet viewer"); + PLUGIN_ERROR ("Failed to spawn applet viewer\n"); error = NPERR_GENERIC_ERROR; } @@ -1540,13 +1545,13 @@ plugin_send_message_to_appletviewer (gchar const* message) { if (channel_error) { - PLUGIN_ERROR ("Failed to write bytes to output channel", + PLUGIN_ERROR ("Failed to write bytes to output channel '%s' \n", channel_error->message); g_error_free (channel_error); channel_error = NULL; } else - PLUGIN_ERROR ("Failed to write bytes to output channel"); + PLUGIN_ERROR ("Failed to write bytes to output channel for %s", newline_message); } if (g_io_channel_flush (out_to_appletviewer, &channel_error) @@ -1554,18 +1559,18 @@ plugin_send_message_to_appletviewer (gchar const* message) { if (channel_error) { - PLUGIN_ERROR ("Failed to flush bytes to output channel", + PLUGIN_ERROR ("Failed to flush bytes to output channel '%s'\n", channel_error->message); g_error_free (channel_error); channel_error = NULL; } else - PLUGIN_ERROR ("Failed to flush bytes to output channel"); + PLUGIN_ERROR ("Failed to flush bytes to output channel for %s", newline_message); } g_free (newline_message); newline_message = NULL; - PLUGIN_DEBUG (" PIPE: plugin wrote: %s\n", message); + PLUGIN_DEBUG (" PIPE: plugin wrote(?): %s\n", message); } PLUGIN_DEBUG ("plugin_send_message_to_appletviewer return\n"); @@ -1621,13 +1626,13 @@ plugin_stop_appletviewer () { if (channel_error) { - PLUGIN_ERROR ("Failed to write shutdown message to" - " appletviewer", channel_error->message); + PLUGIN_ERROR ("Failed to write shutdown message to " + " appletviewer, %s \n", channel_error->message); g_error_free (channel_error); channel_error = NULL; } else - PLUGIN_ERROR ("Failed to write shutdown message to"); + PLUGIN_ERROR ("Failed to write shutdown message to\n"); } if (g_io_channel_flush (out_to_appletviewer, &channel_error) @@ -1636,12 +1641,12 @@ plugin_stop_appletviewer () if (channel_error) { PLUGIN_ERROR ("Failed to write shutdown message to" - " appletviewer", channel_error->message); + " appletviewer %s \n", channel_error->message); g_error_free (channel_error); channel_error = NULL; } else - PLUGIN_ERROR ("Failed to write shutdown message to"); + PLUGIN_ERROR ("Failed to write shutdown message to\n"); } if (g_io_channel_shutdown (out_to_appletviewer, @@ -1651,12 +1656,12 @@ plugin_stop_appletviewer () if (channel_error) { PLUGIN_ERROR ("Failed to shut down appletviewer" - " output channel", channel_error->message); + " output channel %s \n", channel_error->message); g_error_free (channel_error); channel_error = NULL; } else - PLUGIN_ERROR ("Failed to shut down appletviewer"); + PLUGIN_ERROR ("Failed to shut down appletviewer\n"); } } @@ -1669,12 +1674,12 @@ plugin_stop_appletviewer () if (channel_error) { PLUGIN_ERROR ("Failed to shut down appletviewer" - " input channel", channel_error->message); + " input channel %s \n", channel_error->message); g_error_free (channel_error); channel_error = NULL; } else - PLUGIN_ERROR ("Failed to shut down appletviewer"); + PLUGIN_ERROR ("Failed to shut down appletviewer\n"); } } } @@ -1812,7 +1817,7 @@ initialize_data_directory() file_error = g_mkdir (data_directory.c_str(), 0700); if (file_error != 0) { - PLUGIN_ERROR ("Failed to create data directory", + PLUGIN_ERROR ("Failed to create data directory %s, %s\n", data_directory.c_str(), strerror (errno)); return NPERR_GENERIC_ERROR; @@ -1824,7 +1829,7 @@ initialize_data_directory() if (!g_file_test (data_directory.c_str(), (GFileTest) (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) { - PLUGIN_ERROR ("Temp directory does not exist: ", + PLUGIN_ERROR ("Temp directory does not exist %s, %s \n", data_directory.c_str(), strerror (errno)); return NPERR_GENERIC_ERROR; @@ -1852,7 +1857,7 @@ NP_Initialize (NPNetscapeFuncs* browserTable, NPPluginFuncs* pluginTable) if ((browserTable == NULL) || (pluginTable == NULL)) { - PLUGIN_ERROR ("Browser or plugin function table is NULL."); + PLUGIN_ERROR ("Browser or plugin function table is NULL.\n"); return NPERR_INVALID_FUNCTABLE_ERROR; } @@ -1862,7 +1867,7 @@ NP_Initialize (NPNetscapeFuncs* browserTable, NPPluginFuncs* pluginTable) // we've implemented. if ((browserTable->version >> 8) > NP_VERSION_MAJOR) { - PLUGIN_ERROR ("Incompatible version."); + PLUGIN_ERROR ("Incompatible version.\n"); return NPERR_INCOMPATIBLE_VERSION_ERROR; } @@ -1875,7 +1880,7 @@ NP_Initialize (NPNetscapeFuncs* browserTable, NPPluginFuncs* pluginTable) // Check if everything we rely on is supported if ( !browser_functions_supported ) { - PLUGIN_ERROR ("Invalid browser function table."); + PLUGIN_ERROR ("Invalid browser function table.\n"); return NPERR_INVALID_FUNCTABLE_ERROR; } @@ -1888,7 +1893,7 @@ NP_Initialize (NPNetscapeFuncs* browserTable, NPPluginFuncs* pluginTable) // Check if everything we rely on is supported if ( !plugin_functions_supported ) { - PLUGIN_ERROR ("Invalid plugin function table."); + PLUGIN_ERROR ("Invalid plugin function table.\n"); return NPERR_INVALID_FUNCTABLE_ERROR; } @@ -1954,6 +1959,7 @@ __attribute__ ((visibility ("default"))) const char* NP_GetMIMEDescription () { + //this function is called severaltimes between lunches PLUGIN_DEBUG ("NP_GetMIMEDescription\n"); PLUGIN_DEBUG ("NP_GetMIMEDescription return\n"); @@ -1985,7 +1991,7 @@ NP_GetValue (void* future, NPPVariable variable, void* value) break; default: - PLUGIN_ERROR ("Unknown plugin value requested."); + PLUGIN_ERROR ("Unknown plugin value requested.\n"); result = NPERR_GENERIC_ERROR; break; } @@ -2081,6 +2087,12 @@ NP_Shutdown (void) //delete internal_bus; PLUGIN_DEBUG ("NP_Shutdown return\n"); + + if (plugin_debug_to_file){ + fflush (plugin_file_log); + //fclose (plugin_file_log); + //keep writing untill possible! + } return NPERR_NO_ERROR; } diff --git a/plugin/icedteanp/IcedTeaNPPlugin.h b/plugin/icedteanp/IcedTeaNPPlugin.h index cc1f9f5..6e1465b 100644 --- a/plugin/icedteanp/IcedTeaNPPlugin.h +++ b/plugin/icedteanp/IcedTeaNPPlugin.h @@ -122,6 +122,9 @@ extern bool plugin_debug_headers; extern bool plugin_debug_to_file; extern bool plugin_debug_to_streams; extern bool plugin_debug_to_system; +extern bool plugin_debug_to_console; +extern FILE * plugin_file_log; +extern std::string plugin_file_log_name; // Browser function table. extern NPNetscapeFuncs browser_functions; diff --git a/plugin/icedteanp/IcedTeaParseProperties.cc b/plugin/icedteanp/IcedTeaParseProperties.cc index 4c19a96..2e370ff 100644 --- a/plugin/icedteanp/IcedTeaParseProperties.cc +++ b/plugin/icedteanp/IcedTeaParseProperties.cc @@ -76,6 +76,7 @@ bool read_deploy_property_value(string user_file, string system_file, bool use bool find_custom_jre(string user_file, string main_file,string& dest); //end of non-public IcedTeaParseProperties api const std::string default_file_ITW_deploy_props_name = "deployment.properties"; +const std::string default_itw_log_dir_name = "log"; const std::string custom_jre_key = "deployment.jre.dir"; void remove_all_spaces(string& str) @@ -110,7 +111,7 @@ string user_properties_file(){ string old_name = string(mypasswd->pw_dir)+"/.icedtea/"+default_file_ITW_deploy_props_name; //exists? then itw was not yet migrated. Use it if (IcedTeaPluginUtilities::file_exists(old_name)) { - PLUGIN_ERROR("IcedTea-Web plugin is using out-dated configuration"); + PLUGIN_ERROR("IcedTea-Web plugin is using out-dated configuration\n"); return old_name; } //we are probably on XDG specification now @@ -122,6 +123,37 @@ string user_properties_file(){ return string(mypasswd->pw_dir)+"/.config/icedtea-web/"+default_file_ITW_deploy_props_name; } +string get_log_dir(){ + string value; + if (!read_deploy_property_value("deployment.user.logdir", value)) { + int myuid = getuid(); + struct passwd *mypasswd = getpwuid(myuid); + // try pre 1.5 file location + if (getenv ("XDG_CONFIG_HOME") != NULL){ + string r1= string(getenv ("XDG_CONFIG_HOME"))+"/icedtea-web"; + string r2 = r1+"/"+default_itw_log_dir_name; + if (!IcedTeaPluginUtilities::file_exists(r1)){ + g_mkdir(r1.c_str(), 755); + } + if (!IcedTeaPluginUtilities::file_exists(r2)){ + g_mkdir(r2.c_str(), 755); + } + return r2; + } + //if not then use default + string r1 = string(mypasswd->pw_dir)+"/.config/icedtea-web"; + string r2 = r1+"/"+default_itw_log_dir_name; + if (!IcedTeaPluginUtilities::file_exists(r1)){ + g_mkdir(r1.c_str(), 755); + } + if (!IcedTeaPluginUtilities::file_exists(r2)){ + g_mkdir(r2.c_str(), 755); + } + return r2; + } + return value; +} + string main_properties_file(){ return "/etc/.java/deployment/"+default_file_ITW_deploy_props_name; @@ -149,6 +181,17 @@ bool find_system_config_file(string& dest){ return find_system_config_file(main_properties_file(), jdest, found, default_java_properties_file(), dest); } +bool is_java_console_enabled(){ + string value; + if (!read_deploy_property_value("deployment.console.startup.mode", value)) { + return true; + } + if (value == "DISABLE") { + return false; + } else { + return true; + } +} bool read_bool_property(string key, bool defaultValue){ string value; diff --git a/plugin/icedteanp/IcedTeaParseProperties.h b/plugin/icedteanp/IcedTeaParseProperties.h index 4370e3c..88fd0d1 100644 --- a/plugin/icedteanp/IcedTeaParseProperties.h +++ b/plugin/icedteanp/IcedTeaParseProperties.h @@ -40,10 +40,11 @@ exception statement from your version. */ * Utility classes for parsing values from properties files */ #include <string> - +#include <glib.h> //public api std::string user_properties_file(); +std::string get_log_dir(); bool find_system_config_file(std::string& dest); bool find_custom_jre(std::string& dest); bool read_deploy_property_value(std::string property, std::string& dest); @@ -52,7 +53,9 @@ bool is_debug_header_on(); bool is_logging_to_file(); bool is_logging_to_stds(); bool is_logging_to_system(); +bool is_java_console_enabled(); //half public api extern const std::string default_file_ITW_deploy_props_name; +extern const std::string default_itw_log_dir_name; extern const std::string custom_jre_key; //end of public api diff --git a/plugin/icedteanp/IcedTeaPluginUtils.cc b/plugin/icedteanp/IcedTeaPluginUtils.cc index b8881ac..dd2978f 100644 --- a/plugin/icedteanp/IcedTeaPluginUtils.cc +++ b/plugin/icedteanp/IcedTeaPluginUtils.cc @@ -399,7 +399,7 @@ IcedTeaPluginUtilities::getUTF16LEString(int length, int begin, std::vector<std: wchar_t c; - PLUGIN_DEBUG("Converted UTF-16LE string: "); + PLUGIN_DEBUG("Converted UTF-16LE string: \n"); result_unicode_str->clear(); for (int i = begin; i < begin+length; i+=2) @@ -413,7 +413,7 @@ IcedTeaPluginUtilities::getUTF16LEString(int length, int begin, std::vector<std: (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) { - PLUGIN_DEBUG("%c", c); + PLUGIN_DEBUG("%c\n", c); } result_unicode_str->push_back(c); @@ -1105,6 +1105,69 @@ bool IcedTeaPluginUtilities::file_exists(std::string filename) return infile.good(); } +void IcedTeaPluginUtilities::initFileLog(){ + if (plugin_file_log != NULL ) { + //reusing + return; + } + plugin_file_log_name = get_log_dir() + "/" + IcedTeaPluginUtilities::generateLogFileName(); + int plugin_file_log_fd = open(plugin_file_log_name.c_str(), O_WRONLY | O_CREAT | O_EXCL, 0600); + if (plugin_file_log_fd <=0 ) { + plugin_debug_to_file = false; + } else { + plugin_file_log = fdopen(plugin_file_log_fd, "w"); + } + if (plugin_file_log == NULL ) { + plugin_debug_to_file = false; + } +} + + + +std::string IcedTeaPluginUtilities::generateLogFileName(){ + char times[96]; + char result[100]; + time_t t = time(NULL); + struct tm p; + localtime_r(&t, &p); + struct timeval current_time; \ + gettimeofday (¤t_time, NULL);\ + strftime(times, 96, "%Y-%m-%d_%H:%M:%S", &p); + snprintf(result, 100, "%s.%i",times, current_time.tv_usec/1000); + return "itw-cplugin-"+std::string(result)+".log"; +} + +void IcedTeaPluginUtilities::printDebugStatus(){ + if (plugin_debug){ + PLUGIN_DEBUG("plugin_debug: true, initialised\n"); + if (plugin_debug_headers){ + PLUGIN_DEBUG("plugin_debug_headers: true\n"); + } else { + PLUGIN_DEBUG("plugin_debug_headers: false\n"); + } + if (plugin_debug_to_file){ + PLUGIN_DEBUG("plugin_debug_to_file: true, using %s\n", plugin_file_log_name.c_str()); + } else { + PLUGIN_DEBUG("plugin_debug_to_file: false\n"); + } + if (plugin_debug_to_streams){ + PLUGIN_DEBUG("plugin_debug_to_streams: true\n"); + } else { + PLUGIN_DEBUG("plugin_debug_to_streams: false\n"); + } + if (plugin_debug_to_system){ + PLUGIN_DEBUG("plugin_debug_to_system: true\n"); + } else { + PLUGIN_DEBUG("plugin_debug_to_system: false\n"); + } + if (plugin_debug_to_console){ + PLUGIN_DEBUG("plugin_debug_to_console: true\n"); + } else { + PLUGIN_DEBUG("plugin_debug_to_console: false\n"); + } + } + } + /****************************************** * Begin JavaMessageSender implementation * diff --git a/plugin/icedteanp/IcedTeaPluginUtils.h b/plugin/icedteanp/IcedTeaPluginUtils.h index 95aca25..c62faba 100644 --- a/plugin/icedteanp/IcedTeaPluginUtils.h +++ b/plugin/icedteanp/IcedTeaPluginUtils.h @@ -47,7 +47,9 @@ exception statement from your version. */ #include <stdio.h> #include <stdlib.h> #include <time.h> +#include <sys/time.h> +#include <fcntl.h> #include <cstring> #include <iostream> #include <list> @@ -68,41 +70,69 @@ exception statement from your version. */ do \ { \ if (!debug_initiated) { \ - debug_initiated = true; \ + debug_initiated = true; \ plugin_debug = getenv ("ICEDTEAPLUGIN_DEBUG") != NULL || is_debug_on(); \ plugin_debug_headers = is_debug_header_on(); \ plugin_debug_to_file = is_logging_to_file(); \ plugin_debug_to_streams = is_logging_to_stds(); \ plugin_debug_to_system = is_logging_to_system(); \ + plugin_debug_to_console = is_java_console_enabled(); \ + if (plugin_debug_to_file) { \ + IcedTeaPluginUtilities::initFileLog(); \ + } \ + if (plugin_debug_to_console) { \ + /*no op now*/ \ + } \ + IcedTeaPluginUtilities::printDebugStatus(); \ } \ } while (0) -//f is after expansion used as FILE* -#define CREATE_HEADER(f) \ +#define HEADER_SIZE 500 +#define BODY_SIZE 500 +#define MESSAGE_SIZE HEADER_SIZE + BODY_SIZE + +//header is destination char array +#define CREATE_HEADER(ldebug_header) \ do \ { \ - char s[200]; \ + char times[100]; \ time_t t = time(NULL); \ struct tm p; \ localtime_r(&t, &p); \ - strftime(s, 200, "%a %b %d %H:%M:%S %Z %Y", &p); \ + strftime(times, 100, "%a %b %d %H:%M:%S %Z %Y", &p);\ const char *userNameforDebug = (getenv("USERNAME") == NULL) ? "unknown user" : getenv("USERNAME"); \ - fprintf (f, "[%s][ITW-C-PLUGIN][MESSAGE_DEBUG][%s][%s:%d] ITNPP Thread# %ld, gthread %p: ", \ - userNameforDebug, s, __FILE__, __LINE__, pthread_self(), g_thread_self ()); \ + /*this message is parsed in JavaConsole*/ \ + snprintf(ldebug_header, HEADER_SIZE, "[%s][ITW-C-PLUGIN][MESSAGE_DEBUG][%s][%s:%d] ITNPP Thread# %ld, gthread %p: ", \ + userNameforDebug, times, __FILE__, __LINE__, pthread_self(), g_thread_self ()); \ } while (0) - + #define PLUGIN_DEBUG(...) \ do \ { \ initialize_debug(); \ if (plugin_debug) { \ + char ldebug_header[HEADER_SIZE]; \ + char ldebug_body[BODY_SIZE]; \ + char ldebug_message[MESSAGE_SIZE];\ + if (plugin_debug_headers) { \ + CREATE_HEADER(ldebug_header); \ + } else { \ + sprintf(ldebug_header,""); \ + } \ + snprintf(ldebug_body, BODY_SIZE, __VA_ARGS__); \ if (plugin_debug_to_streams) { \ - if (plugin_debug_headers) { \ - CREATE_HEADER(stdout); \ - } \ - fprintf (stdout, __VA_ARGS__); \ + snprintf(ldebug_message, MESSAGE_SIZE, "%s%s", ldebug_header, ldebug_body); \ + fprintf (stdout, "%s", ldebug_message);\ + } \ + if (plugin_debug_to_file) { \ + snprintf(ldebug_message, MESSAGE_SIZE, "%s%s", ldebug_header, ldebug_body); \ + fprintf (plugin_file_log, "%s", ldebug_message); \ + fflush(plugin_file_log); \ + } \ + if (plugin_debug_to_console) { \ + /*no op now*/ \ } \ } \ } while (0) @@ -112,12 +142,27 @@ exception statement from your version. */ do \ { \ initialize_debug(); \ + char ldebug_header[HEADER_SIZE]; \ + char ldebug_body[BODY_SIZE]; \ + char ldebug_message[MESSAGE_SIZE]; \ + if (plugin_debug_headers) { \ + CREATE_HEADER(ldebug_header); \ + } else { \ + sprintf(ldebug_header,""); \ + } \ + snprintf(ldebug_body, BODY_SIZE, __VA_ARGS__); \ if (plugin_debug_to_streams) { \ - if (plugin_debug_headers) { \ - CREATE_HEADER(stderr); \ - } \ - fprintf (stderr, __VA_ARGS__); \ - } \ + snprintf(ldebug_message, MESSAGE_SIZE, "%s%s", ldebug_header, ldebug_body); \ + fprintf (stderr, "%s", ldebug_message); \ + } \ + if (plugin_debug_to_file) { \ + snprintf(ldebug_message, MESSAGE_SIZE, "%s%s", ldebug_header, ldebug_body); \ + fprintf (plugin_file_log, "%s", ldebug_message); \ + fflush(plugin_file_log); \ + } \ + if (plugin_debug_to_console) { \ + /*no op now*/ \ + } \ } while (0) @@ -338,7 +383,10 @@ class IcedTeaPluginUtilities /*cutting whitespaces from end and start of string*/ static void trim(std::string& str); static bool file_exists(std::string filename); - + //file-loggers helpers + static std::string generateLogFileName(); + static void initFileLog(); + static void printDebugStatus(); }; /* diff --git a/plugin/icedteanp/java/sun/applet/PluginMessageHandlerWorker.java b/plugin/icedteanp/java/sun/applet/PluginMessageHandlerWorker.java index 907a2b2..79d925d 100644 --- a/plugin/icedteanp/java/sun/applet/PluginMessageHandlerWorker.java +++ b/plugin/icedteanp/java/sun/applet/PluginMessageHandlerWorker.java @@ -112,7 +112,7 @@ class PluginMessageHandlerWorker extends Thread { waitForWork(); // Someone woke us up, see if there is work to do - PluginDebug.debug("Consumer thread ", id, " woken..."); + // PluginDebug.debug("Consumer thread ", id, " woken..."); } } } diff --git a/tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc b/tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc index abb0b19..1ac2145 100644 --- a/tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc +++ b/tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc @@ -184,38 +184,50 @@ void doDebugErrorRun() { TEST(PLUGIN_DEBUG_ERROR_PROFILING_debug_on_headers_off) { bool plugin_debug_backup = plugin_debug; bool plugin_debug_headers_backup = plugin_debug_headers; + bool plugin_debug_console_backup = plugin_debug_to_console; + plugin_debug_to_console = false; plugin_debug = true; doDebugErrorRun(); plugin_debug = plugin_debug_backup; plugin_debug_headers = plugin_debug_headers_backup; + plugin_debug_to_console = plugin_debug_console_backup; } TEST(PLUGIN_DEBUG_ERROR_PROFILING_debug_off_headers_off) { bool plugin_debug_backup = plugin_debug; bool plugin_debug_headers_backup = plugin_debug_headers; + bool plugin_debug_console_backup = plugin_debug_to_console; + plugin_debug_to_console = false; plugin_debug = false; doDebugErrorRun(); plugin_debug = plugin_debug_backup; plugin_debug_headers = plugin_debug_headers_backup; + plugin_debug_to_console = plugin_debug_console_backup; } TEST(PLUGIN_DEBUG_ERROR_PROFILING_debug_on_headers_on) { bool plugin_debug_backup = plugin_debug; bool plugin_debug_headers_backup = plugin_debug_headers; + bool plugin_debug_console_backup = plugin_debug_to_console; + plugin_debug_to_console = false; plugin_debug = true; plugin_debug_headers = true; doDebugErrorRun(); plugin_debug = plugin_debug_backup; plugin_debug_headers = plugin_debug_headers_backup; + plugin_debug_to_console = plugin_debug_console_backup; } TEST(PLUGIN_DEBUG_ERROR_PROFILING_debug_off_headers_on) { bool plugin_debug_backup = plugin_debug; bool plugin_debug_headers_backup = plugin_debug_headers; + bool plugin_debug_console_backup = plugin_debug_to_console; + plugin_debug_to_console = false; plugin_debug = false; plugin_debug_headers = true; doDebugErrorRun(); plugin_debug = plugin_debug_backup; plugin_debug_headers = plugin_debug_headers_backup; + plugin_debug_to_console = plugin_debug_console_backup; } |