1 package org
.argeo
.cms
.internal
.kernel
;
3 import java
.io
.IOException
;
4 import java
.io
.InputStream
;
6 import java
.nio
.file
.Files
;
7 import java
.nio
.file
.Path
;
8 import java
.util
.ArrayList
;
9 import java
.util
.Dictionary
;
10 import java
.util
.List
;
11 import java
.util
.SortedMap
;
12 import java
.util
.TreeMap
;
14 import javax
.naming
.InvalidNameException
;
15 import javax
.naming
.directory
.Attributes
;
16 import javax
.naming
.directory
.BasicAttributes
;
17 import javax
.naming
.ldap
.LdapName
;
18 import javax
.naming
.ldap
.Rdn
;
20 import org
.apache
.commons
.logging
.Log
;
21 import org
.apache
.commons
.logging
.LogFactory
;
22 import org
.argeo
.cms
.CmsException
;
23 import org
.argeo
.naming
.AttributesDictionary
;
24 import org
.argeo
.naming
.LdifParser
;
25 import org
.argeo
.naming
.LdifWriter
;
26 import org
.argeo
.node
.NodeConstants
;
27 import org
.argeo
.osgi
.useradmin
.UserAdminConf
;
28 import org
.osgi
.framework
.BundleContext
;
29 import org
.osgi
.framework
.FrameworkUtil
;
30 import org
.osgi
.service
.cm
.Configuration
;
31 import org
.osgi
.service
.cm
.ConfigurationAdmin
;
32 import org
.osgi
.service
.cm
.ConfigurationEvent
;
33 import org
.osgi
.service
.cm
.ConfigurationListener
;
35 class DeployConfig
implements ConfigurationListener
{
36 private final Log log
= LogFactory
.getLog(getClass());
37 private final BundleContext bc
= FrameworkUtil
.getBundle(getClass()).getBundleContext();
39 private static Path deployConfigPath
= KernelUtils
.getOsgiInstancePath(KernelConstants
.DEPLOY_CONFIG_PATH
);
40 private SortedMap
<LdapName
, Attributes
> deployConfigs
= new TreeMap
<>();
41 private final DataModels dataModels
;
43 public DeployConfig(ConfigurationAdmin configurationAdmin
, DataModels dataModels
, boolean isClean
) {
44 this.dataModels
= dataModels
;
45 // ConfigurationAdmin configurationAdmin =
46 // bc.getService(bc.getServiceReference(ConfigurationAdmin.class));
48 boolean isFirstInit
= false;
49 if (!isInitialized()) { // first init
53 init(configurationAdmin
, isClean
, isFirstInit
);
54 } catch (IOException e
) {
55 throw new CmsException("Could not init deploy configs", e
);
57 // FIXME check race conditions during initialization
58 // bc.registerService(ConfigurationListener.class, this, null);
61 private void firstInit() throws IOException
{
62 log
.info("## FIRST INIT ##");
63 Files
.createDirectories(deployConfigPath
.getParent());
65 // FirstInit firstInit = new FirstInit();
66 InitUtils
.prepareFirstInitInstanceArea();
68 if (!Files
.exists(deployConfigPath
))
69 deployConfigs
= new TreeMap
<>();
70 else// config file could have juste been copied by preparation
71 try (InputStream in
= Files
.newInputStream(deployConfigPath
)) {
72 deployConfigs
= new LdifParser().read(in
);
77 private void setFromFrameworkProperties(boolean isFirstInit
) {
79 Dictionary
<String
, Object
> nodeConfig
= InitUtils
80 .getNodeRepositoryConfig(getProps(NodeConstants
.NODE_REPOS_FACTORY_PID
, NodeConstants
.NODE
));
81 // node repository is mandatory
82 putFactoryDeployConfig(NodeConstants
.NODE_REPOS_FACTORY_PID
, nodeConfig
);
84 // additional repositories
85 dataModels
: for (DataModels
.DataModel dataModel
: dataModels
.getNonAbstractDataModels()) {
86 if (NodeConstants
.NODE
.equals(dataModel
.getName()))
88 Dictionary
<String
, Object
> config
= InitUtils
.getRepositoryConfig(dataModel
.getName(),
89 getProps(NodeConstants
.NODE_REPOS_FACTORY_PID
, dataModel
.getName()));
90 if (config
.size() != 0)
91 putFactoryDeployConfig(NodeConstants
.NODE_REPOS_FACTORY_PID
, config
);
95 List
<Dictionary
<String
, Object
>> userDirectoryConfigs
= InitUtils
.getUserDirectoryConfigs();
96 if (userDirectoryConfigs
.size() != 0) {
97 List
<String
> activeCns
= new ArrayList
<>();
98 for (int i
= 0; i
< userDirectoryConfigs
.size(); i
++) {
99 Dictionary
<String
, Object
> userDirectoryConfig
= userDirectoryConfigs
.get(i
);
100 String cn
= UserAdminConf
.baseDnHash(userDirectoryConfig
);
102 userDirectoryConfig
.put(NodeConstants
.CN
, cn
);
103 putFactoryDeployConfig(NodeConstants
.NODE_USER_ADMIN_PID
, userDirectoryConfig
);
106 LdapName userAdminFactoryName
= serviceFactoryDn(NodeConstants
.NODE_USER_ADMIN_PID
);
107 for (LdapName name
: deployConfigs
.keySet()) {
108 if (name
.startsWith(userAdminFactoryName
) && !name
.equals(userAdminFactoryName
)) {
110 Attributes attrs
= deployConfigs
.get(name
);
111 String cn
= name
.getRdn(name
.size() - 1).getValue().toString();
112 if (!activeCns
.contains(cn
)) {
113 attrs
.put(UserAdminConf
.disabled
.name(), "true");
115 } catch (Exception e
) {
116 throw new CmsException("Cannot disable user directory " + name
, e
);
123 Dictionary
<String
, Object
> webServerConfig
= InitUtils
124 .getHttpServerConfig(getProps(KernelConstants
.JETTY_FACTORY_PID
, NodeConstants
.DEFAULT
));
125 if (!webServerConfig
.isEmpty()) {
126 // TODO chekc for other customizers
127 webServerConfig
.put("customizer.class", "org.argeo.equinox.jetty.CmsJettyCustomizer");
128 putFactoryDeployConfig(KernelConstants
.JETTY_FACTORY_PID
, webServerConfig
);
133 private void init(ConfigurationAdmin configurationAdmin
, boolean isClean
, boolean isFirstInit
) throws IOException
{
135 try (InputStream in
= Files
.newInputStream(deployConfigPath
)) {
136 deployConfigs
= new LdifParser().read(in
);
139 setFromFrameworkProperties(isFirstInit
);
140 for (LdapName dn
: deployConfigs
.keySet()) {
141 Rdn lastRdn
= dn
.getRdn(dn
.size() - 1);
142 LdapName prefix
= (LdapName
) dn
.getPrefix(dn
.size() - 1);
143 if (prefix
.toString().equals(NodeConstants
.DEPLOY_BASEDN
)) {
144 if (lastRdn
.getType().equals(NodeConstants
.CN
)) {
146 String pid
= lastRdn
.getValue().toString();
147 Configuration conf
= configurationAdmin
.getConfiguration(pid
);
148 AttributesDictionary dico
= new AttributesDictionary(deployConfigs
.get(dn
));
151 // service factory definition
154 // service factory service
155 Rdn beforeLastRdn
= dn
.getRdn(dn
.size() - 2);
156 assert beforeLastRdn
.getType().equals(NodeConstants
.OU
);
157 String factoryPid
= beforeLastRdn
.getValue().toString();
158 Configuration conf
= configurationAdmin
.createFactoryConfiguration(factoryPid
.toString(), null);
159 AttributesDictionary dico
= new AttributesDictionary(deployConfigs
.get(dn
));
164 // TODO check consistency if not clean
168 public void configurationEvent(ConfigurationEvent event
) {
170 if (ConfigurationEvent
.CM_UPDATED
== event
.getType()) {
171 ConfigurationAdmin configurationAdmin
= bc
.getService(event
.getReference());
172 Configuration conf
= configurationAdmin
.getConfiguration(event
.getPid(), null);
173 LdapName serviceDn
= null;
174 String factoryPid
= conf
.getFactoryPid();
175 if (factoryPid
!= null) {
176 LdapName serviceFactoryDn
= serviceFactoryDn(factoryPid
);
177 if (deployConfigs
.containsKey(serviceFactoryDn
)) {
178 for (LdapName dn
: deployConfigs
.keySet()) {
179 if (dn
.startsWith(serviceFactoryDn
)) {
180 Rdn lastRdn
= dn
.getRdn(dn
.size() - 1);
181 assert lastRdn
.getType().equals(NodeConstants
.CN
);
182 Object value
= conf
.getProperties().get(lastRdn
.getType());
183 assert value
!= null;
184 if (value
.equals(lastRdn
.getValue())) {
191 Object cn
= conf
.getProperties().get(NodeConstants
.CN
);
193 throw new IllegalArgumentException("Properties must contain cn");
194 if (serviceDn
== null) {
195 putFactoryDeployConfig(factoryPid
, conf
.getProperties());
197 Attributes attrs
= deployConfigs
.get(serviceDn
);
198 assert attrs
!= null;
199 AttributesDictionary
.copy(conf
.getProperties(), attrs
);
202 if (log
.isDebugEnabled())
203 log
.debug("Updated deploy config " + serviceDn(factoryPid
, cn
.toString()));
205 // ignore non config-registered service factories
208 serviceDn
= serviceDn(event
.getPid());
209 if (deployConfigs
.containsKey(serviceDn
)) {
210 Attributes attrs
= deployConfigs
.get(serviceDn
);
211 assert attrs
!= null;
212 AttributesDictionary
.copy(conf
.getProperties(), attrs
);
214 if (log
.isDebugEnabled())
215 log
.debug("Updated deploy config " + serviceDn
);
217 // ignore non config-registered services
221 } catch (Exception e
) {
222 log
.error("Could not handle configuration event", e
);
226 void putFactoryDeployConfig(String factoryPid
, Dictionary
<String
, Object
> props
) {
227 Object cn
= props
.get(NodeConstants
.CN
);
229 throw new IllegalArgumentException("cn must be set in properties");
230 LdapName serviceFactoryDn
= serviceFactoryDn(factoryPid
);
231 if (!deployConfigs
.containsKey(serviceFactoryDn
))
232 deployConfigs
.put(serviceFactoryDn
, new BasicAttributes(NodeConstants
.OU
, factoryPid
));
233 LdapName serviceDn
= serviceDn(factoryPid
, cn
.toString());
234 Attributes attrs
= new BasicAttributes();
235 AttributesDictionary
.copy(props
, attrs
);
236 deployConfigs
.put(serviceDn
, attrs
);
239 void putDeployConfig(String servicePid
, Dictionary
<String
, Object
> props
) {
240 LdapName serviceDn
= serviceDn(servicePid
);
241 Attributes attrs
= new BasicAttributes(NodeConstants
.CN
, servicePid
);
242 AttributesDictionary
.copy(props
, attrs
);
243 deployConfigs
.put(serviceDn
, attrs
);
247 try (Writer writer
= Files
.newBufferedWriter(deployConfigPath
)) {
248 new LdifWriter(writer
).write(deployConfigs
);
249 } catch (IOException e
) {
250 // throw new CmsException("Cannot save deploy configs", e);
251 log
.error("Cannot save deploy configs", e
);
255 boolean isStandalone(String dataModelName
) {
256 return getProps(NodeConstants
.NODE_REPOS_FACTORY_PID
, dataModelName
) != null;
262 private LdapName
serviceFactoryDn(String factoryPid
) {
264 return new LdapName(NodeConstants
.OU
+ "=" + factoryPid
+ "," + NodeConstants
.DEPLOY_BASEDN
);
265 } catch (InvalidNameException e
) {
266 throw new IllegalArgumentException("Cannot generate DN from " + factoryPid
, e
);
270 private LdapName
serviceDn(String servicePid
) {
272 return new LdapName(NodeConstants
.CN
+ "=" + servicePid
+ "," + NodeConstants
.DEPLOY_BASEDN
);
273 } catch (InvalidNameException e
) {
274 throw new IllegalArgumentException("Cannot generate DN from " + servicePid
, e
);
278 private LdapName
serviceDn(String factoryPid
, String cn
) {
280 return (LdapName
) serviceFactoryDn(factoryPid
).add(new Rdn(NodeConstants
.CN
, cn
));
281 } catch (InvalidNameException e
) {
282 throw new IllegalArgumentException("Cannot generate DN from " + factoryPid
+ " and " + cn
, e
);
286 Dictionary
<String
, Object
> getProps(String factoryPid
, String cn
) {
287 Attributes attrs
= deployConfigs
.get(serviceDn(factoryPid
, cn
));
289 return new AttributesDictionary(attrs
);
294 static boolean isInitialized() {
295 return Files
.exists(deployConfigPath
);