I’m not sure. The weird behavior can be expected, given that the specified string is neither a correct path, nor a correct URL:
new File(“file:C:\\temp\\some.file”).toURI() It’s simply invalid input. Should log4j attempt to handle this invalid input? (Shameless plug) Every java main() method deserves http://picocli.info > On Jul 6, 2018, at 13:11, Ralph Goers <[email protected]> wrote: > > I suppose we could look for that and fix it, but that would mean having > Windows specific code. > > Ralph > >> On Jul 5, 2018, at 9:10 PM, Ralph Goers <[email protected]> wrote: >> >> So that is some weirdness with Java itself, and only on Windows. >> >> Ralph >> >>> On Jul 5, 2018, at 7:34 PM, Remko Popma <[email protected]> wrote: >>> >>> I found that the problem can be reproduced with this: >>> >>> new File(“file:C:\\temp\\some.file”).toURI() >>> >>> If you print the above it shows: >>> >>> file:/C:/my/current/directory/file:C:/temp/some.file >>> >>> >>> So, the configuration should not prefix the path with “file:”, but with >>> “file:/“ (slash after the colon). >>> >>> >>> (Shameless plug) Every java main() method deserves http://picocli.info >>> >>>> On Jul 6, 2018, at 10:52, Gary Gregory <[email protected]> wrote: >>>> >>>> Can't URL contain commas? >>>> >>>> Gary >>>> >>>>> On Thu, Jul 5, 2018, 18:11 Ralph Goers <[email protected]> wrote: >>>>> >>>>> Here is what Log4j does: >>>>> >>>>> If the property is specified first see if it contains any commas, if so >>>>> then there will be multiple configuration files, which essentially does >>>>> what follows for each file. If not then try to convert it to a URI using >>>>> the following code: >>>>> >>>>> public static URI toURI(final String path) { >>>>> try { >>>>> // Resolves absolute URI >>>>> return new URI(path); >>>>> } catch (final URISyntaxException e) { >>>>> // A file path or a Apache Commons VFS URL might contain blanks. >>>>> // A file path may start with a driver letter >>>>> try { >>>>> final URL url = new URL(path); >>>>> return new URI(url.getProtocol(), url.getHost(), >>>>> url.getPath(), null); >>>>> } catch (MalformedURLException | URISyntaxException nestedEx) { >>>>> return new File(path).toURI(); >>>>> } >>>>> } >>>>> } >>>>> >>>>> The URI is then converted to a ConfigurationSource using: >>>>> public static ConfigurationSource fromUri(final URI configLocation) { >>>>> final File configFile = FileUtils.fileFromUri(configLocation); >>>>> if (configFile != null && configFile.exists() && configFile.canRead()) >>>>> { >>>>> try { >>>>> return new ConfigurationSource(new >>>>> FileInputStream(configFile), configFile); >>>>> } catch (final FileNotFoundException ex) { >>>>> ConfigurationFactory.LOGGER.error("Cannot locate file {}", >>>>> configLocation.getPath(), ex); >>>>> } >>>>> } >>>>> if (ConfigurationFactory.isClassLoaderUri(configLocation)) { >>>>> final ClassLoader loader = >>>>> LoaderUtil.getThreadContextClassLoader(); >>>>> final String path = >>>>> ConfigurationFactory.extractClassLoaderUriPath(configLocation); >>>>> final ConfigurationSource source = fromResource(path, loader); >>>>> if (source != null) { >>>>> return source; >>>>> } >>>>> } >>>>> if (!configLocation.isAbsolute()) { // LOG4J2-704 avoid confusing >>>>> error message thrown by uri.toURL() >>>>> ConfigurationFactory.LOGGER.error("File not found in file system >>>>> or classpath: {}", configLocation.toString()); >>>>> return null; >>>>> } >>>>> try { >>>>> return new >>>>> ConfigurationSource(configLocation.toURL().openStream(), >>>>> configLocation.toURL()); >>>>> } catch (final MalformedURLException ex) { >>>>> ConfigurationFactory.LOGGER.error("Invalid URL {}", >>>>> configLocation.toString(), ex); >>>>> } catch (final Exception ex) { >>>>> ConfigurationFactory.LOGGER.error("Unable to access {}", >>>>> configLocation.toString(), ex); >>>>> } >>>>> return null; >>>>> } >>>>> I should point out that the stack trace log you are seeing is from the >>>>> above code failing. If any of the above doesn’t work we then try to create >>>>> a ConfigurationSource using the following code where config is the value >>>>> of >>>>> the property and loader is the ThreadContextClassLoader. So even with the >>>>> error that is shown it is still possible that the file might be found. >>>>> >>>>> protected ConfigurationSource getInputFromString(final String config, >>>>> final ClassLoader loader) { >>>>> try { >>>>> final URL url = new URL(config); >>>>> return new ConfigurationSource(url.openStream(), >>>>> FileUtils.fileFromUri(url.toURI())); >>>>> } catch (final Exception ex) { >>>>> final ConfigurationSource source = >>>>> ConfigurationSource.fromResource(config, loader); >>>>> if (source == null) { >>>>> try { >>>>> final File file = new File(config); >>>>> return new ConfigurationSource(new FileInputStream(file), >>>>> file); >>>>> } catch (final FileNotFoundException fnfe) { >>>>> // Ignore the exception >>>>> LOGGER.catching(Level.DEBUG, fnfe); >>>>> } >>>>> } >>>>> return source; >>>>> } >>>>> } >>>>> ConfigurationSource.fromResource() tries to locate the resource using >>>>> ClassLoader.getResource() and then constructs a ConfgurationSource if it >>>>> can find it. And if all else fails we just pass the string to the File >>>>> constructor and hope for the best. >>>>> As you can see we aren’t really manipulating the input string that was >>>>> provided to us, but we are trying any way we can to convert it into some >>>>> sort of file we can access. If you see something missing in this logic >>>>> please let us know. >>>>> >>>>> Ralph >>>>> >>>>> >>>>> >>>>> >>>>> >>>>>> On Jul 5, 2018, at 1:59 PM, Shawn Heisey <[email protected]> wrote: >>>>>> >>>>>> On 7/5/2018 11:38 AM, Ralph Goers wrote: >>>>>>> I have updated the issue you referenced. From what I can tell this is >>>>> not an issue in Log4j. It is an issue with the way file urls work. >>>>>> >>>>>> Thanks for your attention. >>>>>> >>>>>> The startup script included with Solr versions before 7.4 (using log4j >>>>>> 1.2.x) also did not have // in the file: URI for the log4j.properties >>>>>> file, and it works on both Linux and Windows. >>>>>> >>>>>> Something else I found in the RFC you linked: >>>>>> >>>>>> The syntax given in Section 2 makes the entire authority component, >>>>>> including the double slashes "//", optional. >>>>>> >>>>>> Reading section 2, I didn't actually see that stated. Maybe it's >>>>>> something clarified by one of the other referenced RFCs. But if we take >>>>>> that statement at face value, it seems to be saying that a URI without >>>>>> // should work. It *does* work on Linux. On Windows, this: >>>>>> >>>>>> file:C:\path\to\stuff\log4j2.xml >>>>>> >>>>>> gets translated into this: >>>>>> >>>>>> file:/$CWD/file:C:/path/to/stuff/log4j2.xml >>>>>> >>>>>> Where $CWD is the current working directory. Even the "extra" URI added >>>>>> as a prefix doesn't have the // in it. If instead we use the following, >>>>>> it works as expected: >>>>>> >>>>>> file://C:\path\to\stuff\log4j2.xml >>>>>> >>>>>> If you're sure that there's nothing in log4j code that would result in >>>>>> the strange location, I'd be willing to accept that this problem is >>>>>> caused by Java or the OS and not log4j. The fact that this doesn't >>>>>> happen on Linux is even more reason to believe that. I don't know how >>>>>> likely it is that log4j contains code that behaves differently based on >>>>>> detected OS ... but I strongly believe that you'd want to avoid that if >>>>>> possible. >>>>>> >>>>>> I believe that we can safely add // to Solr's command script to solve >>>>>> this issue for our users, because the value should always be a full >>>>>> absolute path. >>>>>> >>>>>> But I would like to pursue the remaining question: When the RFC is >>>>>> fully and correctly evaluated, is a "file:" URI without "//" considered >>>>>> valid? If not, then that ends the discussion. If it is considered >>>>>> valid, then there's another question: Is it Java, log4j, or Windows that >>>>>> is causing the problem we've seen? >>>>>> >>>>>> Another question: What is the stance of the project on whether non-URI >>>>>> syntax for the log4j.configurationFile system property will be supported >>>>>> long-term? I can remember running into a problem with logging >>>>>> configuration in the past (I *think* it was log4j 1.x, but it MIGHT have >>>>>> been java.util.logging) where the configuration wasn't found until I >>>>>> added "file:" to turn it into a URI. I did not use // in the URI. This >>>>>> is a line from the init script I wrote for Solr 4.x versions (when Solr >>>>>> did not include a startup script): >>>>>> >>>>>> LOG_OPTS="-Dlog4j.configuration=file:etc/log4j.properties" >>>>>> >>>>>> Thanks, >>>>>> Shawn >>>>>> >>>>>> >>>>>> --------------------------------------------------------------------- >>>>>> To unsubscribe, e-mail: [email protected] >>>>>> For additional commands, e-mail: [email protected] >>>>> >>>>> >>> >>> --------------------------------------------------------------------- >>> To unsubscribe, e-mail: [email protected] >>> For additional commands, e-mail: [email protected] >>> >>> >> > > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [email protected] > For additional commands, e-mail: [email protected] > --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
