So that is some weirdness with Java itself, and only on Windows.

Ralph

> On Jul 5, 2018, at 7:34 PM, Remko Popma <remko.po...@gmail.com> 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 <garydgreg...@gmail.com> wrote:
>> 
>> Can't URL contain commas?
>> 
>> Gary
>> 
>>> On Thu, Jul 5, 2018, 18:11 Ralph Goers <ralph.go...@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 <apa...@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-unsubscr...@logging.apache.org
>>>> For additional commands, e-mail: log4j-user-h...@logging.apache.org
>>> 
>>> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: log4j-user-unsubscr...@logging.apache.org
> For additional commands, e-mail: log4j-user-h...@logging.apache.org
> 
> 



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

Reply via email to