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
.Dictionary
;
10 import java
.util
.SortedMap
;
11 import java
.util
.TreeMap
;
13 import javax
.naming
.InvalidNameException
;
14 import javax
.naming
.directory
.Attributes
;
15 import javax
.naming
.directory
.BasicAttributes
;
16 import javax
.naming
.ldap
.LdapName
;
17 import javax
.naming
.ldap
.Rdn
;
19 import org
.apache
.commons
.logging
.Log
;
20 import org
.apache
.commons
.logging
.LogFactory
;
21 import org
.argeo
.cms
.CmsException
;
22 import org
.argeo
.node
.NodeConstants
;
23 import org
.argeo
.osgi
.useradmin
.UserAdminConf
;
24 import org
.argeo
.util
.naming
.AttributesDictionary
;
25 import org
.argeo
.util
.naming
.LdifParser
;
26 import org
.argeo
.util
.naming
.LdifWriter
;
27 import org
.osgi
.framework
.BundleContext
;
28 import org
.osgi
.framework
.FrameworkUtil
;
29 import org
.osgi
.service
.cm
.Configuration
;
30 import org
.osgi
.service
.cm
.ConfigurationAdmin
;
31 import org
.osgi
.service
.cm
.ConfigurationEvent
;
32 import org
.osgi
.service
.cm
.ConfigurationListener
;
34 class DeployConfig
implements ConfigurationListener
{
35 private final Log log
= LogFactory
.getLog(getClass());
36 private final BundleContext bc
= FrameworkUtil
.getBundle(getClass()).getBundleContext();
38 private Path deployConfigPath
= KernelUtils
.getOsgiInstancePath(KernelConstants
.DEPLOY_CONFIG_PATH
);
39 private SortedMap
<LdapName
, Attributes
> deployConfigs
= new TreeMap
<>();
41 public DeployConfig(ConfigurationAdmin configurationAdmin
,boolean isClean
) {
42 // ConfigurationAdmin configurationAdmin =
43 // bc.getService(bc.getServiceReference(ConfigurationAdmin.class));
45 if (!Files
.exists(deployConfigPath
)) { // first init
48 init(configurationAdmin
, isClean
);
49 } catch (IOException e
) {
50 throw new CmsException("Could not init deploy configs", e
);
52 // FIXME check race conditions during initialization
53 // bc.registerService(ConfigurationListener.class, this, null);
56 private void firstInit() throws IOException
{
57 Files
.createDirectories(deployConfigPath
.getParent());
59 FirstInitProperties firstInit
= new FirstInitProperties();
60 firstInit
.prepareInstanceArea();
62 if (!Files
.exists(deployConfigPath
))// could have juste been copied
63 Files
.createFile(deployConfigPath
);
65 try (InputStream in
= Files
.newInputStream(deployConfigPath
)) {
66 deployConfigs
= new LdifParser().read(in
);
70 Dictionary
<String
, Object
> nodeConfig
= firstInit
71 .getNodeRepositoryConfig(getProps(NodeConstants
.NODE_REPOS_FACTORY_PID
, NodeConstants
.ALIAS_NODE
));
72 // node repository is mandatory
73 putFactoryDeployConfig(NodeConstants
.NODE_REPOS_FACTORY_PID
, nodeConfig
);
77 List
<Dictionary
<String
, Object
>> userDirectoryConfigs
= firstInit
.getUserDirectoryConfigs();
78 for (int i
= 0; i
< userDirectoryConfigs
.size(); i
++) {
79 Dictionary
<String
, Object
> userDirectoryConfig
= userDirectoryConfigs
.get(i
);
80 String cn
= Integer
.toString(i
);
81 userDirectoryConfig
.put(NodeConstants
.CN
, cn
);
82 putFactoryDeployConfig(NodeConstants
.NODE_USER_ADMIN_PID
, userDirectoryConfig
);
86 Dictionary
<String
, Object
> webServerConfig
= firstInit
87 .getHttpServerConfig(getProps(KernelConstants
.JETTY_FACTORY_PID
, NodeConstants
.DEFAULT
));
88 if (!webServerConfig
.isEmpty())
89 putFactoryDeployConfig(KernelConstants
.JETTY_FACTORY_PID
, webServerConfig
);
94 private void init(ConfigurationAdmin configurationAdmin
, boolean isClean
) throws IOException
{
96 try (InputStream in
= Files
.newInputStream(deployConfigPath
)) {
97 deployConfigs
= new LdifParser().read(in
);
100 for (LdapName dn
: deployConfigs
.keySet()) {
101 Rdn lastRdn
= dn
.getRdn(dn
.size() - 1);
102 LdapName prefix
= (LdapName
) dn
.getPrefix(dn
.size() - 1);
103 if (prefix
.toString().equals(NodeConstants
.DEPLOY_BASEDN
)) {
104 if (lastRdn
.getType().equals(NodeConstants
.CN
)) {
106 String pid
= lastRdn
.getValue().toString();
107 Configuration conf
= configurationAdmin
.getConfiguration(pid
);
108 AttributesDictionary dico
= new AttributesDictionary(deployConfigs
.get(dn
));
111 // service factory definition
114 // service factory service
115 Rdn beforeLastRdn
= dn
.getRdn(dn
.size() - 2);
116 assert beforeLastRdn
.getType().equals(NodeConstants
.OU
);
117 String factoryPid
= beforeLastRdn
.getValue().toString();
118 Configuration conf
= configurationAdmin
.createFactoryConfiguration(factoryPid
.toString(), null);
119 AttributesDictionary dico
= new AttributesDictionary(deployConfigs
.get(dn
));
124 // TODO check consistency if not clean
128 public void configurationEvent(ConfigurationEvent event
) {
130 if (ConfigurationEvent
.CM_UPDATED
== event
.getType()) {
131 ConfigurationAdmin configurationAdmin
= bc
.getService(event
.getReference());
132 Configuration conf
= configurationAdmin
.getConfiguration(event
.getPid(), null);
133 LdapName serviceDn
= null;
134 String factoryPid
= conf
.getFactoryPid();
135 if (factoryPid
!= null) {
136 LdapName serviceFactoryDn
= serviceFactoryDn(factoryPid
);
137 if (deployConfigs
.containsKey(serviceFactoryDn
)) {
138 for (LdapName dn
: deployConfigs
.keySet()) {
139 if (dn
.startsWith(serviceFactoryDn
)) {
140 Rdn lastRdn
= dn
.getRdn(dn
.size() - 1);
141 assert lastRdn
.getType().equals(NodeConstants
.CN
);
142 Object value
= conf
.getProperties().get(lastRdn
.getType());
143 assert value
!= null;
144 if (value
.equals(lastRdn
.getValue())) {
151 Object cn
= conf
.getProperties().get(NodeConstants
.CN
);
153 throw new IllegalArgumentException("Properties must contain cn");
154 if (serviceDn
== null) {
155 putFactoryDeployConfig(factoryPid
, conf
.getProperties());
157 Attributes attrs
= deployConfigs
.get(serviceDn
);
158 assert attrs
!= null;
159 AttributesDictionary
.copy(conf
.getProperties(), attrs
);
162 if (log
.isDebugEnabled())
163 log
.debug("Updated deploy config " + serviceDn(factoryPid
, cn
.toString()));
165 // ignore non config-registered service factories
168 serviceDn
= serviceDn(event
.getPid());
169 if (deployConfigs
.containsKey(serviceDn
)) {
170 Attributes attrs
= deployConfigs
.get(serviceDn
);
171 assert attrs
!= null;
172 AttributesDictionary
.copy(conf
.getProperties(), attrs
);
174 if (log
.isDebugEnabled())
175 log
.debug("Updated deploy config " + serviceDn
);
177 // ignore non config-registered services
181 } catch (Exception e
) {
182 log
.error("Could not handle configuration event", e
);
186 void putFactoryDeployConfig(String factoryPid
, Dictionary
<String
, Object
> props
) {
187 Object cn
= props
.get(NodeConstants
.CN
);
189 throw new IllegalArgumentException("cn must be set in properties");
190 LdapName serviceFactoryDn
= serviceFactoryDn(factoryPid
);
191 if (!deployConfigs
.containsKey(serviceFactoryDn
))
192 deployConfigs
.put(serviceFactoryDn
, new BasicAttributes(NodeConstants
.OU
, factoryPid
));
193 LdapName serviceDn
= serviceDn(factoryPid
, cn
.toString());
194 Attributes attrs
= new BasicAttributes();
195 AttributesDictionary
.copy(props
, attrs
);
196 deployConfigs
.put(serviceDn
, attrs
);
199 void putDeployConfig(String servicePid
, Dictionary
<String
, Object
> props
) {
200 LdapName serviceDn
= serviceDn(servicePid
);
201 Attributes attrs
= new BasicAttributes(NodeConstants
.CN
, servicePid
);
202 AttributesDictionary
.copy(props
, attrs
);
203 deployConfigs
.put(serviceDn
, attrs
);
207 try (Writer writer
= Files
.newBufferedWriter(deployConfigPath
)) {
208 new LdifWriter(writer
).write(deployConfigs
);
209 } catch (IOException e
) {
210 throw new CmsException("Cannot save deploy configs", e
);
217 private LdapName
serviceFactoryDn(String factoryPid
) {
219 return new LdapName(NodeConstants
.OU
+ "=" + factoryPid
+ "," + NodeConstants
.DEPLOY_BASEDN
);
220 } catch (InvalidNameException e
) {
221 throw new IllegalArgumentException("Cannot generate DN from " + factoryPid
, e
);
225 private LdapName
serviceDn(String servicePid
) {
227 return new LdapName(NodeConstants
.CN
+ "=" + servicePid
+ "," + NodeConstants
.DEPLOY_BASEDN
);
228 } catch (InvalidNameException e
) {
229 throw new IllegalArgumentException("Cannot generate DN from " + servicePid
, e
);
233 private LdapName
serviceDn(String factoryPid
, String cn
) {
235 return (LdapName
) serviceFactoryDn(factoryPid
).add(new Rdn(NodeConstants
.CN
, cn
));
236 } catch (InvalidNameException e
) {
237 throw new IllegalArgumentException("Cannot generate DN from " + factoryPid
+ " and " + cn
, e
);
241 Dictionary
<String
, Object
> getProps(String factoryPid
, String cn
) {
242 Attributes attrs
= deployConfigs
.get(serviceDn(factoryPid
, cn
));
244 return new AttributesDictionary(attrs
);