1 package org
.argeo
.osgi
.useradmin
;
3 import java
.io
.UnsupportedEncodingException
;
5 import java
.net
.URISyntaxException
;
6 import java
.net
.URLDecoder
;
7 import java
.util
.Dictionary
;
8 import java
.util
.Enumeration
;
9 import java
.util
.Hashtable
;
10 import java
.util
.LinkedHashMap
;
11 import java
.util
.LinkedList
;
12 import java
.util
.List
;
15 import javax
.naming
.Context
;
17 import org
.osgi
.framework
.Constants
;
19 /** Properties used to configure user admins. */
20 public enum UserAdminConf
{
21 /** Base DN (cannot be configured externally) */
22 baseDn("dc=example,dc=com"),
24 /** URI of the underlying resource (cannot be configured externally) */
25 uri("ldap://localhost:10389"),
27 /** User objectClass */
28 userObjectClass("inetOrgPerson"),
30 /** Relative base DN for users */
31 userBase("ou=People"),
33 /** Groups objectClass */
34 groupObjectClass("groupOfNames"),
36 /** Relative base DN for users */
37 groupBase("ou=Groups"),
39 /** Read-only source */
42 public final static String FACTORY_PID
= "org.argeo.osgi.useradmin.config";
44 /** The default value. */
47 UserAdminConf(Object def
) {
51 public Object
getDefault() {
56 * For use as Java property.
58 * @deprecated use {@link #name()} instead
61 public String
property() {
65 public String
getValue(Dictionary
<String
, ?
> properties
) {
66 Object res
= getRawValue(properties
);
69 return res
.toString();
72 @SuppressWarnings("unchecked")
73 public <T
> T
getRawValue(Dictionary
<String
, ?
> properties
) {
74 Object res
= properties
.get(name());
80 /** @deprecated use {@link #valueOf(String)} instead */
82 public static UserAdminConf
local(String property
) {
83 return UserAdminConf
.valueOf(property
);
86 /** Hides host and credentials. */
87 public static URI
propertiesAsUri(Dictionary
<String
, ?
> properties
) {
88 StringBuilder query
= new StringBuilder();
91 for (Enumeration
<String
> keys
= properties
.keys(); keys
.hasMoreElements();) {
92 String key
= keys
.nextElement();
93 // TODO clarify which keys are relevant (list only the enum?)
94 if (!key
.equals("service.factoryPid") && !key
.equals("cn") && !key
.equals("dn")
95 && !key
.equals(Constants
.SERVICE_PID
) && !key
.startsWith("java") && !key
.equals(baseDn
.name())
96 && !key
.equals(uri
.name())) {
101 query
.append(valueOf(key
).name());
102 query
.append('=').append(properties
.get(key
).toString());
106 String bDn
= (String
) properties
.get(baseDn
.name());
108 return new URI(null, null, bDn
!= null ?
'/' + bDn
: null, query
.length() != 0 ? query
.toString() : null,
110 } catch (URISyntaxException e
) {
111 throw new UserDirectoryException("Cannot create URI from properties", e
);
115 public static Dictionary
<String
, Object
> uriAsProperties(String uriStr
) {
117 Hashtable
<String
, Object
> res
= new Hashtable
<String
, Object
>();
118 URI u
= new URI(uriStr
);
119 String scheme
= u
.getScheme();
120 String path
= u
.getPath();
121 String bDn
= path
.substring(path
.lastIndexOf('/') + 1, path
.length());
122 if (bDn
.endsWith(".ldif"))
123 bDn
= bDn
.substring(0, bDn
.length() - ".ldif".length());
125 String principal
= null;
126 String credentials
= null;
128 if (scheme
.equals("ldap") || scheme
.equals("ldaps")) {
129 // TODO additional checks
130 String
[] userInfo
= u
.getUserInfo().split(":");
131 principal
= userInfo
.length
> 0 ? userInfo
[0] : null;
132 credentials
= userInfo
.length
> 1 ? userInfo
[1] : null;
133 } else if (scheme
.equals("file")) {
135 throw new UserDirectoryException("Unsupported scheme " + scheme
);
136 Map
<String
, List
<String
>> query
= splitQuery(u
.getQuery());
137 for (String key
: query
.keySet()) {
138 UserAdminConf ldapProp
= UserAdminConf
.valueOf(key
);
139 List
<String
> values
= query
.get(key
);
140 if (values
.size() == 1) {
141 res
.put(ldapProp
.name(), values
.get(0));
143 throw new UserDirectoryException("Only single values are supported");
146 res
.put(baseDn
.name(), bDn
);
147 if (principal
!= null)
148 res
.put(Context
.SECURITY_PRINCIPAL
, principal
);
149 if (credentials
!= null)
150 res
.put(Context
.SECURITY_CREDENTIALS
, credentials
);
151 if (scheme
!= null) {
152 URI bareUri
= new URI(scheme
, null, u
.getHost(), u
.getPort(),
153 scheme
.equals("file") ? u
.getPath() : null, null, null);
154 res
.put(uri
.name(), bareUri
.toString());
157 } catch (Exception e
) {
158 throw new UserDirectoryException("Cannot convert " + uri
+ " to properties", e
);
162 private static Map
<String
, List
<String
>> splitQuery(String query
) throws UnsupportedEncodingException
{
163 final Map
<String
, List
<String
>> query_pairs
= new LinkedHashMap
<String
, List
<String
>>();
166 final String
[] pairs
= query
.split("&");
167 for (String pair
: pairs
) {
168 final int idx
= pair
.indexOf("=");
169 final String key
= idx
> 0 ? URLDecoder
.decode(pair
.substring(0, idx
), "UTF-8") : pair
;
170 if (!query_pairs
.containsKey(key
)) {
171 query_pairs
.put(key
, new LinkedList
<String
>());
173 final String value
= idx
> 0 && pair
.length() > idx
+ 1
174 ? URLDecoder
.decode(pair
.substring(idx
+ 1), "UTF-8") : null;
175 query_pairs
.get(key
).add(value
);
180 public static void main(String
[] args
) {
181 Dictionary
<String
, ?
> props
= uriAsProperties("ldap://" + "uid=admin,ou=system:secret@localhost:10389"
182 + "/dc=example,dc=com" + "?readOnly=false&userObjectClass=person");
183 System
.out
.println(props
);
184 System
.out
.println(propertiesAsUri(props
));
186 System
.out
.println(uriAsProperties("file://some/dir/dc=example,dc=com.ldif"));
188 props
= uriAsProperties(
189 "/dc=example,dc=com.ldif?readOnly=true" + "&userBase=ou=CoWorkers,ou=People&groupBase=ou=Roles");
190 System
.out
.println(props
);
191 System
.out
.println(propertiesAsUri(props
));