/*
* FACTORY PIDs
*/
- String JACKRABBIT_FACTORY_PID = "org.argeo.jackrabbit.config";
+ String NODE_REPOS_FACTORY_PID = "org.argeo.node.repos";
+
+ /*
+ * DEPLOY
+ */
+ String DEPLOY_BASEDN = "ou=deploy,ou=node";
+// String DEPLOY_SERVICES_BASEDN = "ou=services," + DEPLOY_BASEDN;
+// String DEPLOY_SERVICE_FACTORIES_BASEDN = "ou=serviceFactories," + DEPLOY_BASEDN;
/*
* FRAMEWORK PROPERTIES
* STANDARD ATTRIBUTES
*/
String CN = "cn";
+ String OU = "ou";
String LABELED_URI = "labeledUri";
}
List<Locale> getLocales();
String getHostname();
+
+ boolean isClean();
}
import org.argeo.cms.CmsException;
import org.argeo.node.ArgeoLogger;
import org.argeo.node.NodeConstants;
+import org.argeo.node.NodeDeployment;
import org.argeo.node.NodeState;
-import org.argeo.node.RepoConf;
import org.argeo.util.LangUtils;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
private NodeLogger logger;
private CmsState nodeState;
+ private CmsDeployment nodeDeployment;
@Override
public void start(BundleContext bundleContext) throws Exception {
if (props == null) {
if (log.isDebugEnabled())
log.debug("Clean node state");
- Dictionary<String, Object> envProps = getStatePropertiesFromEnvironment();
+ Dictionary<String, Object> envProps = new Hashtable<>();
// Use the UUID of the first framework run as state UUID
cn = bc.getProperty(Constants.FRAMEWORK_UUID);
envProps.put(NodeConstants.CN, cn);
nodeConf.update(envProps);
} else {
// Check if state is in line with environment
- Dictionary<String, Object> envProps = getStatePropertiesFromEnvironment();
- for (String key : LangUtils.keys(envProps)) {
- Object envValue = envProps.get(key);
- Object storedValue = props.get(key);
- if (storedValue == null)
- throw new CmsException("No state value for env " + key + "=" + envValue
- + ", please clean the OSGi configuration.");
- if (!storedValue.equals(envValue))
- throw new CmsException("State value for " + key + "=" + storedValue
- + " is different from env value =" + envValue + ", please clean the OSGi configuration.");
- }
+ // Dictionary<String, Object> envProps = new Hashtable<>();
+ // for (String key : LangUtils.keys(envProps)) {
+ // Object envValue = envProps.get(key);
+ // Object storedValue = props.get(key);
+ // if (storedValue == null)
+ // throw new CmsException("No state value for env " + key + "=" +
+ // envValue
+ // + ", please clean the OSGi configuration.");
+ // if (!storedValue.equals(envValue))
+ // throw new CmsException("State value for " + key + "=" +
+ // storedValue
+ // + " is different from env value =" + envValue + ", please clean
+ // the OSGi configuration.");
+ // }
cn = props.get(NodeConstants.CN);
if (cn == null)
throw new CmsException("No state UUID available");
regProps.put(NodeConstants.CN, cn);
bc.registerService(LangUtils.names(NodeState.class, ManagedService.class), nodeState, regProps);
+ try {
+ nodeDeployment = new CmsDeployment();
+ bc.registerService(LangUtils.names(NodeDeployment.class), nodeDeployment, null);
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ throw e;
+ }
}
@Override
return bc.getService(sr);
}
- protected Dictionary<String, Object> getStatePropertiesFromEnvironment() {
- Hashtable<String, Object> props = new Hashtable<>();
- // i18n
- copyFrameworkProp(NodeConstants.I18N_DEFAULT_LOCALE, props);
- copyFrameworkProp(NodeConstants.I18N_LOCALES, props);
- // user admin
- copyFrameworkProp(NodeConstants.ROLES_URI, props);
- copyFrameworkProp(NodeConstants.USERADMIN_URIS, props);
- // data
- for (RepoConf repoConf : RepoConf.values())
- copyFrameworkProp(NodeConstants.NODE_REPO_PROP_PREFIX + repoConf.name(), props);
- // TODO add other environment sources
- return props;
- }
-
- private void copyFrameworkProp(String key, Dictionary<String, Object> props) {
- String value = bc.getProperty(key);
- if (value != null)
- props.put(key, value);
- }
-
public static NodeState getNodeState() {
return instance.nodeState;
}
import static org.argeo.node.DataModelNamespace.CMS_DATA_MODEL_NAMESPACE;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
+import java.io.Writer;
import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
import javax.jcr.Repository;
import javax.jcr.Session;
+import javax.naming.InvalidNameException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jackrabbit.commons.cnd.CndImporter;
+import org.apache.jackrabbit.core.RepositoryContext;
import org.argeo.cms.CmsException;
import org.argeo.jcr.ArgeoJcrConstants;
import org.argeo.jcr.JcrUtils;
import org.argeo.node.DataModelNamespace;
+import org.argeo.node.NodeConstants;
import org.argeo.node.NodeDeployment;
+import org.argeo.node.NodeState;
+import org.argeo.util.naming.AttributesDictionary;
+import org.argeo.util.naming.LdifParser;
+import org.argeo.util.naming.LdifWriter;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedService;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationEvent;
+import org.osgi.service.cm.SynchronousConfigurationListener;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
-public class CmsDeployment implements NodeDeployment, ManagedService {
+public class CmsDeployment implements NodeDeployment, SynchronousConfigurationListener {
private final Log log = LogFactory.getLog(getClass());
private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext();
- private Repository deployedNodeRepository;
+ private Path deployPath = KernelUtils.getOsgiInstancePath(KernelConstants.DEPLOY_PATH);
+ private SortedMap<LdapName, Attributes> deployConfigs = new TreeMap<>();
+
+ // private Repository deployedNodeRepository;
private HomeRepository homeRepository;
private Long availableSince;
+ public CmsDeployment() {
+ ConfigurationAdmin configurationAdmin = bc.getService(bc.getServiceReference(ConfigurationAdmin.class));
+ // FIXME no guarantee this is already available
+ NodeState nodeState = bc.getService(bc.getServiceReference(NodeState.class));
+ try {
+ initDeployConfigs(configurationAdmin, nodeState);
+ } catch (IOException e) {
+ throw new CmsException("Could not init deploy configs", e);
+ }
+ bc.registerService(SynchronousConfigurationListener.class, this, null);
+
+ new ServiceTracker<>(bc, RepositoryContext.class, new RepositoryContextStc()).open();
+ }
+
+ private void initDeployConfigs(ConfigurationAdmin configurationAdmin, NodeState nodeState) throws IOException {
+ if (!Files.exists(deployPath)) {// first init
+ Files.createDirectories(deployPath.getParent());
+ Files.createFile(deployPath);
+ FirstInitProperties firstInitProperties = new FirstInitProperties();
+
+ Dictionary<String, Object> nodeConfig = firstInitProperties.getNodeRepositoryConfig();
+ // node repository is mandatory
+ putFactoryDeployConfig(NodeConstants.NODE_REPOS_FACTORY_PID, nodeConfig);
+
+ Dictionary<String, Object> webServerConfig = firstInitProperties.getHttpServerConfig();
+ if (!webServerConfig.isEmpty())
+ putFactoryDeployConfig(KernelConstants.JETTY_FACTORY_PID, webServerConfig);
+
+ saveDeployedConfigs();
+ }
+
+ try (InputStream in = Files.newInputStream(deployPath)) {
+ deployConfigs = new LdifParser().read(in);
+ }
+ if (nodeState.isClean()) {
+ for (LdapName dn : deployConfigs.keySet()) {
+ Rdn lastRdn = dn.getRdn(dn.size() - 1);
+ LdapName prefix = (LdapName) dn.getPrefix(dn.size() - 1);
+ if (prefix.toString().equals(NodeConstants.DEPLOY_BASEDN)) {
+ if (lastRdn.getType().equals(NodeConstants.CN)) {
+ // service
+ String pid = lastRdn.getValue().toString();
+ Configuration conf = configurationAdmin.getConfiguration(pid);
+ AttributesDictionary dico = new AttributesDictionary(deployConfigs.get(dn));
+ conf.update(dico);
+ } else {
+ // service factory definition
+ }
+ } else {
+ // service factory service
+ Rdn beforeLastRdn = dn.getRdn(dn.size() - 2);
+ assert beforeLastRdn.getType().equals(NodeConstants.OU);
+ String factoryPid = beforeLastRdn.getValue().toString();
+ Configuration conf = configurationAdmin.createFactoryConfiguration(factoryPid.toString(), null);
+ AttributesDictionary dico = new AttributesDictionary(deployConfigs.get(dn));
+ conf.update(dico);
+ }
+ }
+ }
+ // TODO check consistency if not clean
+ }
+
@Override
- public void updated(Dictionary<String, ?> properties) throws ConfigurationException {
- if (properties == null)
- return;
+ public void configurationEvent(ConfigurationEvent event) {
+ try {
+ if (ConfigurationEvent.CM_UPDATED == event.getType()) {
+ ConfigurationAdmin configurationAdmin = bc.getService(event.getReference());
+ Configuration conf = configurationAdmin.getConfiguration(event.getPid(), null);
+ LdapName serviceDn = null;
+ String factoryPid = conf.getFactoryPid();
+ if (factoryPid != null) {
+ LdapName serviceFactoryDn = serviceFactoryDn(factoryPid);
+ if (deployConfigs.containsKey(serviceFactoryDn)) {
+ for (LdapName dn : deployConfigs.keySet()) {
+ if (dn.startsWith(serviceFactoryDn)) {
+ Rdn lastRdn = dn.getRdn(dn.size() - 1);
+ assert lastRdn.getType().equals(NodeConstants.CN);
+ Object value = conf.getProperties().get(lastRdn.getType());
+ assert value != null;
+ if (value.equals(lastRdn.getValue())) {
+ serviceDn = dn;
+ break;
+ }
+ }
+ }
- if (deployedNodeRepository != null) {
- if (availableSince != null) {
- throw new CmsException("Deployment is already available");
+ Object cn = conf.getProperties().get(NodeConstants.CN);
+ if (cn == null)
+ throw new IllegalArgumentException("Properties must contain cn");
+ if (serviceDn == null) {
+ putFactoryDeployConfig(factoryPid, conf.getProperties());
+ } else {
+ Attributes attrs = deployConfigs.get(serviceDn);
+ assert attrs != null;
+ AttributesDictionary.copy(conf.getProperties(), attrs);
+ }
+ saveDeployedConfigs();
+ if (log.isDebugEnabled())
+ log.debug("Updated deploy config " + serviceDn(factoryPid, cn.toString()));
+ } else {
+ // ignore non config-registered service factories
+ }
+ } else {
+ serviceDn = serviceDn(event.getPid());
+ if (deployConfigs.containsKey(serviceDn)) {
+ Attributes attrs = deployConfigs.get(serviceDn);
+ assert attrs != null;
+ AttributesDictionary.copy(conf.getProperties(), attrs);
+ saveDeployedConfigs();
+ if (log.isDebugEnabled())
+ log.debug("Updated deploy config " + serviceDn);
+ } else {
+ // ignore non config-registered services
+ }
+ }
}
+ } catch (Exception e) {
+ log.error("Could not handle configuration event", e);
+ }
+ }
+
+ private void putFactoryDeployConfig(String factoryPid, Dictionary<String, Object> props) {
+ Object cn = props.get(NodeConstants.CN);
+ if (cn == null)
+ throw new IllegalArgumentException("cn must be set in properties");
+ LdapName serviceFactorydn = serviceFactoryDn(factoryPid);
+ if (!deployConfigs.containsKey(serviceFactorydn))
+ deployConfigs.put(serviceFactorydn, new BasicAttributes(NodeConstants.OU, factoryPid));
+ LdapName serviceDn = serviceDn(factoryPid, cn.toString());
+ Attributes attrs = new BasicAttributes();
+ AttributesDictionary.copy(props, attrs);
+ deployConfigs.put(serviceDn, attrs);
+ }
+
+ private void putDeployConfig(String servicePid, Dictionary<String, Object> props) {
+ LdapName serviceDn = serviceDn(servicePid);
+ Attributes attrs = new BasicAttributes(NodeConstants.CN, servicePid);
+ AttributesDictionary.copy(props, attrs);
+ deployConfigs.put(serviceDn, attrs);
+ }
- availableSince = System.currentTimeMillis();
+ void saveDeployedConfigs() throws IOException {
+ try (Writer writer = Files.newBufferedWriter(deployPath)) {
+ new LdifWriter(writer).write(deployConfigs);
+ }
+ }
- prepareDataModel(KernelUtils.openAdminSession(deployedNodeRepository));
- Hashtable<String, String> regProps = new Hashtable<String, String>();
- regProps.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, ArgeoJcrConstants.ALIAS_HOME);
- homeRepository = new HomeRepository(deployedNodeRepository);
- // register
- bc.registerService(Repository.class, homeRepository, regProps);
+ private LdapName serviceFactoryDn(String factoryPid) {
+ try {
+ return new LdapName(NodeConstants.OU + "=" + factoryPid + "," + NodeConstants.DEPLOY_BASEDN);
+ } catch (InvalidNameException e) {
+ throw new IllegalArgumentException("Cannot generate DN from " + factoryPid, e);
+ }
+ }
+
+ private LdapName serviceDn(String servicePid) {
+ try {
+ return new LdapName(NodeConstants.CN + "=" + servicePid + "," + NodeConstants.DEPLOY_BASEDN);
+ } catch (InvalidNameException e) {
+ throw new IllegalArgumentException("Cannot generate DN from " + servicePid, e);
+ }
+ }
- } else {
- throw new CmsException("No node repository available");
+ private LdapName serviceDn(String factoryPid, String cn) {
+ try {
+ return (LdapName) serviceFactoryDn(factoryPid).add(new Rdn(NodeConstants.CN, cn));
+ } catch (InvalidNameException e) {
+ throw new IllegalArgumentException("Cannot generate DN from " + factoryPid + " and " + cn, e);
}
}
+ private void prepareNodeRepository(Repository deployedNodeRepository) {
+ if (availableSince != null) {
+ throw new CmsException("Deployment is already available");
+ }
+
+ availableSince = System.currentTimeMillis();
+
+ prepareDataModel(KernelUtils.openAdminSession(deployedNodeRepository));
+ Hashtable<String, String> regProps = new Hashtable<String, String>();
+ regProps.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, ArgeoJcrConstants.ALIAS_HOME);
+ homeRepository = new HomeRepository(deployedNodeRepository);
+ // register
+ bc.registerService(Repository.class, homeRepository, regProps);
+ }
+
/** Session is logged out. */
private void prepareDataModel(Session adminSession) {
try {
log.debug("Published data model " + name);
}
- public void setDeployedNodeRepository(Repository deployedNodeRepository) {
- this.deployedNodeRepository = deployedNodeRepository;
- }
+ // public void setDeployedNodeRepository(Repository deployedNodeRepository)
+ // {
+ // this.deployedNodeRepository = deployedNodeRepository;
+ // }
@Override
public long getAvailableSince() {
return availableSince;
}
+ private class RepositoryContextStc implements ServiceTrackerCustomizer<RepositoryContext, RepositoryContext> {
+
+ @Override
+ public RepositoryContext addingService(ServiceReference<RepositoryContext> reference) {
+ RepositoryContext nodeRepo = bc.getService(reference);
+ Object cn = reference.getProperty(NodeConstants.CN);
+ if (cn != null && cn.equals(ArgeoJcrConstants.ALIAS_NODE)) {
+ prepareNodeRepository(nodeRepo.getRepository());
+ // nodeDeployment.setDeployedNodeRepository(nodeRepo.getRepository());
+ // Dictionary<String, Object> props =
+ // LangUtils.init(Constants.SERVICE_PID,
+ // NodeConstants.NODE_DEPLOYMENT_PID);
+ // props.put(NodeConstants.CN,
+ // nodeRepo.getRootNodeId().toString());
+ // register
+ // bc.registerService(LangUtils.names(NodeDeployment.class,
+ // ManagedService.class), nodeDeployment, props);
+ }
+
+ return nodeRepo;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<RepositoryContext> reference, RepositoryContext service) {
+ }
+
+ @Override
+ public void removedService(ServiceReference<RepositoryContext> reference, RepositoryContext service) {
+ }
+
+ }
+
}
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
-import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
+import java.util.SortedMap;
import java.util.UUID;
import javax.jcr.RepositoryFactory;
+import javax.naming.InvalidNameException;
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
import javax.transaction.TransactionManager;
import javax.transaction.TransactionSynchronizationRegistry;
import javax.transaction.UserTransaction;
import org.argeo.node.NodeState;
import org.argeo.node.RepoConf;
import org.argeo.util.LangUtils;
+import org.argeo.util.naming.AttributesDictionary;
+import org.argeo.util.naming.LdifParser;
import org.eclipse.equinox.http.jetty.JettyConfigurator;
import org.eclipse.equinox.http.jetty.JettyConstants;
import org.eclipse.rap.rwt.application.ApplicationConfiguration;
// private RepositoryService repositoryService;
// Deployment
- private final CmsDeployment nodeDeployment = new CmsDeployment();
+ // private final CmsDeployment nodeDeployment = new CmsDeployment();
private boolean cleanState = false;
private URI nodeRepoUri = null;
@Override
public void updated(Dictionary<String, ?> properties) throws ConfigurationException {
if (properties == null) {
- // TODO this should not happen anymore
- this.cleanState = true;
- if (log.isTraceEnabled())
- log.trace("Clean state");
+ // // TODO this should not happen anymore
+ // this.cleanState = true;
+ // if (log.isTraceEnabled())
+ // log.trace("Clean state");
return;
}
String stateUuid = properties.get(NodeConstants.CN).toString();
nodeRepoUri = KernelUtils.getOsgiInstanceUri("repos/node");
- initI18n(properties);
+ initI18n();
initServices();
- initDeployConfigs(properties);
- initWebServer();
- initNodeDeployment();
+// initDeployConfigs();
+ // initWebServer();
+ // initNodeDeployment();
// kernel thread
kernelThread = new KernelThread(threadGroup, "Kernel Thread");
}
}
- private void initI18n(Dictionary<String, ?> stateProps) {
- Object defaultLocaleValue = stateProps.get(NodeConstants.I18N_DEFAULT_LOCALE);
+ private void initI18n() {
+ Object defaultLocaleValue = KernelUtils.getFrameworkProp(NodeConstants.I18N_DEFAULT_LOCALE);
defaultLocale = defaultLocaleValue != null ? new Locale(defaultLocaleValue.toString())
: new Locale(ENGLISH.getLanguage());
- locales = asLocaleList(stateProps.get(NodeConstants.I18N_LOCALES));
+ locales = asLocaleList(KernelUtils.getFrameworkProp(NodeConstants.I18N_LOCALES));
}
private void initServices() {
// trackers
new ServiceTracker<HttpService, HttpService>(bc, HttpService.class, new PrepareHttpStc()).open();
- new ServiceTracker<>(bc, RepositoryContext.class, new RepositoryContextStc()).open();
initTransactionManager();
RepositoryServiceFactory repositoryServiceFactory = new RepositoryServiceFactory();
shutdownHooks.add(() -> repositoryServiceFactory.shutdown());
bc.registerService(ManagedServiceFactory.class, repositoryServiceFactory,
- LangUtils.init(Constants.SERVICE_PID, NodeConstants.JACKRABBIT_FACTORY_PID));
+ LangUtils.init(Constants.SERVICE_PID, NodeConstants.NODE_REPOS_FACTORY_PID));
NodeRepositoryFactory repositoryFactory = new NodeRepositoryFactory();
bc.registerService(RepositoryFactory.class, repositoryFactory, null);
- RepositoryService repositoryService = new RepositoryService();
- shutdownHooks.add(() -> repositoryService.shutdown());
- bc.registerService(LangUtils.names(ManagedService.class, MetaTypeProvider.class), repositoryService,
- LangUtils.init(Constants.SERVICE_PID, NodeConstants.NODE_REPO_PID));
+ // RepositoryService repositoryService = new RepositoryService();
+ // shutdownHooks.add(() -> repositoryService.shutdown());
+ // bc.registerService(LangUtils.names(ManagedService.class,
+ // MetaTypeProvider.class), repositoryService,
+ // LangUtils.init(Constants.SERVICE_PID, NodeConstants.NODE_REPO_PID));
// Security
NodeUserAdmin userAdmin = new NodeUserAdmin();
// LangUtils.init(PROPERTY_CONTEXT_NAME, "user"));
// }
- private void initDeployConfigs(Dictionary<String, ?> stateProps) throws IOException {
- Path deployPath = KernelUtils.getOsgiInstancePath(KernelConstants.DIR_NODE + '/' + KernelConstants.DIR_DEPLOY);
- Files.createDirectories(deployPath);
-
- Path nodeConfigPath = deployPath.resolve(NodeConstants.NODE_REPO_PID + ".properties");
- if (!Files.exists(nodeConfigPath)) {
- Dictionary<String, Object> nodeConfig = getNodeConfig(stateProps);
- nodeConfig.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, ArgeoJcrConstants.ALIAS_NODE);
- nodeConfig.put(RepoConf.labeledUri.name(), nodeRepoUri.toString());
- LangUtils.storeAsProperties(nodeConfig, nodeConfigPath);
- }
-
- if (cleanState) {
- try (DirectoryStream<Path> ds = Files.newDirectoryStream(deployPath)) {
- for (Path path : ds) {
- if (Files.isDirectory(path)) {// managed factories
- try (DirectoryStream<Path> factoryDs = Files.newDirectoryStream(path)) {
- for (Path confPath : factoryDs) {
- Configuration conf = configurationAdmin
- .createFactoryConfiguration(path.getFileName().toString());
- Dictionary<String, Object> props = LangUtils.loadFromProperties(confPath);
- conf.update(props);
- }
- }
- } else {// managed services
- String pid = path.getFileName().toString();
- pid = pid.substring(0, pid.length() - ".properties".length());
- Configuration conf = configurationAdmin.getConfiguration(pid);
- Dictionary<String, Object> props = LangUtils.loadFromProperties(path);
- conf.update(props);
- }
- }
- }
- }
- }
-
// private void initRepositories(Dictionary<String, ?> stateProps) throws
// IOException {
// // register
// MetaTypeProvider.class), repositoryService, regProps);
// }
- private void initWebServer() {
- String httpPort = getFrameworkProp("org.osgi.service.http.port");
- String httpsPort = getFrameworkProp("org.osgi.service.http.port.secure");
- /// TODO make it more generic
- String httpHost = getFrameworkProp("org.eclipse.equinox.http.jetty.http.host");
- try {
- if (httpPort != null || httpsPort != null) {
- final Hashtable<String, Object> jettyProps = new Hashtable<String, Object>();
- if (httpPort != null) {
- jettyProps.put(JettyConstants.HTTP_PORT, httpPort);
- jettyProps.put(JettyConstants.HTTP_ENABLED, true);
- }
- if (httpsPort != null) {
- jettyProps.put(JettyConstants.HTTPS_PORT, httpsPort);
- jettyProps.put(JettyConstants.HTTPS_ENABLED, true);
- jettyProps.put(JettyConstants.SSL_KEYSTORETYPE, "PKCS12");
- // jettyProps.put(JettyConstants.SSL_KEYSTORE,
- // nodeSecurity.getHttpServerKeyStore().getCanonicalPath());
- jettyProps.put(JettyConstants.SSL_PASSWORD, "changeit");
- jettyProps.put(JettyConstants.SSL_WANTCLIENTAUTH, true);
- }
- if(httpHost!=null){
- jettyProps.put(JettyConstants.HTTP_HOST, httpHost);
- }
- if (configurationAdmin != null) {
- // TODO make filter more generic
- String filter = "(" + JettyConstants.HTTP_PORT + "=" + httpPort + ")";
- if (configurationAdmin.listConfigurations(filter) != null)
- return;
- Configuration jettyConf = configurationAdmin
- .createFactoryConfiguration(KernelConstants.JETTY_FACTORY_PID, null);
- jettyConf.update(jettyProps);
-
- } else {
- JettyConfigurator.startServer("default", jettyProps);
- }
- }
- } catch (Exception e) {
- throw new CmsException("Cannot initialize web server on " + httpPortsMsg(httpPort, httpsPort), e);
- }
- }
-
- private void initNodeDeployment() throws IOException {
- Configuration nodeDeploymentConf = configurationAdmin.getConfiguration(NodeConstants.NODE_DEPLOYMENT_PID);
- nodeDeploymentConf.update(new Hashtable<>());
- }
+ // private void initNodeDeployment() throws IOException {
+ // Configuration nodeDeploymentConf =
+ // configurationAdmin.getConfiguration(NodeConstants.NODE_DEPLOYMENT_PID);
+ // nodeDeploymentConf.update(new Hashtable<>());
+ // }
void shutdown() {
// if (transactionManager != null)
new GogoShellKiller().start();
}
- private Dictionary<String, Object> getNodeConfig(Dictionary<String, ?> properties) {
- // Object repoType = properties.get(NodeConstants.NODE_REPO_PROP_PREFIX
- // + RepoConf.type.name());
- // if (repoType == null)
- // return null;
-
- Hashtable<String, Object> props = new Hashtable<String, Object>();
- for (RepoConf repoConf : RepoConf.values()) {
- Object value = properties.get(NodeConstants.NODE_REPO_PROP_PREFIX + repoConf.name());
- if (value != null)
- props.put(repoConf.name(), value);
- }
- return props;
- }
-
- private class RepositoryContextStc implements ServiceTrackerCustomizer<RepositoryContext, RepositoryContext> {
-
- @Override
- public RepositoryContext addingService(ServiceReference<RepositoryContext> reference) {
- RepositoryContext nodeRepo = bc.getService(reference);
- Object repoUri = reference.getProperty(ArgeoJcrConstants.JCR_REPOSITORY_URI);
- if (repoUri != null && repoUri.equals(nodeRepoUri.toString())) {
- nodeDeployment.setDeployedNodeRepository(nodeRepo.getRepository());
- Dictionary<String, Object> props = LangUtils.init(Constants.SERVICE_PID,
- NodeConstants.NODE_DEPLOYMENT_PID);
- props.put(NodeConstants.CN, nodeRepo.getRootNodeId().toString());
- // register
- bc.registerService(LangUtils.names(NodeDeployment.class, ManagedService.class), nodeDeployment, props);
- }
-
- return nodeRepo;
- }
-
- @Override
- public void modifiedService(ServiceReference<RepositoryContext> reference, RepositoryContext service) {
- }
-
- @Override
- public void removedService(ServiceReference<RepositoryContext> reference, RepositoryContext service) {
- }
-
- }
-
private class PrepareHttpStc implements ServiceTrackerCustomizer<HttpService, HttpService> {
private DataHttp dataHttp;
private NodeHttp nodeHttp;
}
+ @Override
+ public boolean isClean() {
+ return cleanState;
+ }
+
/*
* ACCESSORS
*/
--- /dev/null
+package org.argeo.cms.internal.kernel;
+
+import static org.argeo.cms.internal.kernel.KernelUtils.getFrameworkProp;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.node.NodeConstants;
+import org.argeo.node.RepoConf;
+import org.eclipse.equinox.http.jetty.JettyConstants;
+
+/**
+ * Interprets framework properties in order to generate the initial deploy
+ * configuration.
+ */
+class FirstInitProperties {
+ Dictionary<String, Object> getNodeRepositoryConfig() {
+ Hashtable<String, Object> props = new Hashtable<String, Object>();
+ for (RepoConf repoConf : RepoConf.values()) {
+ Object value = getFrameworkProp(NodeConstants.NODE_REPO_PROP_PREFIX + repoConf.name());
+ if (value != null)
+ props.put(repoConf.name(), value);
+ }
+ props.put(NodeConstants.CN, ArgeoJcrConstants.ALIAS_NODE);
+ props.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, ArgeoJcrConstants.ALIAS_NODE);
+ return props;
+ }
+
+ Dictionary<String, Object> getHttpServerConfig() {
+ String httpPort = getFrameworkProp("org.osgi.service.http.port");
+ String httpsPort = getFrameworkProp("org.osgi.service.http.port.secure");
+ /// TODO make it more generic
+ String httpHost = getFrameworkProp("org.eclipse.equinox.http.jetty.http.host");
+
+ final Hashtable<String, Object> props = new Hashtable<String, Object>();
+ // try {
+ if (httpPort != null || httpsPort != null) {
+ if (httpPort != null) {
+ props.put(JettyConstants.HTTP_PORT, httpPort);
+ props.put(JettyConstants.HTTP_ENABLED, true);
+ }
+ if (httpsPort != null) {
+ props.put(JettyConstants.HTTPS_PORT, httpsPort);
+ props.put(JettyConstants.HTTPS_ENABLED, true);
+ props.put(JettyConstants.SSL_KEYSTORETYPE, "PKCS12");
+ // jettyProps.put(JettyConstants.SSL_KEYSTORE,
+ // nodeSecurity.getHttpServerKeyStore().getCanonicalPath());
+ props.put(JettyConstants.SSL_PASSWORD, "changeit");
+ props.put(JettyConstants.SSL_WANTCLIENTAUTH, true);
+ }
+ if (httpHost != null) {
+ props.put(JettyConstants.HTTP_HOST, httpHost);
+ }
+ props.put(NodeConstants.CN, "default");
+ }
+ return props;
+ }
+}
package org.argeo.cms.internal.kernel;
+import org.argeo.node.NodeConstants;
+
public interface KernelConstants {
// Directories
final static String DIR_NODE = "node";
- final static String DIR_DEPLOY = "deploy";
+ final static String DIR_REPOS = "repos";
+// final static String DIR_DEPLOY = "deploy";
final static String DIR_TRANSACTIONS = "transactions";
final static String DIR_PKI = "pki";
final static String DIR_PKI_PRIVATE = DIR_PKI + "/private";
+ // Files
+ String DEPLOY_PATH = KernelConstants.DIR_NODE + '/' + NodeConstants.DEPLOY_BASEDN + ".ldif";
+
// Security
final static String DEFAULT_SECURITY_KEY = "argeo";
final static String JAAS_CONFIG = "/org/argeo/cms/internal/kernel/jaas.cfg";
import org.argeo.cms.CmsException;
import org.argeo.jcr.ArgeoJcrConstants;
import org.argeo.jcr.ArgeoJcrException;
+import org.argeo.node.NodeConstants;
import org.argeo.node.RepoConf;
import org.osgi.framework.Constants;
import org.osgi.service.cm.ConfigurationAdmin;
private Properties getConfigurationProperties(JackrabbitType type, Dictionary<String, ?> properties) {
Properties props = new Properties();
- keys: for (Enumeration<String> keys = properties.keys(); keys.hasMoreElements();) {
+ for (Enumeration<String> keys = properties.keys(); keys.hasMoreElements();) {
String key = keys.nextElement();
- if (key.equals(ConfigurationAdmin.SERVICE_FACTORYPID) || key.equals(Constants.SERVICE_PID)
- || key.equals(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS))
- continue keys;
- String value = prop(properties, RepoConf.valueOf(key));
- if (value != null)
- props.put(key, value);
+ // if (key.equals(ConfigurationAdmin.SERVICE_FACTORYPID) ||
+ // key.equals(Constants.SERVICE_PID)
+ // || key.equals(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS))
+ // continue keys;
+ // try {
+ // String value = prop(properties, RepoConf.valueOf(key));
+ // if (value != null)
+ props.put(key, properties.get(key));
+ // } catch (IllegalArgumentException e) {
+ // // ignore non RepoConf
+ // // FIXME make it more flexible/extensible
+ // }
}
// home
String homeUri = props.getProperty(RepoConf.labeledUri.name());
Path homePath;
- try {
- homePath = Paths.get(new URI(homeUri)).toAbsolutePath();
- } catch (URISyntaxException e) {
- throw new CmsException("Invalid repository home URI", e);
+ if (homeUri == null) {
+ String cn = props.getProperty(NodeConstants.CN);
+ assert cn != null;
+ homePath = KernelUtils.getOsgiInstancePath(KernelConstants.DIR_REPOS + '/' + cn);
+ } else {
+ try {
+ homePath = Paths.get(new URI(homeUri)).toAbsolutePath();
+ } catch (URISyntaxException e) {
+ throw new CmsException("Invalid repository home URI", e);
+ }
}
Path rootUuidPath = homePath.resolve("repository/meta/rootUUID");
if (!Files.exists(rootUuidPath)) {
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.jackrabbit.api.JackrabbitRepository;
import org.apache.jackrabbit.core.RepositoryContext;
import org.argeo.ArgeoException;
import org.argeo.jcr.ArgeoJcrConstants;
-import org.argeo.node.RepoConf;
+import org.argeo.node.NodeConstants;
import org.argeo.util.LangUtils;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
private final BundleContext bc = FrameworkUtil.getBundle(RepositoryServiceFactory.class).getBundleContext();
private Map<String, RepositoryContext> repositories = new HashMap<String, RepositoryContext>();
+ private Map<String, Object> pidToCn = new HashMap<String, Object>();
@Override
public String getName() {
RepositoryContext repositoryContext = repositoryBuilder.createRepositoryContext(properties);
repositories.put(pid, repositoryContext);
Dictionary<String, Object> props = LangUtils.init(Constants.SERVICE_PID, pid);
- props.put(ArgeoJcrConstants.JCR_REPOSITORY_URI, properties.get(RepoConf.labeledUri.name()));
- bc.registerService(JackrabbitRepository.class, repositoryContext.getRepository(), props);
+ // props.put(ArgeoJcrConstants.JCR_REPOSITORY_URI,
+ // properties.get(RepoConf.labeledUri.name()));
+ Object cn = properties.get(NodeConstants.CN);
+ if (cn != null) {
+ props.put(NodeConstants.CN, cn);
+ props.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, cn);
+ pidToCn.put(pid, cn);
+ }
+ bc.registerService(RepositoryContext.class, repositoryContext, props);
} catch (Exception e) {
throw new ArgeoException("Cannot create Jackrabbit repository " + pid, e);
}
for (String pid : repositories.keySet()) {
try {
repositories.get(pid).getRepository().shutdown();
+ if (log.isDebugEnabled())
+ log.debug("Shut down repository " + pid
+ + (pidToCn.containsKey(pid) ? " (" + pidToCn.get(pid) + ")" : ""));
} catch (Exception e) {
log.error("Error when shutting down Jackrabbit repository " + pid, e);
}
try {
ConfigurationAdmin confAdmin = bc.getService(bc.getServiceReference(ConfigurationAdmin.class));
Configuration[] confs = confAdmin.listConfigurations(
- "(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + NodeConstants.JACKRABBIT_FACTORY_PID + ")");
+ "(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + NodeConstants.NODE_REPOS_FACTORY_PID + ")");
if (confs == null || confs.length == 0) {
Group buttonGroup = new Group(parent, SWT.NONE);
buttonGroup.setText("Repository Type");
attr.set(i, values[i]);
}
} else {
- if (attr.size() != 1)
+ if (attr.size() > 1)
throw new IllegalArgumentException("Attribute " + key + " is multi-valued");
- attr.set(0, value.toString());
+ if (attr.size() == 1)
+ attr.set(0, value.toString());
+ else
+ attr.add(value.toString());
}
return oldValue;
}
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
+import java.util.Map;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
}
}
+ public void write(Map<LdapName, Attributes> entries) throws IOException {
+ for (LdapName dn : entries.keySet())
+ writeEntry(dn, entries.get(dn));
+ }
+
protected void writeAttribute(Attribute attribute) throws NamingException, IOException {
for (NamingEnumeration<?> attrValues = attribute.getAll(); attrValues.hasMore();) {
Object value = attrValues.next();
* Implements an open session in view patter: a new JCR session is created for
* each request
*/
+@Deprecated
public class OpenInViewSessionProvider implements SessionProvider, Serializable {
private static final long serialVersionUID = 2270957712453841368L;
import org.apache.jackrabbit.server.remoting.davex.JcrRemotingServlet;
/** Provides remote access to a JCR repository */
+@Deprecated
public class RemotingServlet extends JcrRemotingServlet {
public final static String INIT_PARAM_RESOURCE_PATH_PREFIX = JcrRemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX;
public final static String INIT_PARAM_HOME = JcrRemotingServlet.INIT_PARAM_HOME;
import org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet;
/** WebDav servlet whose repository is injected */
+@Deprecated
public class WebdavServlet extends SimpleWebdavServlet {
public final static String INIT_PARAM_RESOURCE_CONFIG = SimpleWebdavServlet.INIT_PARAM_RESOURCE_CONFIG;
public final static String INIT_PARAM_RESOURCE_PATH_PREFIX = SimpleWebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
-import java.util.Map;
import java.util.Properties;
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+
public class LangUtils {
/*
* NON-API OSGi
}
}
+ public static void appendAsLdif(String dnBase, String dnKey, Dictionary<String, Object> props, Path path)
+ throws IOException {
+ if (props == null)
+ throw new IllegalArgumentException("Props cannot be null");
+ Object dnValue = props.get(dnKey);
+ String dnStr = dnKey + '=' + dnValue + ',' + dnBase;
+ LdapName dn;
+ try {
+ dn = new LdapName(dnStr);
+ } catch (InvalidNameException e) {
+ throw new IllegalArgumentException("Cannot interpret DN " + dnStr, e);
+ }
+ if (dnValue == null)
+ throw new IllegalArgumentException("DN key " + dnKey + " must have a value");
+ try (Writer writer = Files.newBufferedWriter(path, StandardOpenOption.APPEND, StandardOpenOption.CREATE)) {
+ writer.append("\ndn: ");
+ writer.append(dn.toString());
+ writer.append('\n');
+ for (Enumeration<String> keys = props.keys(); keys.hasMoreElements();) {
+ String key = keys.nextElement();
+ Object value = props.get(key);
+ writer.append(key);
+ writer.append(": ");
+ // FIXME deal with binary and multiple values
+ writer.append(value.toString());
+ writer.append('\n');
+ }
+ }
+ }
+
public static Dictionary<String, Object> loadFromProperties(Path path) throws IOException {
Properties toLoad = new Properties();
try (InputStream in = Files.newInputStream(path)) {