[502065] Enhance user file localization for FileUserManager
* UserManager gets the users in a file on server. Previously, the
file path could be absolute or relative to the application.
* Now the file path can also be relative to the config folder
(where cdo-server.xml is) by specifying "@config/...".
* File validity checks are removed to support file creation during
addUser().
* With -Dnet4j.security.FileUserManager.fallBackToConfigFolder=true
a relative path is resolved in both the application's current folder
and the config folder (in this order).
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=502065
Change-Id: I63b559c93cb67ccfc656018fe0136511e7434c03
Signed-off-by: Laurent Fasani <laurent.fasani@obeo.fr>
Signed-off-by: Eike Stepper <stepper@esc-net.de>
diff --git a/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml b/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml
index 4ee0904..4f9f109 100644
--- a/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml
+++ b/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml
@@ -31,7 +31,7 @@
-->
<!-- Example http://bugs.eclipse.org/302775
- <authenticator type="file" description="_database/repo1.users"/>
+ <authenticator type="file" description="@config/repo1.users"/>
-->
<!-- Example http://bugs.eclipse.org/345431
diff --git a/plugins/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml b/plugins/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml
index 4ee0904..4f9f109 100644
--- a/plugins/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml
+++ b/plugins/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml
@@ -31,7 +31,7 @@
-->
<!-- Example http://bugs.eclipse.org/302775
- <authenticator type="file" description="_database/repo1.users"/>
+ <authenticator type="file" description="@config/repo1.users"/>
-->
<!-- Example http://bugs.eclipse.org/345431
diff --git a/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml b/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml
index 02168ad..28ff34c 100644
--- a/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml
+++ b/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml
@@ -31,7 +31,7 @@
-->
<!-- Example http://bugs.eclipse.org/302775
- <authenticator type="file" description="_database/repo1.users"/>
+ <authenticator type="file" description="@config/repo1.users"/>
-->
<!-- Example http://bugs.eclipse.org/345431
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/FileAuthenticatorFactory.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/FileAuthenticatorFactory.java
index 86dc181..3dbfe68 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/FileAuthenticatorFactory.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/FileAuthenticatorFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012 Eike Stepper (Berlin, Germany) and others.
+ * Copyright (c) 2012-2016 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/FileUserManager.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/FileUserManager.java
index a57c627..d082c89 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/FileUserManager.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/FileUserManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008-2012 Eike Stepper (Berlin, Germany) and others.
+ * Copyright (c) 2008-2012, 2016 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,12 +10,13 @@
*/
package org.eclipse.net4j.util.security;
+import org.eclipse.net4j.util.StringUtil;
import org.eclipse.net4j.util.io.IORuntimeException;
import org.eclipse.net4j.util.io.IOUtil;
+import org.eclipse.net4j.util.om.OMPlatform;
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -29,8 +30,14 @@
*/
public class FileUserManager extends UserManager
{
+ private static final boolean FALL_BACK_TO_CONFIG_FOLDER = OMPlatform.INSTANCE.isProperty("net4j.security.FileUserManager.fallBackToConfigFolder");
+
+ private static final String CONFIG_FOLDER_PREFIX = "@config/";
+
protected String fileName;
+ private File file;
+
public FileUserManager()
{
}
@@ -40,55 +47,102 @@
return fileName;
}
+ /**
+ * Sets the name of the file to be used by this user manager.
+ * <p>
+ * The {@link #getFile() file} is resolved in the following order:
+ * <ol>
+ * <li> If it starts with the path segment "@config" the subsequent path segments are interpreted as relative to the {@link OMPlatform#getConfigFolder() config folder}.
+ * <li> If it is relative it is interpreted as relative to the application's current directory.
+ * <li> Otherwise it is interpreted as absolute.
+ * </ol>
+ * The resolved file is not required to exist when this user manager is activated. In this case it will be created when {@link #addUser(String, char[]) addUser()}
+ * or {@link #removeUser(String) removeUser()} are called.
+ * <p>
+ * With "-Dnet4j.security.FileUserManager.fallBackToConfigFolder=true" a relative path is resolved in both the application's current folder
+ * and the config folder (in this order).
+ */
public void setFileName(String fileName)
{
+ checkInactive();
this.fileName = fileName;
}
+ /**
+ * @since 3.7
+ */
+ public final File getFile()
+ {
+ return file;
+ }
+
+ /**
+ * @since 3.7
+ */
+ protected File resolveFile(String fileName) throws Exception
+ {
+ if (StringUtil.isEmpty(fileName))
+ {
+ return null;
+ }
+
+ if (fileName.replace('\\', '/').startsWith(CONFIG_FOLDER_PREFIX))
+ {
+ return OMPlatform.INSTANCE.getConfigFile(fileName.substring(CONFIG_FOLDER_PREFIX.length()));
+ }
+
+ File file = new File(fileName);
+
+ if (FALL_BACK_TO_CONFIG_FOLDER && !file.isFile())
+ {
+ File configFile = OMPlatform.INSTANCE.getConfigFile(fileName);
+ if (configFile != null && configFile.isFile())
+ {
+ return configFile;
+ }
+ }
+
+ return file;
+ }
+
@Override
protected void doBeforeActivate() throws Exception
{
super.doBeforeActivate();
- if (fileName == null)
- {
- throw new IllegalStateException("fileName == null"); //$NON-NLS-1$
- }
- File file = new File(fileName);
- if (file.exists())
+ file = resolveFile(fileName);
+ if (file != null)
{
- if (!file.isFile())
- {
- throw new IllegalStateException("Not a file: " + fileName); //$NON-NLS-1$
- }
+ file = file.getCanonicalFile();
}
- else
- {
- throw new FileNotFoundException("User manager file not found: " + fileName);
- }
+ }
+
+ @Override
+ protected void doDeactivate() throws Exception
+ {
+ super.doDeactivate();
+ file = null;
}
@Override
protected void load(Map<String, char[]> users) throws IORuntimeException
{
- File file = new File(fileName);
- if (!file.exists())
+ if (file != null && file.isFile())
{
- return;
- }
+ FileInputStream stream = IOUtil.openInputStream(file);
- FileInputStream stream = IOUtil.openInputStream(new File(fileName));
- try
- {
- load(users, stream);
- }
- catch (IOException ex)
- {
- throw new IORuntimeException(ex);
- }
- finally
- {
- IOUtil.closeSilent(stream);
+ try
+ {
+ load(users, stream);
+ }
+ catch (IOException ex)
+ {
+ throw new IORuntimeException(ex);
+ }
+ finally
+ {
+ IOUtil.closeSilent(stream);
+ }
}
}
@@ -96,6 +150,7 @@
{
Properties properties = new Properties();
properties.load(stream);
+
for (Entry<Object, Object> entry : properties.entrySet())
{
String userID = (String)entry.getKey();
@@ -107,30 +162,30 @@
@Override
protected void save(Map<String, char[]> users) throws IORuntimeException
{
- File file = new File(fileName);
- if (!file.exists())
+ if (file != null)
{
- return;
- }
+ file.getParentFile().mkdirs();
+ FileOutputStream stream = IOUtil.openOutputStream(file);
- FileOutputStream stream = IOUtil.openOutputStream(new File(fileName));
- try
- {
- save(users, stream);
- }
- catch (IOException ex)
- {
- throw new IORuntimeException(ex);
- }
- finally
- {
- IOUtil.closeSilent(stream);
+ try
+ {
+ save(users, stream);
+ }
+ catch (IOException ex)
+ {
+ throw new IORuntimeException(ex);
+ }
+ finally
+ {
+ IOUtil.closeSilent(stream);
+ }
}
}
protected void save(Map<String, char[]> users, FileOutputStream stream) throws IOException
{
Properties properties = new Properties();
+
for (Entry<String, char[]> entry : users.entrySet())
{
properties.put(entry.getKey(), new String(entry.getValue()));
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/UserManager.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/UserManager.java
index d77d7bb..8478399 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/UserManager.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/UserManager.java
@@ -47,7 +47,7 @@
/**
* @since 3.3
*/
- public char[] getPassword(String userID)
+ public synchronized char[] getPassword(String userID)
{
return users.get(userID);
}