1 package org
.argeo
.cms
.internal
.kernel
;
3 import static org
.argeo
.api
.DataModelNamespace
.CMS_DATA_MODEL_NAMESPACE
;
4 import static org
.osgi
.service
.http
.whiteboard
.HttpWhiteboardConstants
.HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX
;
7 import java
.io
.IOException
;
8 import java
.io
.InputStreamReader
;
10 import java
.lang
.management
.ManagementFactory
;
12 import java
.nio
.file
.Files
;
13 import java
.nio
.file
.Path
;
14 import java
.nio
.file
.Paths
;
15 import java
.util
.ArrayList
;
16 import java
.util
.Arrays
;
17 import java
.util
.Collection
;
18 import java
.util
.Dictionary
;
19 import java
.util
.HashSet
;
20 import java
.util
.Hashtable
;
21 import java
.util
.Iterator
;
22 import java
.util
.List
;
26 import javax
.jcr
.Repository
;
27 import javax
.jcr
.RepositoryException
;
28 import javax
.jcr
.Session
;
29 import javax
.security
.auth
.callback
.CallbackHandler
;
30 import javax
.servlet
.Servlet
;
31 import javax
.transaction
.UserTransaction
;
33 import org
.apache
.commons
.logging
.Log
;
34 import org
.apache
.commons
.logging
.LogFactory
;
35 import org
.apache
.jackrabbit
.commons
.cnd
.CndImporter
;
36 import org
.apache
.jackrabbit
.core
.RepositoryContext
;
37 import org
.apache
.jackrabbit
.core
.RepositoryImpl
;
38 import org
.argeo
.api
.DataModelNamespace
;
39 import org
.argeo
.api
.NodeConstants
;
40 import org
.argeo
.api
.NodeDeployment
;
41 import org
.argeo
.api
.NodeState
;
42 import org
.argeo
.api
.NodeUtils
;
43 import org
.argeo
.api
.security
.CryptoKeyring
;
44 import org
.argeo
.api
.security
.Keyring
;
45 import org
.argeo
.cms
.ArgeoNames
;
46 import org
.argeo
.cms
.internal
.http
.CmsRemotingServlet
;
47 import org
.argeo
.cms
.internal
.http
.CmsWebDavServlet
;
48 import org
.argeo
.cms
.internal
.http
.HttpUtils
;
49 import org
.argeo
.cms
.internal
.jcr
.JcrInitUtils
;
50 import org
.argeo
.jcr
.Jcr
;
51 import org
.argeo
.jcr
.JcrException
;
52 import org
.argeo
.jcr
.JcrUtils
;
53 import org
.argeo
.maintenance
.backup
.LogicalRestore
;
54 import org
.argeo
.naming
.LdapAttrs
;
55 import org
.argeo
.osgi
.useradmin
.UserAdminConf
;
56 import org
.argeo
.util
.LangUtils
;
57 import org
.eclipse
.equinox
.http
.jetty
.JettyConfigurator
;
58 import org
.osgi
.framework
.Bundle
;
59 import org
.osgi
.framework
.BundleContext
;
60 import org
.osgi
.framework
.Constants
;
61 import org
.osgi
.framework
.FrameworkUtil
;
62 import org
.osgi
.framework
.InvalidSyntaxException
;
63 import org
.osgi
.framework
.ServiceReference
;
64 import org
.osgi
.framework
.wiring
.BundleCapability
;
65 import org
.osgi
.framework
.wiring
.BundleWire
;
66 import org
.osgi
.framework
.wiring
.BundleWiring
;
67 import org
.osgi
.service
.cm
.Configuration
;
68 import org
.osgi
.service
.cm
.ConfigurationAdmin
;
69 import org
.osgi
.service
.cm
.ManagedService
;
70 import org
.osgi
.service
.http
.HttpService
;
71 import org
.osgi
.service
.http
.whiteboard
.HttpWhiteboardConstants
;
72 import org
.osgi
.service
.useradmin
.Group
;
73 import org
.osgi
.service
.useradmin
.Role
;
74 import org
.osgi
.service
.useradmin
.UserAdmin
;
75 import org
.osgi
.util
.tracker
.ServiceTracker
;
77 /** Implementation of a CMS deployment. */
78 public class CmsDeployment
implements NodeDeployment
{
79 private final Log log
= LogFactory
.getLog(getClass());
80 private final BundleContext bc
= FrameworkUtil
.getBundle(getClass()).getBundleContext();
82 private DataModels dataModels
;
83 private DeployConfig deployConfig
;
85 private Long availableSince
;
87 // private final boolean cleanState;
89 // private NodeHttp nodeHttp;
90 private String webDavConfig
= HttpUtils
.WEBDAV_CONFIG
;
92 private boolean argeoDataModelExtensionsAvailable
= false;
95 private boolean nodeAvailable
= false;
96 private boolean userAdminAvailable
= false;
97 private boolean httpExpected
= false;
98 private boolean httpAvailable
= false;
100 public CmsDeployment() {
101 // ServiceReference<NodeState> nodeStateSr = bc.getServiceReference(NodeState.class);
102 // if (nodeStateSr == null)
103 // throw new CmsException("No node state available");
105 // NodeState nodeState = bc.getService(nodeStateSr);
106 // cleanState = nodeState.isClean();
108 // nodeHttp = new NodeHttp();
109 dataModels
= new DataModels(bc
);
113 private void initTrackers() {
114 ServiceTracker
<?
, ?
> httpSt
= new ServiceTracker
<HttpService
, HttpService
>(bc
, HttpService
.class, null) {
117 public HttpService
addingService(ServiceReference
<HttpService
> sr
) {
118 httpAvailable
= true;
119 Object httpPort
= sr
.getProperty("http.port");
120 Object httpsPort
= sr
.getProperty("https.port");
121 log
.info(httpPortsMsg(httpPort
, httpsPort
));
123 return super.addingService(sr
);
127 KernelUtils
.asyncOpen(httpSt
);
129 ServiceTracker
<?
, ?
> repoContextSt
= new RepositoryContextStc();
130 // repoContextSt.open();
131 KernelUtils
.asyncOpen(repoContextSt
);
133 ServiceTracker
<?
, ?
> userAdminSt
= new ServiceTracker
<UserAdmin
, UserAdmin
>(bc
, UserAdmin
.class, null) {
135 public UserAdmin
addingService(ServiceReference
<UserAdmin
> reference
) {
136 UserAdmin userAdmin
= super.addingService(reference
);
137 addStandardSystemRoles(userAdmin
);
138 userAdminAvailable
= true;
143 // userAdminSt.open();
144 KernelUtils
.asyncOpen(userAdminSt
);
146 ServiceTracker
<?
, ?
> confAdminSt
= new ServiceTracker
<ConfigurationAdmin
, ConfigurationAdmin
>(bc
,
147 ConfigurationAdmin
.class, null) {
149 public ConfigurationAdmin
addingService(ServiceReference
<ConfigurationAdmin
> reference
) {
150 ConfigurationAdmin configurationAdmin
= bc
.getService(reference
);
153 Configuration
[] confs
= configurationAdmin
154 .listConfigurations("(service.factoryPid=" + NodeConstants
.NODE_USER_ADMIN_PID
+ ")");
155 isClean
= confs
== null || confs
.length
== 0;
156 } catch (Exception e
) {
157 throw new IllegalStateException("Cannot analyse clean state", e
);
159 deployConfig
= new DeployConfig(configurationAdmin
, dataModels
, isClean
);
160 JcrInitUtils
.addToDeployment(CmsDeployment
.this);
161 httpExpected
= deployConfig
.getProps(KernelConstants
.JETTY_FACTORY_PID
, "default") != null;
163 Configuration
[] configs
= configurationAdmin
164 .listConfigurations("(service.factoryPid=" + NodeConstants
.NODE_USER_ADMIN_PID
+ ")");
166 boolean hasDomain
= false;
167 for (Configuration config
: configs
) {
168 Object realm
= config
.getProperties().get(UserAdminConf
.realm
.name());
170 log
.debug("Found realm: " + realm
);
175 loadIpaJaasConfiguration();
177 } catch (Exception e
) {
178 throw new IllegalStateException("Cannot initialize config", e
);
180 return super.addingService(reference
);
183 // confAdminSt.open();
184 KernelUtils
.asyncOpen(confAdminSt
);
187 public void addFactoryDeployConfig(String factoryPid
, Dictionary
<String
, Object
> props
) {
188 deployConfig
.putFactoryDeployConfig(factoryPid
, props
);
191 deployConfig
.loadConfigs();
192 } catch (IOException e
) {
193 throw new IllegalStateException(e
);
197 public Dictionary
<String
, Object
> getProps(String factoryPid
, String cn
) {
198 return deployConfig
.getProps(factoryPid
, cn
);
201 private String
httpPortsMsg(Object httpPort
, Object httpsPort
) {
202 return (httpPort
!= null ?
"HTTP " + httpPort
+ " " : " ") + (httpsPort
!= null ?
"HTTPS " + httpsPort
: "");
205 private void addStandardSystemRoles(UserAdmin userAdmin
) {
206 // we assume UserTransaction is already available (TODO make it more robust)
207 UserTransaction userTransaction
= bc
.getService(bc
.getServiceReference(UserTransaction
.class));
209 userTransaction
.begin();
210 Role adminRole
= userAdmin
.getRole(NodeConstants
.ROLE_ADMIN
);
211 if (adminRole
== null) {
212 adminRole
= userAdmin
.createRole(NodeConstants
.ROLE_ADMIN
, Role
.GROUP
);
214 if (userAdmin
.getRole(NodeConstants
.ROLE_USER_ADMIN
) == null) {
215 Group userAdminRole
= (Group
) userAdmin
.createRole(NodeConstants
.ROLE_USER_ADMIN
, Role
.GROUP
);
216 userAdminRole
.addMember(adminRole
);
218 userTransaction
.commit();
219 } catch (Exception e
) {
221 userTransaction
.rollback();
222 } catch (Exception e1
) {
225 throw new IllegalStateException("Cannot add standard system roles", e
);
229 private void loadIpaJaasConfiguration() {
230 if (System
.getProperty(KernelConstants
.JAAS_CONFIG_PROP
) == null) {
231 String jaasConfig
= KernelConstants
.JAAS_CONFIG_IPA
;
232 URL url
= getClass().getClassLoader().getResource(jaasConfig
);
233 KernelUtils
.setJaasConfiguration(url
);
234 log
.debug("Set IPA JAAS configuration.");
238 public void shutdown() {
239 // if (nodeHttp != null)
240 // nodeHttp.destroy();
243 for (ServiceReference
<JackrabbitLocalRepository
> sr
: bc
244 .getServiceReferences(JackrabbitLocalRepository
.class, null)) {
245 bc
.getService(sr
).destroy();
247 } catch (InvalidSyntaxException e1
) {
248 log
.error("Cannot sclean repsoitories", e1
);
252 JettyConfigurator
.stopServer(KernelConstants
.DEFAULT_JETTY_SERVER
);
253 } catch (Exception e
) {
254 log
.error("Cannot stop default Jetty server.", e
);
257 if (deployConfig
!= null) {
258 new Thread(() -> deployConfig
.save(), "Save Argeo Deploy Config").start();
263 * Checks whether the deployment is available according to expectations, and
264 * mark it as available.
266 private synchronized void checkReadiness() {
269 if (nodeAvailable
&& userAdminAvailable
&& (httpExpected ? httpAvailable
: true)) {
270 String data
= KernelUtils
.getFrameworkProp(KernelUtils
.OSGI_INSTANCE_AREA
);
271 String state
= KernelUtils
.getFrameworkProp(KernelUtils
.OSGI_CONFIGURATION_AREA
);
272 availableSince
= System
.currentTimeMillis();
273 long jvmUptime
= ManagementFactory
.getRuntimeMXBean().getUptime();
274 String jvmUptimeStr
= " in " + (jvmUptime
/ 1000) + "." + (jvmUptime
% 1000) + "s";
275 log
.info("## ARGEO NODE AVAILABLE" + (log
.isDebugEnabled() ? jvmUptimeStr
: "") + " ##");
276 if (log
.isDebugEnabled()) {
277 log
.debug("## state: " + state
);
279 log
.debug("## data: " + data
);
281 long begin
= bc
.getService(bc
.getServiceReference(NodeState
.class)).getAvailableSince();
282 long initDuration
= System
.currentTimeMillis() - begin
;
283 if (log
.isTraceEnabled())
284 log
.trace("Kernel initialization took " + initDuration
+ "ms");
285 tributeToFreeSoftware(initDuration
);
289 final private void tributeToFreeSoftware(long initDuration
) {
290 if (log
.isTraceEnabled()) {
291 long ms
= initDuration
/ 100;
292 log
.trace("Spend " + ms
+ "ms" + " reflecting on the progress brought to mankind" + " by Free Software...");
293 long beginNano
= System
.nanoTime();
296 } catch (InterruptedException e
) {
299 long durationNano
= System
.nanoTime() - beginNano
;
300 final double M
= 1000d
* 1000d
;
301 double sleepAccuracy
= ((double) durationNano
) / (ms
* M
);
302 log
.trace("Sleep accuracy: " + String
.format("%.2f", 100 - (sleepAccuracy
* 100 - 100)) + " %");
306 private void prepareNodeRepository(Repository deployedNodeRepository
, List
<String
> publishAsLocalRepo
) {
307 if (availableSince
!= null) {
308 throw new IllegalStateException("Deployment is already available");
312 prepareDataModel(NodeConstants
.NODE_REPOSITORY
, deployedNodeRepository
, publishAsLocalRepo
);
315 if (deployConfig
.isFirstInit()) {
316 Path restorePath
= Paths
.get(System
.getProperty("user.dir"), "restore");
317 if (Files
.exists(restorePath
)) {
318 if (log
.isDebugEnabled())
319 log
.debug("Found backup " + restorePath
+ ", restoring it...");
320 LogicalRestore logicalRestore
= new LogicalRestore(bc
, deployedNodeRepository
, restorePath
);
321 KernelUtils
.doAsDataAdmin(logicalRestore
);
322 log
.info("Restored backup from " + restorePath
);
326 // init from repository
327 Collection
<ServiceReference
<Repository
>> initRepositorySr
;
329 initRepositorySr
= bc
.getServiceReferences(Repository
.class,
330 "(" + NodeConstants
.CN
+ "=" + NodeConstants
.NODE_INIT
+ ")");
331 } catch (InvalidSyntaxException e1
) {
332 throw new IllegalArgumentException(e1
);
334 Iterator
<ServiceReference
<Repository
>> it
= initRepositorySr
.iterator();
335 while (it
.hasNext()) {
336 ServiceReference
<Repository
> sr
= it
.next();
337 Object labeledUri
= sr
.getProperties().get(LdapAttrs
.labeledURI
.name());
338 Repository initRepository
= bc
.getService(sr
);
339 if (log
.isDebugEnabled())
340 log
.debug("Found init repository " + labeledUri
+ ", copying it...");
341 initFromRepository(deployedNodeRepository
, initRepository
);
342 log
.info("Node repository initialised from " + labeledUri
);
346 /** Init from a (typically remote) repository. */
347 private void initFromRepository(Repository deployedNodeRepository
, Repository initRepository
) {
348 Session initSession
= null;
350 initSession
= initRepository
.login();
351 workspaces
: for (String workspaceName
: initSession
.getWorkspace().getAccessibleWorkspaceNames()) {
352 if ("security".equals(workspaceName
))
354 if (log
.isDebugEnabled())
355 log
.debug("Copying workspace " + workspaceName
+ " from init repository...");
356 long begin
= System
.currentTimeMillis();
357 Session targetSession
= null;
358 Session sourceSession
= null;
361 targetSession
= NodeUtils
.openDataAdminSession(deployedNodeRepository
, workspaceName
);
362 } catch (IllegalArgumentException e
) {// no such workspace
363 Session adminSession
= NodeUtils
.openDataAdminSession(deployedNodeRepository
, null);
365 adminSession
.getWorkspace().createWorkspace(workspaceName
);
367 Jcr
.logout(adminSession
);
369 targetSession
= NodeUtils
.openDataAdminSession(deployedNodeRepository
, workspaceName
);
371 sourceSession
= initRepository
.login(workspaceName
);
372 // JcrUtils.copyWorkspaceXml(sourceSession, targetSession);
373 // TODO deal with referenceable nodes
374 JcrUtils
.copy(sourceSession
.getRootNode(), targetSession
.getRootNode());
375 targetSession
.save();
376 long duration
= System
.currentTimeMillis() - begin
;
377 if (log
.isDebugEnabled())
378 log
.debug("Copied workspace " + workspaceName
+ " from init repository in " + (duration
/ 1000)
380 } catch (Exception e
) {
381 log
.error("Cannot copy workspace " + workspaceName
+ " from init repository.", e
);
383 Jcr
.logout(sourceSession
);
384 Jcr
.logout(targetSession
);
387 } catch (RepositoryException e
) {
388 throw new JcrException(e
);
390 Jcr
.logout(initSession
);
394 private void prepareHomeRepository(RepositoryImpl deployedRepository
) {
395 Session adminSession
= KernelUtils
.openAdminSession(deployedRepository
);
397 argeoDataModelExtensionsAvailable
= Arrays
398 .asList(adminSession
.getWorkspace().getNamespaceRegistry().getURIs())
399 .contains(ArgeoNames
.ARGEO_NAMESPACE
);
400 } catch (RepositoryException e
) {
401 log
.warn("Cannot check whether Argeo namespace is registered assuming it isn't.", e
);
402 argeoDataModelExtensionsAvailable
= false;
404 JcrUtils
.logoutQuietly(adminSession
);
407 // Publish home with the highest service ranking
408 Hashtable
<String
, Object
> regProps
= new Hashtable
<>();
409 regProps
.put(NodeConstants
.CN
, NodeConstants
.EGO_REPOSITORY
);
410 regProps
.put(Constants
.SERVICE_RANKING
, Integer
.MAX_VALUE
);
411 Repository egoRepository
= new EgoRepository(deployedRepository
, false);
412 bc
.registerService(Repository
.class, egoRepository
, regProps
);
413 registerRepositoryServlets(NodeConstants
.EGO_REPOSITORY
, egoRepository
);
415 // Keyring only if Argeo extensions are available
416 if (argeoDataModelExtensionsAvailable
) {
417 new ServiceTracker
<CallbackHandler
, CallbackHandler
>(bc
, CallbackHandler
.class, null) {
420 public CallbackHandler
addingService(ServiceReference
<CallbackHandler
> reference
) {
421 NodeKeyRing nodeKeyring
= new NodeKeyRing(egoRepository
);
422 CallbackHandler callbackHandler
= bc
.getService(reference
);
423 nodeKeyring
.setDefaultCallbackHandler(callbackHandler
);
424 bc
.registerService(LangUtils
.names(Keyring
.class, CryptoKeyring
.class, ManagedService
.class),
425 nodeKeyring
, LangUtils
.dict(Constants
.SERVICE_PID
, NodeConstants
.NODE_KEYRING_PID
));
426 return callbackHandler
;
433 /** Session is logged out. */
434 private void prepareDataModel(String cn
, Repository repository
, List
<String
> publishAsLocalRepo
) {
435 Session adminSession
= KernelUtils
.openAdminSession(repository
);
437 Set
<String
> processed
= new HashSet
<String
>();
438 bundles
: for (Bundle bundle
: bc
.getBundles()) {
439 BundleWiring wiring
= bundle
.adapt(BundleWiring
.class);
442 if (NodeConstants
.NODE_REPOSITORY
.equals(cn
))// process all data models
443 processWiring(cn
, adminSession
, wiring
, processed
, false, publishAsLocalRepo
);
445 List
<BundleCapability
> capabilities
= wiring
.getCapabilities(CMS_DATA_MODEL_NAMESPACE
);
446 for (BundleCapability capability
: capabilities
) {
447 String dataModelName
= (String
) capability
.getAttributes().get(DataModelNamespace
.NAME
);
448 if (dataModelName
.equals(cn
))// process only own data model
449 processWiring(cn
, adminSession
, wiring
, processed
, false, publishAsLocalRepo
);
454 JcrUtils
.logoutQuietly(adminSession
);
458 private void processWiring(String cn
, Session adminSession
, BundleWiring wiring
, Set
<String
> processed
,
459 boolean importListedAbstractModels
, List
<String
> publishAsLocalRepo
) {
460 // recursively process requirements first
461 List
<BundleWire
> requiredWires
= wiring
.getRequiredWires(CMS_DATA_MODEL_NAMESPACE
);
462 for (BundleWire wire
: requiredWires
) {
463 processWiring(cn
, adminSession
, wire
.getProviderWiring(), processed
, true, publishAsLocalRepo
);
466 List
<BundleCapability
> capabilities
= wiring
.getCapabilities(CMS_DATA_MODEL_NAMESPACE
);
467 capabilities
: for (BundleCapability capability
: capabilities
) {
468 if (!importListedAbstractModels
469 && KernelUtils
.asBoolean((String
) capability
.getAttributes().get(DataModelNamespace
.ABSTRACT
))) {
470 continue capabilities
;
472 boolean publish
= registerDataModelCapability(cn
, adminSession
, capability
, processed
);
474 publishAsLocalRepo
.add((String
) capability
.getAttributes().get(DataModelNamespace
.NAME
));
478 private boolean registerDataModelCapability(String cn
, Session adminSession
, BundleCapability capability
,
479 Set
<String
> processed
) {
480 Map
<String
, Object
> attrs
= capability
.getAttributes();
481 String name
= (String
) attrs
.get(DataModelNamespace
.NAME
);
482 if (processed
.contains(name
)) {
483 if (log
.isTraceEnabled())
484 log
.trace("Data model " + name
+ " has already been processed");
489 String path
= (String
) attrs
.get(DataModelNamespace
.CND
);
491 File dataModel
= bc
.getBundle().getDataFile("dataModels/" + path
);
492 if (!dataModel
.exists()) {
493 URL url
= capability
.getRevision().getBundle().getResource(path
);
495 throw new IllegalArgumentException("No data model '" + name
+ "' found under path " + path
);
496 try (Reader reader
= new InputStreamReader(url
.openStream())) {
497 CndImporter
.registerNodeTypes(reader
, adminSession
, true);
499 dataModel
.getParentFile().mkdirs();
500 dataModel
.createNewFile();
501 if (log
.isDebugEnabled())
502 log
.debug("Registered CND " + url
);
503 } catch (Exception e
) {
504 log
.error("Cannot import CND " + url
, e
);
509 if (KernelUtils
.asBoolean((String
) attrs
.get(DataModelNamespace
.ABSTRACT
)))
512 boolean isStandalone
= deployConfig
.isStandalone(name
);
513 boolean publishLocalRepo
;
514 if (isStandalone
&& name
.equals(cn
))// includes the node itself
515 publishLocalRepo
= true;
516 else if (!isStandalone
&& cn
.equals(NodeConstants
.NODE_REPOSITORY
))
517 publishLocalRepo
= true;
519 publishLocalRepo
= false;
521 return publishLocalRepo
;
524 private void publishLocalRepo(String dataModelName
, Repository repository
) {
525 Hashtable
<String
, Object
> properties
= new Hashtable
<>();
526 properties
.put(NodeConstants
.CN
, dataModelName
);
527 LocalRepository localRepository
;
529 if (repository
instanceof RepositoryImpl
) {
530 localRepository
= new JackrabbitLocalRepository((RepositoryImpl
) repository
, dataModelName
);
531 classes
= new String
[] { Repository
.class.getName(), LocalRepository
.class.getName(),
532 JackrabbitLocalRepository
.class.getName() };
534 localRepository
= new LocalRepository(repository
, dataModelName
);
535 classes
= new String
[] { Repository
.class.getName(), LocalRepository
.class.getName() };
537 bc
.registerService(classes
, localRepository
, properties
);
539 // TODO make it configurable
540 registerRepositoryServlets(dataModelName
, localRepository
);
541 if (log
.isTraceEnabled())
542 log
.trace("Published data model " + dataModelName
);
546 public synchronized Long
getAvailableSince() {
547 return availableSince
;
550 public synchronized boolean isAvailable() {
551 return availableSince
!= null;
554 protected void registerRepositoryServlets(String alias
, Repository repository
) {
555 registerRemotingServlet(alias
, repository
);
556 registerWebdavServlet(alias
, repository
);
559 protected void registerWebdavServlet(String alias
, Repository repository
) {
560 CmsWebDavServlet webdavServlet
= new CmsWebDavServlet(alias
, repository
);
561 Hashtable
<String
, String
> ip
= new Hashtable
<>();
562 ip
.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX
+ CmsWebDavServlet
.INIT_PARAM_RESOURCE_CONFIG
, webDavConfig
);
563 ip
.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX
+ CmsWebDavServlet
.INIT_PARAM_RESOURCE_PATH_PREFIX
,
566 ip
.put(HttpWhiteboardConstants
.HTTP_WHITEBOARD_SERVLET_PATTERN
, "/" + alias
+ "/*");
567 ip
.put(HttpWhiteboardConstants
.HTTP_WHITEBOARD_CONTEXT_SELECT
,
568 "(" + HttpWhiteboardConstants
.HTTP_WHITEBOARD_CONTEXT_PATH
+ "=" + NodeConstants
.PATH_DATA
+ ")");
569 bc
.registerService(Servlet
.class, webdavServlet
, ip
);
572 protected void registerRemotingServlet(String alias
, Repository repository
) {
573 CmsRemotingServlet remotingServlet
= new CmsRemotingServlet(alias
, repository
);
574 Hashtable
<String
, String
> ip
= new Hashtable
<>();
575 ip
.put(NodeConstants
.CN
, alias
);
576 // Properties ip = new Properties();
577 ip
.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX
+ CmsRemotingServlet
.INIT_PARAM_RESOURCE_PATH_PREFIX
,
579 ip
.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX
+ CmsRemotingServlet
.INIT_PARAM_AUTHENTICATE_HEADER
,
582 // Looks like a bug in Jackrabbit remoting init
585 tmpDir
= Files
.createTempDirectory("remoting_" + alias
);
586 } catch (IOException e
) {
587 throw new RuntimeException("Cannot create temp directory for remoting servlet", e
);
589 ip
.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX
+ CmsRemotingServlet
.INIT_PARAM_HOME
, tmpDir
.toString());
590 ip
.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX
+ CmsRemotingServlet
.INIT_PARAM_TMP_DIRECTORY
,
591 "remoting_" + alias
);
592 ip
.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX
+ CmsRemotingServlet
.INIT_PARAM_PROTECTED_HANDLERS_CONFIG
,
593 HttpUtils
.DEFAULT_PROTECTED_HANDLERS
);
594 ip
.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX
+ CmsRemotingServlet
.INIT_PARAM_CREATE_ABSOLUTE_URI
, "false");
596 ip
.put(HttpWhiteboardConstants
.HTTP_WHITEBOARD_SERVLET_PATTERN
, "/" + alias
+ "/*");
597 ip
.put(HttpWhiteboardConstants
.HTTP_WHITEBOARD_CONTEXT_SELECT
,
598 "(" + HttpWhiteboardConstants
.HTTP_WHITEBOARD_CONTEXT_PATH
+ "=" + NodeConstants
.PATH_JCR
+ ")");
599 bc
.registerService(Servlet
.class, remotingServlet
, ip
);
602 private class RepositoryContextStc
extends ServiceTracker
<RepositoryContext
, RepositoryContext
> {
604 public RepositoryContextStc() {
605 super(bc
, RepositoryContext
.class, null);
609 public RepositoryContext
addingService(ServiceReference
<RepositoryContext
> reference
) {
610 RepositoryContext repoContext
= bc
.getService(reference
);
611 String cn
= (String
) reference
.getProperty(NodeConstants
.CN
);
613 List
<String
> publishAsLocalRepo
= new ArrayList
<>();
614 if (cn
.equals(NodeConstants
.NODE_REPOSITORY
)) {
615 // JackrabbitDataModelMigration.clearRepositoryCaches(repoContext.getRepositoryConfig());
616 prepareNodeRepository(repoContext
.getRepository(), publishAsLocalRepo
);
617 // TODO separate home repository
618 prepareHomeRepository(repoContext
.getRepository());
619 registerRepositoryServlets(cn
, repoContext
.getRepository());
620 nodeAvailable
= true;
623 prepareDataModel(cn
, repoContext
.getRepository(), publishAsLocalRepo
);
625 // Publish all at once, so that bundles with multiple CNDs are consistent
626 for (String dataModelName
: publishAsLocalRepo
)
627 publishLocalRepo(dataModelName
, repoContext
.getRepository());
633 public void modifiedService(ServiceReference
<RepositoryContext
> reference
, RepositoryContext service
) {
637 public void removedService(ServiceReference
<RepositoryContext
> reference
, RepositoryContext service
) {