logging-log4j-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Remko Popma <remko.po...@gmail.com>
Subject Re: Odd problem starting program with log4j2 on Windows
Date Fri, 06 Jul 2018 02:34:04 GMT
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 <garydgregory@gmail.com> wrote:
> 
> Can't URL contain commas?
> 
> Gary
> 
>> On Thu, Jul 5, 2018, 18:11 Ralph Goers <ralph.goers@dslextreme.com> 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 <apache@elyograg.org> 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: log4j-user-unsubscribe@logging.apache.org
>>> For additional commands, e-mail: log4j-user-help@logging.apache.org
>> 
>> 

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-user-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-user-help@logging.apache.org


Mime
View raw message