org.eclipse.equinox.cm,\
org.eclipse.rap.rwt.osgi
+#org.eclipse.equinox.metatype,\
+
argeo.osgi.start.3.node=\
org.argeo.cms
<artifactId>org.argeo.dep.cms.client</artifactId>
<version>2.1.45-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.cms.api</artifactId>
+ <version>2.1.45-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.argeo.commons</groupId>
<artifactId>org.argeo.cms</artifactId>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.argeo.cms.api</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+Provide-Capability: cms.datamodel;name=node;cnd=/org/argeo/node/node.cnd
\ No newline at end of file
--- /dev/null
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>argeo-commons</artifactId>
+ <version>2.1.45-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <artifactId>org.argeo.cms.api</artifactId>
+ <name>Commons CMS API</name>
+ <packaging>jar</packaging>
+ <dependencies>
+ </dependencies>
+</project>
\ No newline at end of file
--- /dev/null
+package org.argeo.node;
+
+import java.security.Principal;
+
+/** Allows to modify any data. */
+public final class DataAdminPrincipal implements Principal {
+ private final String name = "ou=dataAdmin";
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return this == obj;
+ }
+
+ @Override
+ public String toString() {
+ return name.toString();
+ }
+
+}
--- /dev/null
+package org.argeo.node;
+
+import org.osgi.resource.Namespace;
+
+/** CMS Data Model capability namespace. */
+public class DataModelNamespace extends Namespace {
+
+ public static final String CMS_DATA_MODEL_NAMESPACE = "cms.datamodel";
+ public static final String CAPABILITY_NAME_ATTRIBUTE = "name";
+ public static final String CAPABILITY_CND_ATTRIBUTE = "cnd";
+
+ private DataModelNamespace() {
+ // empty
+ }
+
+}
--- /dev/null
+package org.argeo.node;
+
+public interface NodeConstants {
+ /*
+ * PIDs
+ */
+ String NODE_STATE_PID = "org.argeo.node.state";
+ String NODE_DEPLOYMENT_PID = "org.argeo.node.deployment";
+ String NODE_INSTANCE_PID = "org.argeo.node.instance";
+
+ String NODE_REPO_PID = "org.argeo.node.repo";
+ String NODE_USER_ADMIN_PID = "org.argeo.node.userAdmin";
+
+ /*
+ * FACTORY PIDs
+ */
+ String JACKRABBIT_FACTORY_PID = "org.argeo.jackrabbit.config";
+
+ /*
+ * FRAMEWORK PROPERTIES
+ */
+ String NODE_INIT = "argeo.node.init";
+ String I18N_DEFAULT_LOCALE = "argeo.i18n.defaultLocale";
+ String I18N_LOCALES = "argeo.i18n.locales";
+ // Node Security
+ String ROLES_URI = "argeo.node.roles.uri";
+ /** URI to an LDIF file or LDAP server used as initialization or backend */
+ String USERADMIN_URIS = "argeo.node.useradmin.uris";
+ // Node
+ /** Properties configuring the node repository */
+ String NODE_REPO_PROP_PREFIX = "argeo.node.repo.";
+
+}
--- /dev/null
+package org.argeo.node;
+
+public interface NodeDeployment {
+
+}
--- /dev/null
+package org.argeo.node;
+
+public interface NodeInstance {
+
+}
--- /dev/null
+package org.argeo.node;
+
+import java.util.List;
+import java.util.Locale;
+
+public interface NodeState {
+ public Locale getDefaultLocale();
+
+ public List<Locale> getLocales();
+}
--- /dev/null
+package org.argeo.node;
+
+/** JCR repository configuration */
+public enum RepoConf {
+ /** Repository type */
+ type("localfs"),
+ /** Default workspace */
+ defaultWorkspace("main"),
+ /** Database URL */
+ dburl(null),
+ /** Database user */
+ dbuser(null),
+ /** Database password */
+ dbpassword(null),
+
+ /** The identifier (can be an URL locating the repo) */
+ uri(null),
+
+ //
+ // JACKRABBIT SPECIFIC
+ //
+ /** Maximum database pool size */
+ maxPoolSize(10),
+ /** Maximum cache size in MB */
+ maxCacheMB(null),
+ /** Bundle cache size in MB */
+ bundleCacheMB(8),
+ /** Extractor pool size */
+ extractorPoolSize(0),
+ /** Search cache size */
+ searchCacheSize(1000),
+ /** Max volatile index size */
+ maxVolatileIndexSize(1048576);
+
+ /** The default value. */
+ private Object def;
+
+ RepoConf(Object def) {
+ this.def = def;
+ }
+
+ public Object getDefault() {
+ return def;
+ }
+}
--- /dev/null
+<argeo = 'http://www.argeo.org/ns/argeo'>
+
+// USER NODES
+[argeo:userHome] > mix:created, mix:lastModified
+mixin
+- argeo:userID (STRING) m
++ argeo:keyring (argeo:pbeSpec)
+//+ argeo:preferences (argeo:preferenceNode)
+
+[argeo:userProfile] > mix:created, mix:lastModified, mix:title, mix:versionable
+mixin
+- argeo:userID (STRING) m
+
+//[argeo:preferenceNode] > mix:lastModified, mix:versionable
+//mixin
+//+ * (argeo:preferenceNode) * version
+
+[argeo:remoteRepository] > nt:unstructured
+- argeo:uri (STRING)
+- argeo:userID (STRING)
++ argeo:password (argeo:encrypted)
+
+// TABULAR CONTENT
+[argeo:table] > nt:file
++ * (argeo:column) *
+
+[argeo:column] > mix:title
+- jcr:requiredType (STRING) = 'STRING'
+
+[argeo:csv] > nt:resource
+
+// CRYPTO
+[argeo:encrypted] > nt:base
+mixin
+// initialization vector used by some algorithms
+- argeo:iv (BINARY)
+
+[argeo:pbeKeySpec] > nt:base
+mixin
+- argeo:secretKeyFactory (STRING)
+- argeo:salt (BINARY)
+- argeo:iterationCount (LONG)
+- argeo:keyLength (LONG)
+- argeo:secretKeyEncryption (STRING)
+
+[argeo:pbeSpec] > argeo:pbeKeySpec
+mixin
+- argeo:cipher (STRING)
+
--- /dev/null
+/**
+ * Abstractions or constants related to an Argeo Node, an active repository of
+ * linked data.
+ */
+package org.argeo.node;
\ No newline at end of file
--- /dev/null
+version 2.1.0
\ No newline at end of file
+
Bundle-SymbolicName: org.argeo.cms;singleton:=true
Bundle-Activator: org.argeo.cms.internal.kernel.Activator
Import-Package: javax.jcr.security,\
org.eclipse.core.commands;resolution:=optional,\
org.eclipse.swt;resolution:=optional,\
org.eclipse.jface.window;resolution:=optional,\
-org.eclipse.swt.widgets;resolution:=optional,\
org.h2;resolution:=optional,\
org.postgresql;resolution:=optional,\
org.apache.commons.vfs2.*;resolution:=optional,\
-source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
OSGI-INF/,\
- bin/
+ bin/,\
+ OSGI-INF/org.argeo.cms.internal.kernel.KernelInitOld.xml
+source.. = src/
additional.bundles = org.apache.jackrabbit.data
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.argeo.commons</groupId>
<name>Commons CMS</name>
<packaging>jar</packaging>
<dependencies>
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.cms.api</artifactId>
+ <version>2.1.45-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.argeo.commons</groupId>
<artifactId>org.argeo.server.jcr</artifactId>
// LOGIN CONTEXTS
final static String LOGIN_CONTEXT_USER = "USER";
final static String LOGIN_CONTEXT_ANONYMOUS = "ANONYMOUS";
- final static String LOGIN_CONTEXT_SYSTEM = "SYSTEM";
+ final static String LOGIN_CONTEXT_DATA_ADMIN = "DATA_ADMIN";
final static String LOGIN_CONTEXT_SINGLE_USER = "SINGLE_USER";
// RESERVED ROLES
--- /dev/null
+package org.argeo.cms.auth;
+
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+import org.argeo.node.DataAdminPrincipal;
+
+public class DataAdminLoginModule implements LoginModule {
+ private Subject subject;
+
+ @Override
+ public void initialize(Subject subject, CallbackHandler callbackHandler,
+ Map<String, ?> sharedState, Map<String, ?> options) {
+ this.subject = subject;
+ }
+
+ @Override
+ public boolean login() throws LoginException {
+ // TODO check permission?
+ return true;
+ }
+
+ @Override
+ public boolean commit() throws LoginException {
+ subject.getPrincipals().add(new DataAdminPrincipal());
+ return true;
+ }
+
+ @Override
+ public boolean abort() throws LoginException {
+ return true;
+ }
+
+ @Override
+ public boolean logout() throws LoginException {
+ // remove ALL credentials (e.g. additional Jackrabbit credentials)
+ subject.getPrincipals().clear();
+ return true;
+ }
+
+}
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.argeo.cms.CmsException;
-import org.argeo.cms.internal.kernel.Activator;
import org.argeo.cms.internal.kernel.WebCmsSessionImpl;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
@Override
public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
Map<String, ?> options) {
- bc = Activator.getBundleContext();
+ bc = FrameworkUtil.getBundle(HttpLoginModule.class).getBundleContext();
+ assert bc != null;
this.subject = subject;
this.callbackHandler = callbackHandler;
this.sharedState = (Map<String, Object>) sharedState;
--- /dev/null
+package org.argeo.cms.auth;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+import javax.transaction.UserTransaction;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.UserAdmin;
+
+/**
+ * Register one or many roles via a user admin service. Does nothing if the role
+ * is already registered.
+ */
+public class SimpleRoleRegistration implements Runnable {
+ private final static Log log = LogFactory
+ .getLog(SimpleRoleRegistration.class);
+
+ private String role;
+ private List<String> roles = new ArrayList<String>();
+ private UserAdmin userAdmin;
+ private UserTransaction userTransaction;
+
+ @Override
+ public void run() {
+ try {
+ userTransaction.begin();
+ if (role != null && !roleExists(role))
+ newRole(toDn(role));
+
+ for (String r : roles)
+ if (!roleExists(r))
+ newRole(toDn(r));
+ userTransaction.commit();
+ } catch (Exception e) {
+ try {
+ userTransaction.rollback();
+ } catch (Exception e1) {
+ log.error("Cannot rollback", e1);
+ }
+ throw new ArgeoException("Cannot add roles", e);
+ }
+ }
+
+ private boolean roleExists(String role) {
+ return userAdmin.getRole(toDn(role).toString()) != null;
+ }
+
+ protected void newRole(LdapName r) {
+ userAdmin.createRole(r.toString(), Role.GROUP);
+ log.info("Added role " + r + " required by application.");
+ }
+
+ public void register(UserAdmin userAdminService, Map<?, ?> properties) {
+ this.userAdmin = userAdminService;
+ run();
+ }
+
+ protected LdapName toDn(String name) {
+ try {
+ return new LdapName("cn=" + name + ",ou=roles,ou=node");
+ } catch (InvalidNameException e) {
+ throw new ArgeoException("Badly formatted role name " + name, e);
+ }
+ }
+
+ public void setRole(String role) {
+ this.role = role;
+ }
+
+ public void setRoles(List<String> roles) {
+ this.roles = roles;
+ }
+
+ public void setUserAdmin(UserAdmin userAdminService) {
+ this.userAdmin = userAdminService;
+ }
+
+ public void setUserTransaction(UserTransaction userTransaction) {
+ this.userTransaction = userTransaction;
+ }
+
+}
import javax.security.auth.spi.LoginModule;
import org.argeo.ArgeoException;
-import org.argeo.cms.internal.kernel.Activator;
import org.argeo.eclipse.ui.specific.UiContext;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
import org.osgi.service.useradmin.Authorization;
import org.osgi.service.useradmin.User;
import org.osgi.service.useradmin.UserAdmin;
public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
Map<String, ?> options) {
try {
- bc = Activator.getBundleContext();
+ bc = FrameworkUtil.getBundle(UserAdminLoginModule.class).getBundleContext();
+ assert bc != null;
// this.subject = subject;
this.callbackHandler = callbackHandler;
this.sharedState = (Map<String, Object>) sharedState;
package org.argeo.cms.internal.kernel;
-import java.util.UUID;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Hashtable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoLogger;
+import org.argeo.cms.CmsException;
+import org.argeo.node.NodeConstants;
+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;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
+import org.osgi.service.log.LogReaderService;
/**
* Activates the {@link Kernel} from the provided {@link BundleContext}. Gives
* access to kernel information for the rest of the bundle (and only it)
*/
public class Activator implements BundleActivator {
- public final static String SYSTEM_KEY_PROPERTY = "argeo.security.systemKey";
+ // public final static String SYSTEM_KEY_PROPERTY =
+ // "argeo.security.systemKey";
private final Log log = LogFactory.getLog(Activator.class);
- private final static String systemKey;
- static {
- systemKey = UUID.randomUUID().toString();
- System.setProperty(SYSTEM_KEY_PROPERTY, systemKey);
- }
+ // private final static String systemKey;
+ // static {
+ // System.setProperty(SYSTEM_KEY_PROPERTY, systemKey);
+ // }
+
+// private static Kernel kernel;
+ private static Activator instance;
+
+ private BundleContext bc;
+ private ConditionalPermissionAdmin permissionAdmin;
+ private LogReaderService logReaderService;
+ private ConfigurationAdmin configurationAdmin;
- private static BundleContext bundleContext;
- private static Kernel kernel;
+ private NodeLogger logger;
+ private CmsState nodeState;
@Override
- public void start(BundleContext context) throws Exception {
- assert bundleContext == null;
- assert kernel == null;
- bundleContext = context;
- try {
- kernel = new Kernel();
- kernel.init();
- } catch (Exception e) {
- log.error("Cannot boot kernel", e);
+ public void start(BundleContext bundleContext) throws Exception {
+ // try {
+ // kernel = new Kernel();
+ // kernel.init();
+ // } catch (Exception e) {
+ // log.error("Cannot boot kernel", e);
+ // }
+
+ instance = this;
+ this.bc = bundleContext;
+ this.permissionAdmin = getService(ConditionalPermissionAdmin.class);
+ this.logReaderService = getService(LogReaderService.class);
+ this.configurationAdmin = getService(ConfigurationAdmin.class);
+
+ initSecurity();// must be first
+ initArgeoLogger();
+ initNodeState();
+ }
+
+ private void initSecurity() {
+ URL url = getClass().getClassLoader().getResource(KernelConstants.JAAS_CONFIG);
+ System.setProperty("java.security.auth.login.config", url.toExternalForm());
+ }
+
+ private void initArgeoLogger() {
+ logger = new NodeLogger(logReaderService);
+
+ // register
+ bc.registerService(ArgeoLogger.class, logger, null);
+ }
+
+ private void initNodeState() throws IOException {
+ nodeState = new CmsState();
+ bc.registerService(LangUtils.names(NodeState.class, ManagedService.class), nodeState,
+ LangUtils.init(Constants.SERVICE_PID, NodeConstants.NODE_STATE_PID));
+
+ Configuration nodeConf = configurationAdmin.getConfiguration(NodeConstants.NODE_STATE_PID);
+ Dictionary<String, Object> props = nodeConf.getProperties();
+ if (props == null) {
+ if (log.isDebugEnabled())
+ log.debug("Clean node state");
+ Dictionary<String, Object> envProps = getStatePropertiesFromEnvironment();
+ nodeConf.update(envProps);
+ } else {
+ // Check id 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.");
+ }
}
+
}
@Override
- public void stop(BundleContext context) throws Exception {
- kernel.destroy();
- kernel = null;
- bundleContext = null;
+ public void stop(BundleContext bundleContext) throws Exception {
+ nodeState.shutdown();
+
+ instance = null;
+ this.bc = null;
+ this.permissionAdmin = null;
+ this.logReaderService = null;
+ this.configurationAdmin = null;
+
+// if (kernel != null) {
+// kernel.destroy();
+// kernel = null;
+// }
+
+ }
+
+ private <T> T getService(Class<T> clazz) {
+ ServiceReference<T> sr = bc.getServiceReference(clazz);
+ if (sr == null)
+ throw new CmsException("No service available for " + clazz);
+ return bc.getService(sr);
}
- /**
- * Singleton interface to the {@link BundleContext} related to the calling
- * thread.
- *
- * @BundleScope
- */
- public static BundleContext getBundleContext() {
- return bundleContext;
+ 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;
}
- public static KernelHeader getKernelHeader() {
- return kernel;
+ private void copyFrameworkProp(String key, Dictionary<String, Object> props) {
+ String value = bc.getProperty(key);
+ if (value != null)
+ props.put(key, value);
}
- /**
- * @return a String which is guaranteed to be unique between and constant
- * within a Java static context (typically a VM launch)
- * @BundleScope
- */
- public final static String getSystemKey() {
- return systemKey;
+ public static NodeState getNodeState() {
+ return instance.nodeState;
}
}
--- /dev/null
+package org.argeo.cms.internal.kernel;
+
+import static org.argeo.node.DataModelNamespace.CMS_DATA_MODEL_NAMESPACE;
+
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.URL;
+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 javax.jcr.Repository;
+import javax.jcr.Session;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.commons.cnd.CndImporter;
+import org.argeo.cms.CmsException;
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.node.DataModelNamespace;
+import org.argeo.node.NodeDeployment;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+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;
+
+public class CmsDeployment implements NodeDeployment, ManagedService {
+ private final Log log = LogFactory.getLog(getClass());
+ private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext();
+
+ private Repository deployedNodeRepository;
+ private HomeRepository homeRepository;
+
+ @Override
+ public void updated(Dictionary<String, ?> properties) throws ConfigurationException {
+ if (properties == null)
+ return;
+
+ 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 {
+ Set<String> processed = new HashSet<String>();
+ bundles: for (Bundle bundle : bc.getBundles()) {
+ BundleWiring wiring = bundle.adapt(BundleWiring.class);
+ if (wiring == null) {
+ if (log.isTraceEnabled())
+ log.error("No wiring for " + bundle.getSymbolicName());
+ continue bundles;
+ }
+ processWiring(adminSession, wiring, processed);
+ }
+ } finally {
+ JcrUtils.logoutQuietly(adminSession);
+ }
+ }
+
+ private void processWiring(Session adminSession, BundleWiring wiring, Set<String> processed) {
+ // recursively process requirements first
+ List<BundleWire> requiredWires = wiring.getRequiredWires(CMS_DATA_MODEL_NAMESPACE);
+ for (BundleWire wire : requiredWires) {
+ processWiring(adminSession, wire.getProviderWiring(), processed);
+ // registerCnd(adminSession, wire.getCapability(), processed);
+ }
+ List<BundleCapability> capabilities = wiring.getCapabilities(CMS_DATA_MODEL_NAMESPACE);
+ for (BundleCapability capability : capabilities) {
+ registerCnd(adminSession, capability, processed);
+ }
+ }
+
+ private void registerCnd(Session adminSession, BundleCapability capability, Set<String> processed) {
+ Map<String, Object> attrs = capability.getAttributes();
+ String name = attrs.get(DataModelNamespace.CAPABILITY_NAME_ATTRIBUTE).toString();
+ if (processed.contains(name)) {
+ if (log.isTraceEnabled())
+ log.trace("Data model " + name + " has already been processed");
+ return;
+ }
+ String path = attrs.get(DataModelNamespace.CAPABILITY_CND_ATTRIBUTE).toString();
+ URL url = capability.getRevision().getBundle().getResource(path);
+ try (Reader reader = new InputStreamReader(url.openStream())) {
+ CndImporter.registerNodeTypes(reader, adminSession, true);
+ processed.add(name);
+ if (log.isDebugEnabled())
+ log.debug("Registered CND " + url);
+ } catch (Exception e) {
+ throw new CmsException("Cannot import CND " + url, e);
+ }
+
+ Hashtable<String, Object> properties = new Hashtable<>();
+ properties.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, name);
+ bc.registerService(Repository.class, adminSession.getRepository(), properties);
+ if (log.isDebugEnabled())
+ log.debug("Published data model " + name);
+ }
+
+ public void setDeployedNodeRepository(Repository deployedNodeRepository) {
+ this.deployedNodeRepository = deployedNodeRepository;
+ }
+
+
+}
--- /dev/null
+package org.argeo.cms.internal.kernel;
+
+import static bitronix.tm.TransactionManagerServices.getTransactionManager;
+import static bitronix.tm.TransactionManagerServices.getTransactionSynchronizationRegistry;
+import static java.util.Locale.ENGLISH;
+import static org.argeo.cms.internal.kernel.KernelUtils.getFrameworkProp;
+import static org.argeo.util.LocaleChoice.asLocaleList;
+import static org.osgi.framework.Constants.FRAMEWORK_UUID;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Locale;
+
+import javax.jcr.RepositoryFactory;
+import javax.transaction.TransactionManager;
+import javax.transaction.TransactionSynchronizationRegistry;
+import javax.transaction.UserTransaction;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.argeo.cms.CmsException;
+import org.argeo.jackrabbit.OsgiJackrabbitRepositoryFactory;
+import org.argeo.jcr.ArgeoJcrConstants;
+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.eclipse.equinox.http.jetty.JettyConfigurator;
+import org.eclipse.equinox.http.jetty.JettyConstants;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.cm.ManagedServiceFactory;
+import org.osgi.service.http.HttpService;
+import org.osgi.service.useradmin.UserAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+import bitronix.tm.BitronixTransactionManager;
+import bitronix.tm.BitronixTransactionSynchronizationRegistry;
+import bitronix.tm.TransactionManagerServices;
+
+public class CmsState implements NodeState, ManagedService {
+ private final Log log = LogFactory.getLog(CmsState.class);
+ private final BundleContext bc = FrameworkUtil.getBundle(CmsState.class).getBundleContext();
+
+ // REFERENCES
+ private ConfigurationAdmin configurationAdmin;
+
+ // i18n
+ private Locale defaultLocale;
+ private List<Locale> locales = null;
+
+ // Standalone services
+ private BitronixTransactionManager transactionManager;
+ private BitronixTransactionSynchronizationRegistry transactionSynchronizationRegistry;
+ private OsgiJackrabbitRepositoryFactory repositoryFactory;
+
+ // Security
+ private NodeUserAdmin userAdmin;
+ private JackrabbitRepositoryServiceFactory repositoryServiceFactory;
+
+ // Deployment
+ 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) {
+ this.cleanState = true;
+ if (log.isTraceEnabled())
+ log.trace("Clean state");
+ return;
+ }
+
+ try {
+ if (log.isDebugEnabled())
+ log.debug(
+ "## CMS STARTED " + (cleanState ? " (clean state) " : "") + LangUtils.toJson(properties, true));
+ configurationAdmin = bc.getService(bc.getServiceReference(ConfigurationAdmin.class));
+
+ initI18n(properties);
+ initTrackers();
+ initTransactionManager();
+ initRepositoryFactory();
+ initUserAdmin();
+ initRepositories(properties);
+ initWebServer();
+ initNodeDeployment();
+ } catch (Exception e) {
+ throw new CmsException("Cannot get configuration", e);
+ }
+ }
+
+ private void initTrackers() {
+ new ServiceTracker<HttpService, HttpService>(bc, HttpService.class, new PrepareHttpStc()).open();
+ new ServiceTracker<>(bc, JackrabbitRepository.class, new JackrabbitrepositoryStc()).open();
+ }
+
+ private void initI18n(Dictionary<String, ?> stateProps) {
+ Object defaultLocaleValue = stateProps.get(NodeConstants.I18N_DEFAULT_LOCALE);
+ defaultLocale = defaultLocaleValue != null ? new Locale(defaultLocaleValue.toString())
+ : new Locale(ENGLISH.getLanguage());
+ locales = asLocaleList(stateProps.get(NodeConstants.I18N_LOCALES));
+ }
+
+ private void initTransactionManager() {
+ bitronix.tm.Configuration tmConf = TransactionManagerServices.getConfiguration();
+ tmConf.setServerId(getFrameworkProp(FRAMEWORK_UUID));
+
+ Bundle bitronixBundle = FrameworkUtil.getBundle(bitronix.tm.Configuration.class);
+ File tmBaseDir = bitronixBundle.getDataFile(KernelConstants.DIR_TRANSACTIONS);
+ File tmDir1 = new File(tmBaseDir, "btm1");
+ tmDir1.mkdirs();
+ tmConf.setLogPart1Filename(new File(tmDir1, tmDir1.getName() + ".tlog").getAbsolutePath());
+ File tmDir2 = new File(tmBaseDir, "btm2");
+ tmDir2.mkdirs();
+ tmConf.setLogPart2Filename(new File(tmDir2, tmDir2.getName() + ".tlog").getAbsolutePath());
+ transactionManager = getTransactionManager();
+ transactionSynchronizationRegistry = getTransactionSynchronizationRegistry();
+ // register
+ bc.registerService(TransactionManager.class, transactionManager, null);
+ bc.registerService(UserTransaction.class, transactionManager, null);
+ bc.registerService(TransactionSynchronizationRegistry.class, transactionSynchronizationRegistry, null);
+ }
+
+ private void initRepositoryFactory() {
+ // TODO rationalise RepositoryFactory
+ repositoryFactory = new OsgiJackrabbitRepositoryFactory();
+ repositoryFactory.setBundleContext(bc);
+ // register
+ bc.registerService(RepositoryFactory.class, repositoryFactory, null);
+ }
+
+ private void initUserAdmin() {
+ userAdmin = new NodeUserAdmin();
+ // register
+ Dictionary<String, Object> props = userAdmin.currentState();
+ props.put(Constants.SERVICE_PID, NodeConstants.NODE_REPO_PID);
+ // TODO use ManagedService
+ bc.registerService(UserAdmin.class, userAdmin, props);
+ }
+
+ private void initRepositories(Dictionary<String, ?> stateProps) throws IOException {
+ nodeRepoUri = KernelUtils.getOsgiInstanceUri("repos/node");
+ // register
+ repositoryServiceFactory = new JackrabbitRepositoryServiceFactory();
+ bc.registerService(ManagedServiceFactory.class, repositoryServiceFactory,
+ LangUtils.init(Constants.SERVICE_PID, NodeConstants.JACKRABBIT_FACTORY_PID));
+
+ if (cleanState) {
+ Configuration newNodeConf = configurationAdmin
+ .createFactoryConfiguration(NodeConstants.JACKRABBIT_FACTORY_PID);
+ Dictionary<String, Object> props = getNodeConfig(stateProps);
+ if (props == null) {
+ if (log.isDebugEnabled())
+ log.debug("No argeo.node.repo.type=localfs|h2|postgresql|memory"
+ + " property defined, entering interactive mode...");
+ // TODO interactive configuration
+ return;
+ }
+ // props.put(Constants.SERVICE_PID, NodeConstants.NODE_REPO_PID);
+ props.put(RepoConf.uri.name(), nodeRepoUri.toString());
+ newNodeConf.update(props);
+ }
+ }
+
+ private void initWebServer() {
+ String httpPort = getFrameworkProp("org.osgi.service.http.port");
+ String httpsPort = getFrameworkProp("org.osgi.service.http.port.secure");
+ 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 (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<>());
+ }
+
+ void shutdown() {
+ if (transactionManager != null)
+ transactionManager.shutdown();
+ if (userAdmin != null)
+ userAdmin.destroy();
+ if (repositoryServiceFactory != null)
+ repositoryServiceFactory.shutdown();
+
+ // Clean hanging Gogo shell thread
+ new GogoShellKiller().start();
+
+ if (log.isDebugEnabled())
+ log.debug("## CMS STOPPED");
+ }
+
+ 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 JackrabbitrepositoryStc
+ implements ServiceTrackerCustomizer<JackrabbitRepository, JackrabbitRepository> {
+
+ @Override
+ public JackrabbitRepository addingService(ServiceReference<JackrabbitRepository> reference) {
+ JackrabbitRepository nodeRepo = bc.getService(reference);
+ Object repoUri = reference.getProperty(ArgeoJcrConstants.JCR_REPOSITORY_URI);
+ if (repoUri != null && repoUri.equals(nodeRepoUri.toString())) {
+ nodeDeployment.setDeployedNodeRepository(nodeRepo);
+ // register
+ bc.registerService(LangUtils.names(NodeDeployment.class, ManagedService.class), nodeDeployment,
+ LangUtils.init(Constants.SERVICE_PID, NodeConstants.NODE_DEPLOYMENT_PID));
+ }
+
+ return nodeRepo;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<JackrabbitRepository> reference, JackrabbitRepository service) {
+ }
+
+ @Override
+ public void removedService(ServiceReference<JackrabbitRepository> reference, JackrabbitRepository service) {
+ }
+
+ }
+
+ private class PrepareHttpStc implements ServiceTrackerCustomizer<HttpService, HttpService> {
+ private DataHttp dataHttp;
+ private NodeHttp nodeHttp;
+
+ @Override
+ public HttpService addingService(ServiceReference<HttpService> reference) {
+ HttpService httpService = addHttpService(reference);
+ return httpService;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<HttpService> reference, HttpService service) {
+ }
+
+ @Override
+ public void removedService(ServiceReference<HttpService> reference, HttpService service) {
+ dataHttp.destroy();
+ dataHttp = null;
+ }
+
+ private HttpService addHttpService(ServiceReference<HttpService> sr) {
+ HttpService httpService = bc.getService(sr);
+ // TODO find constants
+ Object httpPort = sr.getProperty("http.port");
+ Object httpsPort = sr.getProperty("https.port");
+ dataHttp = new DataHttp(httpService);
+ nodeHttp = new NodeHttp(httpService, bc);
+ if (log.isDebugEnabled())
+ log.debug(httpPortsMsg(httpPort, httpsPort));
+ return httpService;
+ }
+
+ }
+
+ /*
+ * ACCESSORS
+ */
+ public Locale getDefaultLocale() {
+ return defaultLocale;
+ }
+
+ public List<Locale> getLocales() {
+ return locales;
+ }
+
+ /*
+ * STATIC
+ */
+ private static String httpPortsMsg(Object httpPort, Object httpsPort) {
+ return "HTTP " + httpPort + (httpsPort != null ? " - HTTPS " + httpsPort : "");
+ }
+
+ /** Workaround for blocking Gogo shell by system shutdown. */
+ private class GogoShellKiller extends Thread {
+
+ public GogoShellKiller() {
+ super("Gogo shell killer");
+ setDaemon(true);
+ }
+
+ @Override
+ public void run() {
+ ThreadGroup rootTg = getRootThreadGroup(null);
+ Thread gogoShellThread = findGogoShellThread(rootTg);
+ if (gogoShellThread == null)
+ return;
+ while (getNonDaemonCount(rootTg) > 2) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ // silent
+ }
+ }
+ gogoShellThread = findGogoShellThread(rootTg);
+ if (gogoShellThread == null)
+ return;
+ System.exit(0);
+ }
+ }
+
+ private static ThreadGroup getRootThreadGroup(ThreadGroup tg) {
+ if (tg == null)
+ tg = Thread.currentThread().getThreadGroup();
+ if (tg.getParent() == null)
+ return tg;
+ else
+ return getRootThreadGroup(tg.getParent());
+ }
+
+ private static int getNonDaemonCount(ThreadGroup rootThreadGroup) {
+ Thread[] threads = new Thread[rootThreadGroup.activeCount()];
+ rootThreadGroup.enumerate(threads);
+ int nonDameonCount = 0;
+ for (Thread t : threads)
+ if (t != null && !t.isDaemon())
+ nonDameonCount++;
+ return nonDameonCount;
+ }
+
+ private static Thread findGogoShellThread(ThreadGroup rootThreadGroup) {
+ Thread[] threads = new Thread[rootThreadGroup.activeCount()];
+ rootThreadGroup.enumerate(threads, true);
+ for (Thread thread : threads) {
+ if (thread.getName().equals("Gogo shell"))
+ return thread;
+ }
+ return null;
+ }
+
+}
import org.argeo.cms.auth.HttpRequestCallbackHandler;
import org.argeo.jcr.ArgeoJcrConstants;
import org.argeo.jcr.JcrUtils;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;
import org.osgi.service.useradmin.Authorization;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
/**
* Intercepts and enriches http access, mainly focusing on security and
private final static String DEFAULT_PROTECTED_HANDLERS = "/org/argeo/cms/internal/kernel/protectedHandlers.xml";
+ private final BundleContext bc;
private final HttpService httpService;
+ private final ServiceTracker<Repository, Repository> repositories;
// FIXME Make it more unique
private String httpAuthRealm = "Argeo";
private OpenInViewSessionProvider sessionProvider;
DataHttp(HttpService httpService) {
- this.httpService = httpService;
+ this.bc = FrameworkUtil.getBundle(getClass()).getBundleContext();
sessionProvider = new OpenInViewSessionProvider();
- // registerRepositoryServlets(ALIAS_NODE, node);
+ this.httpService = httpService;
+ repositories = new ServiceTracker<>(bc, Repository.class, new RepositoriesStc());
+ repositories.open();
}
public void destroy() {
- // unregisterRepositoryServlets(ALIAS_NODE);
+ repositories.close();
}
void registerRepositoryServlets(String alias, Repository repository) {
registerWebdavServlet(alias, repository, false);
registerRemotingServlet(alias, repository, true);
registerRemotingServlet(alias, repository, false);
+ if (log.isDebugEnabled())
+ log.debug("Registered servlets for repository '" + alias + "'");
} catch (Exception e) {
- throw new CmsException("Could not register servlets for repository " + alias, e);
+ throw new CmsException("Could not register servlets for repository '" + alias + "'", e);
}
}
void unregisterRepositoryServlets(String alias) {
- // FIXME unregister servlets
+ try {
+ httpService.unregister(webdavPath(alias, true));
+ httpService.unregister(webdavPath(alias, false));
+ httpService.unregister(remotingPath(alias, true));
+ httpService.unregister(remotingPath(alias, false));
+ if (log.isDebugEnabled())
+ log.debug("Unregistered servlets for repository '" + alias + "'");
+ } catch (Exception e) {
+ log.error("Could not unregister servlets for repository '" + alias + "'", e);
+ }
}
void registerWebdavServlet(String alias, Repository repository, boolean anonymous)
throws NamespaceException, ServletException {
WebdavServlet webdavServlet = new WebdavServlet(repository, sessionProvider);
- String pathPrefix = anonymous ? WEBDAV_PUBLIC : WEBDAV_PRIVATE;
- String path = pathPrefix + "/" + alias;
+ String path = webdavPath(alias, anonymous);
Properties ip = new Properties();
ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_CONFIG, WEBDAV_CONFIG);
ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path);
void registerRemotingServlet(String alias, Repository repository, boolean anonymous)
throws NamespaceException, ServletException {
- String pathPrefix = anonymous ? REMOTING_PUBLIC : REMOTING_PRIVATE;
RemotingServlet remotingServlet = new RemotingServlet(repository, sessionProvider);
- String path = pathPrefix + "/" + alias;
+ String path = remotingPath(alias, anonymous);
Properties ip = new Properties();
ip.setProperty(JcrRemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path);
httpService.registerServlet(path, remotingServlet, ip, new DataHttpContext(anonymous));
}
+ private String webdavPath(String alias, boolean anonymous) {
+ String pathPrefix = anonymous ? WEBDAV_PUBLIC : WEBDAV_PRIVATE;
+ return pathPrefix + "/" + alias;
+ }
+
+ private String remotingPath(String alias, boolean anonymous) {
+ String pathPrefix = anonymous ? REMOTING_PUBLIC : REMOTING_PRIVATE;
+ return pathPrefix + "/" + alias;
+ }
+
private Subject subjectFromRequest(HttpServletRequest request) {
Authorization authorization = (Authorization) request.getAttribute(HttpContext.AUTHORIZATION);
if (authorization == null)
}
}
+ private class RepositoriesStc implements ServiceTrackerCustomizer<Repository, Repository> {
+
+ @Override
+ public Repository addingService(ServiceReference<Repository> reference) {
+ Repository repository = bc.getService(reference);
+ Object jcrRepoAlias = reference.getProperty(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS);
+ if (jcrRepoAlias != null) {
+ String alias = jcrRepoAlias.toString();
+ registerRepositoryServlets(alias, repository);
+ }
+ return repository;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<Repository> reference, Repository service) {
+ }
+
+ @Override
+ public void removedService(ServiceReference<Repository> reference, Repository service) {
+ Object jcrRepoAlias = reference.getProperty(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS);
+ if (jcrRepoAlias != null) {
+ String alias = jcrRepoAlias.toString();
+ unregisterRepositoryServlets(alias);
+ }
+ }
+ }
+
private class DataHttpContext implements HttpContext {
private final boolean anonymous;
@Override
public URL getResource(String name) {
- return Activator.getBundleContext().getBundle().getResource(name);
+ return KernelUtils.getBundleContext(DataHttp.class).getBundle().getResource(name);
}
@Override
+++ /dev/null
-package org.argeo.cms.internal.kernel;
-
-import org.osgi.resource.Namespace;
-
-/** CMS Data Model capability namespace. */
-class DataModelNamespace extends Namespace {
-
- public static final String CMS_DATA_MODEL_NAMESPACE = "cms.datamodel";
- public static final String CAPABILITY_NAME_ATTRIBUTE = "name";
- public static final String CAPABILITY_CND_ATTRIBUTE = "cnd";
-
- private DataModelNamespace() {
- // empty
- }
-
-}
--- /dev/null
+package org.argeo.cms.internal.kernel;
+
+import java.security.PrivilegedAction;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.jcr.LoginException;
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.security.Privilege;
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+
+import org.argeo.ArgeoException;
+import org.argeo.cms.CmsException;
+import org.argeo.cms.auth.AuthConstants;
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.jcr.ArgeoNames;
+import org.argeo.jcr.ArgeoTypes;
+import org.argeo.jcr.JcrRepositoryWrapper;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.UserJcrUtils;
+
+/**
+ * Make sure each user has a home directory available in the default workspace.
+ */
+class HomeRepository extends JcrRepositoryWrapper implements KernelConstants, ArgeoJcrConstants {
+ // private final Kernel kernel;
+
+ /** The home base path. */
+ private String homeBasePath = "/home";
+ private String peopleBasePath = ArgeoJcrConstants.PEOPLE_BASE_PATH;
+
+ private Set<String> checkedUsers = new HashSet<String>();
+
+ public HomeRepository(Repository repository) {
+ // this.kernel = kernel;
+ setRepository(repository);
+ LoginContext lc;
+ try {
+ lc = new LoginContext(AuthConstants.LOGIN_CONTEXT_DATA_ADMIN);
+ lc.login();
+ } catch (javax.security.auth.login.LoginException e1) {
+ throw new CmsException("Cannot login as systrem", e1);
+ }
+ Subject.doAs(lc.getSubject(), new PrivilegedAction<Void>() {
+
+ @Override
+ public Void run() {
+ try {
+ initJcr(getRepository().login());
+ } catch (RepositoryException e) {
+ throw new CmsException("Cannot init JCR home", e);
+ }
+ return null;
+ }
+
+ });
+ }
+
+ @Override
+ public Session login() throws LoginException, RepositoryException {
+ Session session = super.login();
+ String username = session.getUserID();
+ if (username == null)
+ return session;
+ if (session.getUserID().equals(AuthConstants.ROLE_ANONYMOUS))
+ return session;
+
+ if (checkedUsers.contains(username))
+ return session;
+ Session adminSession = KernelUtils.openAdminSession(getRepository(), session.getWorkspace().getName());
+ try {
+ syncJcr(adminSession, username);
+ checkedUsers.add(username);
+ } finally {
+ JcrUtils.logoutQuietly(adminSession);
+ }
+ return session;
+ }
+
+ /*
+ * JCR
+ */
+ /** Session is logged out. */
+ private void initJcr(Session adminSession) {
+ try {
+ JcrUtils.mkdirs(adminSession, homeBasePath);
+ JcrUtils.mkdirs(adminSession, peopleBasePath);
+ adminSession.save();
+
+ JcrUtils.addPrivilege(adminSession, homeBasePath, AuthConstants.ROLE_USER_ADMIN, Privilege.JCR_READ);
+ JcrUtils.addPrivilege(adminSession, peopleBasePath, AuthConstants.ROLE_USER_ADMIN, Privilege.JCR_ALL);
+ adminSession.save();
+ } catch (RepositoryException e) {
+ throw new CmsException("Cannot initialize node user admin", e);
+ } finally {
+ JcrUtils.logoutQuietly(adminSession);
+ }
+ }
+
+ private Node syncJcr(Session session, String username) {
+ try {
+ Node userHome = UserJcrUtils.getUserHome(session, username);
+ if (userHome == null) {
+ String homePath = generateUserPath(homeBasePath, username);
+ if (session.itemExists(homePath))// duplicate user id
+ userHome = session.getNode(homePath).getParent().addNode(JcrUtils.lastPathElement(homePath));
+ else
+ userHome = JcrUtils.mkdirs(session, homePath);
+ // userHome = JcrUtils.mkfolders(session, homePath);
+ userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME);
+ userHome.setProperty(ArgeoNames.ARGEO_USER_ID, username);
+ session.save();
+
+ JcrUtils.clearAccessControList(session, homePath, username);
+ JcrUtils.addPrivilege(session, homePath, username, Privilege.JCR_ALL);
+ }
+
+ Node userProfile = UserJcrUtils.getUserProfile(session, username);
+ // new user
+ if (userProfile == null) {
+ String personPath = generateUserPath(peopleBasePath, username);
+ Node personBase;
+ if (session.itemExists(personPath))// duplicate user id
+ personBase = session.getNode(personPath).getParent().addNode(JcrUtils.lastPathElement(personPath));
+ else
+ personBase = JcrUtils.mkdirs(session, personPath);
+ userProfile = personBase.addNode(ArgeoNames.ARGEO_PROFILE);
+ userProfile.addMixin(ArgeoTypes.ARGEO_USER_PROFILE);
+ userProfile.setProperty(ArgeoNames.ARGEO_USER_ID, username);
+// userProfile.setProperty(ArgeoNames.ARGEO_ENABLED, true);
+// userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED, true);
+// userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED, true);
+// userProfile.setProperty(ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED, true);
+ session.save();
+
+ JcrUtils.clearAccessControList(session, userProfile.getPath(), username);
+ JcrUtils.addPrivilege(session, userProfile.getPath(), username, Privilege.JCR_READ);
+ }
+
+ // Remote roles
+ // if (roles != null) {
+ // writeRemoteRoles(userProfile, roles);
+ // }
+ if (session.hasPendingChanges())
+ session.save();
+ return userProfile;
+ } catch (RepositoryException e) {
+ JcrUtils.discardQuietly(session);
+ throw new ArgeoException("Cannot sync node security model for " + username, e);
+ }
+ }
+
+ /** Generate path for a new user home */
+ private String generateUserPath(String base, String username) {
+ LdapName dn;
+ try {
+ dn = new LdapName(username);
+ } catch (InvalidNameException e) {
+ throw new ArgeoException("Invalid name " + username, e);
+ }
+ String userId = dn.getRdn(dn.size() - 1).getValue().toString();
+ int atIndex = userId.indexOf('@');
+ if (atIndex > 0) {
+ String domain = userId.substring(0, atIndex);
+ String name = userId.substring(atIndex + 1);
+ return base + '/' + JcrUtils.firstCharsToPath(domain, 2) + '/' + domain + '/'
+ + JcrUtils.firstCharsToPath(name, 2) + '/' + name;
+ } else if (atIndex == 0 || atIndex == (userId.length() - 1)) {
+ throw new ArgeoException("Unsupported username " + userId);
+ } else {
+ return base + '/' + JcrUtils.firstCharsToPath(userId, 2) + '/' + userId;
+ }
+ }
+
+}
--- /dev/null
+package org.argeo.cms.internal.kernel;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.commons.io.IOUtils;
+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.apache.jackrabbit.core.RepositoryImpl;
+import org.apache.jackrabbit.core.cache.CacheManager;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
+import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
+import org.argeo.ArgeoException;
+import org.argeo.cms.CmsException;
+import org.argeo.jackrabbit.JackrabbitNodeType;
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.jcr.ArgeoJcrException;
+import org.argeo.node.RepoConf;
+import org.argeo.util.LangUtils;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedServiceFactory;
+import org.xml.sax.InputSource;
+
+public class JackrabbitRepositoryServiceFactory implements ManagedServiceFactory {
+ private final static Log log = LogFactory.getLog(JackrabbitRepositoryServiceFactory.class);
+ private final BundleContext bc = FrameworkUtil.getBundle(JackrabbitRepositoryServiceFactory.class)
+ .getBundleContext();
+
+ // Node
+ final static String REPO_TYPE = "repoType";
+
+ private Map<String, RepositoryContext> repositories = new HashMap<String, RepositoryContext>();
+
+ @Override
+ public String getName() {
+ return "Jackrabbit repository service factory";
+ }
+
+ @Override
+ public void updated(String pid, Dictionary<String, ?> properties) throws ConfigurationException {
+ if (repositories.containsKey(pid))
+ throw new ArgeoException("Already a repository registered for " + pid);
+
+ if (properties == null)
+ return;
+
+ if (repositories.containsKey(pid)) {
+ log.warn("Ignore update of Jackrabbit repository " + pid);
+ return;
+ }
+
+ try {
+ RepositoryContext repositoryContext = createNode(properties);
+ repositories.put(pid, repositoryContext);
+ Dictionary<String, Object> props = LangUtils.init(Constants.SERVICE_PID, pid);
+ props.put(ArgeoJcrConstants.JCR_REPOSITORY_URI, properties.get(RepoConf.uri.name()));
+ bc.registerService(JackrabbitRepository.class, repositoryContext.getRepository(), props);
+ } catch (Exception e) {
+ throw new ArgeoException("Cannot create Jackrabbit repository " + pid, e);
+ }
+
+ }
+
+ @Override
+ public void deleted(String pid) {
+ RepositoryContext repositoryContext = repositories.remove(pid);
+ repositoryContext.getRepository().shutdown();
+ if (log.isDebugEnabled())
+ log.debug("Deleted repository " + pid);
+ }
+
+ public void shutdown() {
+ for (String pid : repositories.keySet()) {
+ try {
+ repositories.get(pid).getRepository().shutdown();
+ } catch (Exception e) {
+ log.error("Error when shutting down Jackrabbit repository " + pid, e);
+ }
+ }
+ }
+
+ private RepositoryConfig getConfiguration(Dictionary<String, ?> properties) throws RepositoryException {
+ JackrabbitNodeType type = JackrabbitNodeType.valueOf(prop(properties, RepoConf.type).toString());
+ ClassLoader cl = getClass().getClassLoader();
+ InputStream in = null;
+ try {
+ final String base = "/org/argeo/jackrabbit";
+ switch (type) {
+ case h2:
+ in = cl.getResourceAsStream(base + "/repository-h2.xml");
+ break;
+ case postgresql:
+ in = cl.getResourceAsStream(base + "/repository-postgresql.xml");
+ break;
+ case memory:
+ in = cl.getResourceAsStream(base + "/repository-memory.xml");
+ break;
+ case localfs:
+ in = cl.getResourceAsStream(base + "/repository-localfs.xml");
+ break;
+ default:
+ throw new ArgeoJcrException("Unsupported node type " + type);
+ }
+
+ if (in == null)
+ throw new ArgeoJcrException("Repository configuration not found");
+ InputSource config = new InputSource(in);
+ Properties jackrabbitVars = getConfigurationProperties(type, properties);
+ RepositoryConfig repositoryConfig = RepositoryConfig.create(config, jackrabbitVars);
+ return repositoryConfig;
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+ }
+
+ private Properties getConfigurationProperties(JackrabbitNodeType type, Dictionary<String, ?> properties) {
+ Properties props = new Properties();
+ keys: for (Enumeration<String> keys = properties.keys(); keys.hasMoreElements();) {
+ String key = keys.nextElement();
+ if (key.equals(ConfigurationAdmin.SERVICE_FACTORYPID) || key.equals(Constants.SERVICE_PID))
+ continue keys;
+ String value = prop(properties, RepoConf.valueOf(key));
+ if (value != null)
+ props.put(key, value);
+ }
+
+ // home
+ // File osgiInstanceDir = getOsgiInstanceDir();
+ String homeUri = props.getProperty(RepoConf.uri.name());
+ Path homePath;
+ try {
+ homePath = Paths.get(new URI(homeUri));
+ } catch (URISyntaxException e) {
+ throw new CmsException("Invalid repository home URI", e);
+ }
+ // File homeDir = new File(osgiInstanceDir, "repos/node");
+ File homeDir = homePath.toFile();
+ homeDir.mkdirs();
+ // home cannot be overridden
+ props.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, homeDir.getAbsolutePath());
+
+ // common
+ setProp(props, RepoConf.defaultWorkspace);
+ setProp(props, RepoConf.maxPoolSize);
+ // Jackrabbit defaults
+ setProp(props, RepoConf.bundleCacheMB);
+ // See http://wiki.apache.org/jackrabbit/Search
+ setProp(props, RepoConf.extractorPoolSize);
+ setProp(props, RepoConf.searchCacheSize);
+ setProp(props, RepoConf.maxVolatileIndexSize);
+
+ // specific
+ String dburl;
+ switch (type) {
+ case h2:
+ dburl = "jdbc:h2:" + homeDir.getPath() + "/h2/repository";
+ setProp(props, RepoConf.dburl, dburl);
+ setProp(props, RepoConf.dbuser, "sa");
+ setProp(props, RepoConf.dbpassword, "");
+ break;
+ case postgresql:
+ dburl = "jdbc:postgresql://localhost/demo";
+ setProp(props, RepoConf.dburl, dburl);
+ setProp(props, RepoConf.dbuser, "argeo");
+ setProp(props, RepoConf.dbpassword, "argeo");
+ break;
+ case memory:
+ break;
+ case localfs:
+ break;
+ default:
+ throw new ArgeoJcrException("Unsupported node type " + type);
+ }
+ return props;
+ }
+
+ private void setProp(Properties props, RepoConf key, String def) {
+ Object value = props.get(key.name());
+ if (value == null)
+ value = def;
+ if (value == null)
+ value = key.getDefault();
+ if (value != null)
+ props.put(key.name(), value.toString());
+ }
+
+ private void setProp(Properties props, RepoConf key) {
+ setProp(props, key, null);
+ }
+
+ private String prop(Dictionary<String, ?> properties, RepoConf key) {
+ Object value = properties.get(key.name());
+ if (value == null)
+ return key.getDefault() != null ? key.getDefault().toString() : null;
+ else
+ return value.toString();
+ }
+
+ private RepositoryContext createNode(Dictionary<String, ?> properties) throws RepositoryException {
+ RepositoryConfig repositoryConfig = getConfiguration(properties);
+ RepositoryContext repositoryContext = createJackrabbitRepository(repositoryConfig);
+ RepositoryImpl repository = repositoryContext.getRepository();
+
+ // cache
+ Object maxCacheMbStr = prop(properties, RepoConf.maxCacheMB);
+ if (maxCacheMbStr != null) {
+ Integer maxCacheMB = Integer.parseInt(maxCacheMbStr.toString());
+ CacheManager cacheManager = repository.getCacheManager();
+ cacheManager.setMaxMemory(maxCacheMB * 1024l * 1024l);
+ cacheManager.setMaxMemoryPerCache((maxCacheMB / 4) * 1024l * 1024l);
+ }
+
+ return repositoryContext;
+ }
+
+ private RepositoryContext createJackrabbitRepository(RepositoryConfig repositoryConfig) throws RepositoryException {
+ ClassLoader currentContextCl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(JackrabbitRepositoryServiceFactory.class.getClassLoader());
+ try {
+ long begin = System.currentTimeMillis();
+ //
+ // Actual repository creation
+ //
+ RepositoryContext repositoryContext = RepositoryContext.create(repositoryConfig);
+
+ double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
+ if (log.isTraceEnabled())
+ log.trace(
+ "Created Jackrabbit repository in " + duration + " s, home: " + repositoryConfig.getHomeDir());
+
+ return repositoryContext;
+ } finally {
+ Thread.currentThread().setContextClassLoader(currentContextCl);
+ }
+ }
+
+}
import static bitronix.tm.TransactionManagerServices.getTransactionManager;
import static bitronix.tm.TransactionManagerServices.getTransactionSynchronizationRegistry;
import static java.util.Locale.ENGLISH;
-import static org.argeo.cms.internal.kernel.DataModelNamespace.CMS_DATA_MODEL_NAMESPACE;
import static org.argeo.cms.internal.kernel.KernelUtils.getFrameworkProp;
import static org.argeo.cms.internal.kernel.KernelUtils.getOsgiInstanceDir;
-import static org.argeo.jcr.ArgeoJcrConstants.ALIAS_NODE;
-import static org.argeo.jcr.ArgeoJcrConstants.JCR_REPOSITORY_ALIAS;
+import static org.argeo.node.DataModelNamespace.CMS_DATA_MODEL_NAMESPACE;
import static org.argeo.util.LocaleChoice.asLocaleList;
import static org.osgi.framework.Constants.FRAMEWORK_UUID;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileFilter;
+import java.io.FilePermission;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.management.ManagementFactory;
+import java.lang.reflect.ReflectPermission;
+import java.net.SocketPermission;
import java.net.URL;
+import java.security.AllPermission;
import java.security.PrivilegedAction;
import java.util.Dictionary;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.PropertyPermission;
import java.util.Set;
-import javax.jcr.ImportUUIDBehavior;
import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
import javax.jcr.RepositoryFactory;
import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
+import javax.management.MBeanPermission;
+import javax.management.MBeanServerPermission;
+import javax.management.MBeanTrustPermission;
+import javax.security.auth.AuthPermission;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import org.argeo.ArgeoLogger;
import org.argeo.cms.CmsException;
import org.argeo.cms.maintenance.MaintenanceUi;
-import org.argeo.jackrabbit.JackrabbitDataModel;
-import org.argeo.jackrabbit.ManagedJackrabbitRepository;
import org.argeo.jackrabbit.OsgiJackrabbitRepositoryFactory;
import org.argeo.jcr.ArgeoJcrConstants;
-import org.argeo.jcr.ArgeoJcrUtils;
import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.RepoConf;
+import org.argeo.node.DataModelNamespace;
+import org.argeo.node.NodeConstants;
+import org.argeo.node.RepoConf;
import org.eclipse.equinox.http.jetty.JettyConfigurator;
import org.eclipse.equinox.http.jetty.JettyConstants;
-import org.eclipse.equinox.http.servlet.ExtendedHttpService;
import org.eclipse.rap.rwt.application.ApplicationConfiguration;
+import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceListener;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServicePermission;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.startlevel.BundleStartLevel;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
-import org.osgi.service.cm.ManagedService;
+import org.osgi.service.cm.ConfigurationPermission;
+import org.osgi.service.cm.ManagedServiceFactory;
+import org.osgi.service.condpermadmin.BundleLocationCondition;
+import org.osgi.service.condpermadmin.ConditionInfo;
+import org.osgi.service.condpermadmin.ConditionalPermissionAdmin;
+import org.osgi.service.condpermadmin.ConditionalPermissionInfo;
+import org.osgi.service.condpermadmin.ConditionalPermissionUpdate;
+import org.osgi.service.http.HttpService;
import org.osgi.service.log.LogReaderService;
+import org.osgi.service.permissionadmin.PermissionInfo;
import org.osgi.service.useradmin.UserAdmin;
import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
import bitronix.tm.BitronixTransactionManager;
import bitronix.tm.BitronixTransactionSynchronizationRegistry;
* <li>OS access</li>
* </ul>
*/
-final class Kernel implements KernelHeader, KernelConstants, ServiceListener {
+final class Kernel implements KernelHeader, KernelConstants {
/*
* SERVICE REFERENCES
*/
- private ServiceReference<ConfigurationAdmin> configurationAdmin;
+ // private ServiceReference<ConfigurationAdmin> configurationAdmin;
+ private final ServiceTracker<ConfigurationAdmin, ConfigurationAdmin> configurationAdmin;
+ private final ServiceTracker<LogReaderService, LogReaderService> logReaderService;
+ private final ServiceTracker<HttpService, HttpService> httpService;
+ private final ConditionalPermissionAdmin permissionAdmin;
/*
* REGISTERED SERVICES
*/
private ServiceRegistration<TransactionManager> tmReg;
private ServiceRegistration<UserTransaction> utReg;
private ServiceRegistration<TransactionSynchronizationRegistry> tsrReg;
- private ServiceRegistration<? extends Repository> repositoryReg;
+ private ServiceRegistration<?> repositoryReg;
private ServiceRegistration<RepositoryFactory> repositoryFactoryReg;
private ServiceRegistration<UserAdmin> userAdminReg;
private BitronixTransactionManager transactionManager;
private BitronixTransactionSynchronizationRegistry transactionSynchronizationRegistry;
private OsgiJackrabbitRepositoryFactory repositoryFactory;
- JackrabbitRepository repository;
+ private Repository repository;
private NodeUserAdmin userAdmin;
// Members
+ private final BundleContext bc;// = Activator.getBundleContext();
+ private final NodeSecurity nodeSecurity;
+
private final static Log log = LogFactory.getLog(Kernel.class);
ThreadGroup threadGroup = new ThreadGroup(Kernel.class.getSimpleName());
- private final BundleContext bc = Activator.getBundleContext();
- private final NodeSecurity nodeSecurity;
private DataHttp dataHttp;
private NodeHttp nodeHttp;
private KernelThread kernelThread;
public Kernel() {
// KernelUtils.logFrameworkProperties(log);
nodeSecurity = new NodeSecurity();
+ bc = FrameworkUtil.getBundle(getClass()).getBundleContext();
+ configurationAdmin = new ServiceTracker<ConfigurationAdmin, ConfigurationAdmin>(bc, ConfigurationAdmin.class,
+ new PrepareStc<ConfigurationAdmin>());
+ configurationAdmin.open();
+ logReaderService = new ServiceTracker<LogReaderService, LogReaderService>(bc, LogReaderService.class,
+ new PrepareStc<LogReaderService>());
+ logReaderService.open();
+ httpService = new ServiceTracker<HttpService, HttpService>(bc, HttpService.class, new PrepareHttpStc());
+ httpService.open();
+
+ permissionAdmin = bc.getService(bc.getServiceReference(ConditionalPermissionAdmin.class));
+
+ applySystemPermissions();
+ }
+
+ private void applySystemPermissions() {
+ ConditionalPermissionUpdate update = permissionAdmin.newConditionalPermissionUpdate();
+ // Self
+ update.getConditionalPermissionInfos()
+ .add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { locate(Kernel.class) }) },
+ new PermissionInfo[] { new PermissionInfo(AllPermission.class.getName(), null, null) },
+ ConditionalPermissionInfo.ALLOW));
+ update.getConditionalPermissionInfos()
+ .add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { bc.getBundle(0).getLocation() }) },
+ new PermissionInfo[] { new PermissionInfo(AllPermission.class.getName(), null, null) },
+ ConditionalPermissionInfo.ALLOW));
+ // All
+ // FIXME understand why Jetty and Jackrabbit require that
+ update.getConditionalPermissionInfos()
+ .add(permissionAdmin.newConditionalPermissionInfo(null, null, new PermissionInfo[] {
+ new PermissionInfo(SocketPermission.class.getName(), "localhost:7070", "listen,resolve"),
+ new PermissionInfo(FilePermission.class.getName(), "<<ALL FILES>>", "read,write,delete"),
+ new PermissionInfo(PropertyPermission.class.getName(), "DEBUG", "read"),
+ new PermissionInfo(PropertyPermission.class.getName(), "STOP.*", "read"),
+ new PermissionInfo(PropertyPermission.class.getName(), "org.apache.jackrabbit.*", "read"),
+ new PermissionInfo(RuntimePermission.class.getName(), "*", "*"), },
+ ConditionalPermissionInfo.ALLOW));
+
+ // Eclipse
+ // update.getConditionalPermissionInfos()
+ // .add(permissionAdmin.newConditionalPermissionInfo(null,
+ // new ConditionInfo[] { new
+ // ConditionInfo(BundleLocationCondition.class.getName(),
+ // new String[] { "*/org.eclipse.*" }) },
+ // new PermissionInfo[] { new
+ // PermissionInfo(RuntimePermission.class.getName(), "*", "*"),
+ // new PermissionInfo(AdminPermission.class.getName(), "*", "*"),
+ // new PermissionInfo(ServicePermission.class.getName(), "*", "get"),
+ // new PermissionInfo(ServicePermission.class.getName(), "*",
+ // "register"),
+ // new PermissionInfo(TopicPermission.class.getName(), "*", "publish"),
+ // new PermissionInfo(TopicPermission.class.getName(), "*",
+ // "subscribe"),
+ // new PermissionInfo(PropertyPermission.class.getName(), "osgi.*",
+ // "read"),
+ // new PermissionInfo(PropertyPermission.class.getName(), "eclipse.*",
+ // "read"),
+ // new PermissionInfo(PropertyPermission.class.getName(),
+ // "org.eclipse.*", "read"),
+ // new PermissionInfo(PropertyPermission.class.getName(), "equinox.*",
+ // "read"),
+ // new PermissionInfo(PropertyPermission.class.getName(), "xml.*",
+ // "read"),
+ // new PermissionInfo("org.eclipse.equinox.log.LogPermission", "*",
+ // "log"), },
+ // ConditionalPermissionInfo.ALLOW));
+ update.getConditionalPermissionInfos()
+ .add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { "*/org.eclipse.*" }) },
+ new PermissionInfo[] { new PermissionInfo(AllPermission.class.getName(), null, null), },
+ ConditionalPermissionInfo.ALLOW));
+ update.getConditionalPermissionInfos()
+ .add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { "*/org.apache.felix.*" }) },
+ new PermissionInfo[] { new PermissionInfo(AllPermission.class.getName(), null, null), },
+ ConditionalPermissionInfo.ALLOW));
+
+ // Configuration admin
+ update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { locate(configurationAdmin.getService().getClass()) }) },
+ new PermissionInfo[] { new PermissionInfo(ConfigurationPermission.class.getName(), "*", "configure"),
+ new PermissionInfo(AdminPermission.class.getName(), "*", "*"),
+ new PermissionInfo(PropertyPermission.class.getName(), "osgi.*", "read"), },
+ ConditionalPermissionInfo.ALLOW));
+
+ // Bitronix
+ update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { locate(BitronixTransactionManager.class) }) },
+ new PermissionInfo[] { new PermissionInfo(PropertyPermission.class.getName(), "bitronix.tm.*", "read"),
+ new PermissionInfo(RuntimePermission.class.getName(), "getClassLoader", null),
+ new PermissionInfo(MBeanServerPermission.class.getName(), "createMBeanServer", null),
+ new PermissionInfo(MBeanPermission.class.getName(), "bitronix.tm.*", "registerMBean"),
+ new PermissionInfo(MBeanTrustPermission.class.getName(), "register", null) },
+ ConditionalPermissionInfo.ALLOW));
+
+ // DS
+ Bundle dsBundle = findBundle("org.eclipse.equinox.ds");
+ update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { dsBundle.getLocation() }) },
+ new PermissionInfo[] { new PermissionInfo(ConfigurationPermission.class.getName(), "*", "configure"),
+ new PermissionInfo(AdminPermission.class.getName(), "*", "*"),
+ new PermissionInfo(ServicePermission.class.getName(), "*", "get"),
+ new PermissionInfo(ServicePermission.class.getName(), "*", "register"),
+ new PermissionInfo(PropertyPermission.class.getName(), "osgi.*", "read"),
+ new PermissionInfo(PropertyPermission.class.getName(), "xml.*", "read"),
+ new PermissionInfo(PropertyPermission.class.getName(), "equinox.*", "read"),
+ new PermissionInfo(RuntimePermission.class.getName(), "accessDeclaredMembers", null),
+ new PermissionInfo(RuntimePermission.class.getName(), "getClassLoader", null),
+ new PermissionInfo(ReflectPermission.class.getName(), "suppressAccessChecks", null), },
+ ConditionalPermissionInfo.ALLOW));
+
+ // Jetty
+ Bundle jettyUtilBundle = findBundle("org.eclipse.equinox.http.jetty");
+ update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { "*/org.eclipse.jetty.*" }) },
+ new PermissionInfo[] {
+ new PermissionInfo(FilePermission.class.getName(), "<<ALL FILES>>", "read,write,delete"), },
+ ConditionalPermissionInfo.ALLOW));
+
+ // Blueprint
+ Bundle blueprintBundle = findBundle("org.eclipse.gemini.blueprint.core");
+ update.getConditionalPermissionInfos()
+ .add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { blueprintBundle.getLocation() }) },
+ new PermissionInfo[] { new PermissionInfo(RuntimePermission.class.getName(), "*", null),
+ new PermissionInfo(AdminPermission.class.getName(), "*", "*"), },
+ ConditionalPermissionInfo.ALLOW));
+ Bundle blueprintExtenderBundle = findBundle("org.eclipse.gemini.blueprint.extender");
+ update.getConditionalPermissionInfos()
+ .add(permissionAdmin
+ .newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { blueprintExtenderBundle.getLocation() }) },
+ new PermissionInfo[] { new PermissionInfo(RuntimePermission.class.getName(), "*", null),
+ new PermissionInfo(PropertyPermission.class.getName(), "org.eclipse.gemini.*",
+ "read"),
+ new PermissionInfo(AdminPermission.class.getName(), "*", "*"),
+ new PermissionInfo(ServicePermission.class.getName(), "*", "register"), },
+ ConditionalPermissionInfo.ALLOW));
+ Bundle springCoreBundle = findBundle("org.springframework.core");
+ update.getConditionalPermissionInfos()
+ .add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { springCoreBundle.getLocation() }) },
+ new PermissionInfo[] { new PermissionInfo(RuntimePermission.class.getName(), "*", null),
+ new PermissionInfo(AdminPermission.class.getName(), "*", "*"), },
+ ConditionalPermissionInfo.ALLOW));
+ Bundle blueprintIoBundle = findBundle("org.eclipse.gemini.blueprint.io");
+ update.getConditionalPermissionInfos()
+ .add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { blueprintIoBundle.getLocation() }) },
+ new PermissionInfo[] { new PermissionInfo(RuntimePermission.class.getName(), "*", null),
+ new PermissionInfo(AdminPermission.class.getName(), "*", "*"), },
+ ConditionalPermissionInfo.ALLOW));
+
+ // Equinox
+ Bundle registryBundle = findBundle("org.eclipse.equinox.registry");
+ update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { registryBundle.getLocation() }) },
+ new PermissionInfo[] { new PermissionInfo(PropertyPermission.class.getName(), "eclipse.*", "read"),
+ new PermissionInfo(PropertyPermission.class.getName(), "osgi.*", "read"),
+ new PermissionInfo(FilePermission.class.getName(), "<<ALL FILES>>", "read,write,delete"), },
+ ConditionalPermissionInfo.ALLOW));
+
+ Bundle equinoxUtilBundle = findBundle("org.eclipse.equinox.util");
+ update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { equinoxUtilBundle.getLocation() }) },
+ new PermissionInfo[] { new PermissionInfo(PropertyPermission.class.getName(), "equinox.*", "read"),
+ new PermissionInfo(ServicePermission.class.getName(), "*", "get"),
+ new PermissionInfo(ServicePermission.class.getName(), "*", "register"), },
+ ConditionalPermissionInfo.ALLOW));
+ Bundle equinoxCommonBundle = findBundle("org.eclipse.equinox.common");
+ update.getConditionalPermissionInfos()
+ .add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { equinoxCommonBundle.getLocation() }) },
+ new PermissionInfo[] { new PermissionInfo(AdminPermission.class.getName(), "*", "*"), },
+ ConditionalPermissionInfo.ALLOW));
+
+ Bundle consoleBundle = findBundle("org.eclipse.equinox.console");
+ update.getConditionalPermissionInfos()
+ .add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { consoleBundle.getLocation() }) },
+ new PermissionInfo[] { new PermissionInfo(ServicePermission.class.getName(), "*", "register"),
+ new PermissionInfo(AdminPermission.class.getName(), "*", "listener") },
+ ConditionalPermissionInfo.ALLOW));
+ Bundle preferencesBundle = findBundle("org.eclipse.equinox.preferences");
+ update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { preferencesBundle.getLocation() }) },
+ new PermissionInfo[] {
+ new PermissionInfo(FilePermission.class.getName(), "<<ALL FILES>>", "read,write,delete"), },
+ ConditionalPermissionInfo.ALLOW));
+ Bundle appBundle = findBundle("org.eclipse.equinox.app");
+ update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { appBundle.getLocation() }) },
+ new PermissionInfo[] {
+ new PermissionInfo(FilePermission.class.getName(), "<<ALL FILES>>", "read,write,delete"), },
+ ConditionalPermissionInfo.ALLOW));
+
+ // Jackrabbit
+ Bundle jackrabbitCoreBundle = findBundle("org.apache.jackrabbit.core");
+ update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { jackrabbitCoreBundle.getLocation() }) },
+ new PermissionInfo[] {
+ new PermissionInfo(FilePermission.class.getName(), "<<ALL FILES>>", "read,write,delete"),
+ new PermissionInfo(PropertyPermission.class.getName(), "*", "read,write"),
+ new PermissionInfo(AuthPermission.class.getName(), "getLoginConfiguration", null),
+ new PermissionInfo(AuthPermission.class.getName(), "createLoginContext.Jackrabbit", null), },
+ ConditionalPermissionInfo.ALLOW));
+ Bundle jackrabbitCommonBundle = findBundle("org.apache.jackrabbit.jcr.commons");
+ update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { jackrabbitCommonBundle.getLocation() }) },
+ new PermissionInfo[] {
+ new PermissionInfo(AuthPermission.class.getName(), "createLoginContext.Jackrabbit", null), },
+ ConditionalPermissionInfo.ALLOW));
+ Bundle tikaCoreBundle = findBundle("org.apache.tika.core");
+ update.getConditionalPermissionInfos()
+ .add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { tikaCoreBundle.getLocation() }) },
+ new PermissionInfo[] { new PermissionInfo(PropertyPermission.class.getName(), "*", "read"),
+ new PermissionInfo(AdminPermission.class.getName(), "*", "*") },
+ ConditionalPermissionInfo.ALLOW));
+ Bundle luceneBundle = findBundle("org.apache.lucene");
+ update.getConditionalPermissionInfos()
+ .add(permissionAdmin.newConditionalPermissionInfo(null,
+ new ConditionInfo[] { new ConditionInfo(BundleLocationCondition.class.getName(),
+ new String[] { luceneBundle.getLocation() }) },
+ new PermissionInfo[] {
+ new PermissionInfo(FilePermission.class.getName(), "<<ALL FILES>>",
+ "read,write,delete"),
+ new PermissionInfo(PropertyPermission.class.getName(), "*", "read"),
+ new PermissionInfo(AdminPermission.class.getName(), "*", "*") },
+ ConditionalPermissionInfo.ALLOW));
+
+ // COMMIT
+ update.commit();
}
+ /** @return bundle location */
+ private String locate(Class<?> clzz) {
+ return FrameworkUtil.getBundle(clzz).getLocation();
+ }
+
+ /*
+ * PACKAGE RESTRICTED INTERFACE
+ */
+ Subject getKernelSubject() {
+ return nodeSecurity.getKernelSubject();
+ }
+
+ /*
+ * INITIALISATION
+ */
+
final void init() {
Subject.doAs(nodeSecurity.getKernelSubject(), new PrivilegedAction<Void>() {
@Override
Thread.currentThread().setContextClassLoader(Kernel.class.getClassLoader());
try {
// Listen to service publication (also ours)
- bc.addServiceListener(Kernel.this);
+ // bc.addServiceListener(Kernel.this);
if (nodeSecurity.isFirstInit())
firstInit();
- defaultLocale = new Locale(getFrameworkProp(I18N_DEFAULT_LOCALE, ENGLISH.getLanguage()));
- locales = asLocaleList(getFrameworkProp(I18N_LOCALES));
+ defaultLocale = new Locale(getFrameworkProp(NodeConstants.I18N_DEFAULT_LOCALE, ENGLISH.getLanguage()));
+ locales = asLocaleList(getFrameworkProp(NodeConstants.I18N_LOCALES));
- ServiceTracker<LogReaderService, LogReaderService> logReaderService = new ServiceTracker<LogReaderService, LogReaderService>(
- bc, LogReaderService.class, null);
- logReaderService.open();
+ // ServiceTracker<LogReaderService, LogReaderService>
+ // logReaderService = new ServiceTracker<LogReaderService,
+ // LogReaderService>(
+ // bc, LogReaderService.class, null);
+ // logReaderService.open();
logger = new NodeLogger(logReaderService.getService());
- logReaderService.close();
+ // logReaderService.close();
if (isMaintenance())
maintenanceInit();
else
normalInit();
- } catch (Exception e) {
+ } catch (Throwable e) {
log.error("Cannot initialize Argeo CMS", e);
throw new ArgeoException("Cannot initialize", e);
} finally {
// Initialise services
initTransactionManager();
+ JackrabbitRepositoryServiceFactory jrsf = new JackrabbitRepositoryServiceFactory();
+ String[] clazzes = { ManagedServiceFactory.class.getName() };
+ Hashtable<String, String> serviceProps = new Hashtable<String, String>();
+ serviceProps.put(Constants.SERVICE_PID, ArgeoJcrConstants.JACKRABBIT_REPO_FACTORY_PID);
+ bc.registerService(clazzes, jrsf, serviceProps);
+
try {
- Configuration nodeConf = conf.getConfiguration(ArgeoJcrConstants.REPO_PID_NODE);
+ Configuration nodeConf = conf.createFactoryConfiguration(ArgeoJcrConstants.JACKRABBIT_REPO_FACTORY_PID);
+ // Configuration nodeConf =
+ // conf.getConfiguration(ArgeoJcrConstants.REPO_PID_NODE);
if (nodeConf.getProperties() == null) {
- Dictionary<String, ?> props = getNodeConfigFromFrameworkProperties();
+ Dictionary<String, Object> props = getNodeConfigFromFrameworkProperties();
if (props == null) {
// TODO interactive configuration
if (log.isDebugEnabled())
+ " property defined, entering interactive mode...");
return;
}
+ // props.put(ConfigurationAdmin.SERVICE_FACTORYPID,
+ // ArgeoJcrConstants.JACKRABBIT_REPO_FACTORY_PID);
+ props.put(Constants.SERVICE_PID, ArgeoJcrConstants.REPO_PID_NODE);
nodeConf.update(props);
}
} catch (IOException e) {
throw new CmsException("Cannot get configuration", e);
}
- ManagedJackrabbitRepository nodeRepo = new ManagedJackrabbitRepository();
- String[] clazzes = { ManagedService.class.getName(), Repository.class.getName(),
- JackrabbitRepository.class.getName() };
- Hashtable<String, String> serviceProps = new Hashtable<String, String>();
- serviceProps.put(Constants.SERVICE_PID, ArgeoJcrConstants.REPO_PID_NODE);
- serviceProps.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, ArgeoJcrConstants.ALIAS_NODE);
- ServiceRegistration<?> nodeSr = bc.registerService(clazzes, nodeRepo, serviceProps);
- nodeRepo.waitForInit();
+ // ManagedJackrabbitRepository nodeRepo = new
+ // ManagedJackrabbitRepository();
+ // String[] clazzes = { ManagedService.class.getName(),
+ // Repository.class.getName(),
+ // JackrabbitRepository.class.getName() };
+ // Hashtable<String, String> serviceProps = new Hashtable<String,
+ // String>();
+ // serviceProps.put(Constants.SERVICE_PID,
+ // ArgeoJcrConstants.REPO_PID_NODE);
+ // serviceProps.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS,
+ // ArgeoJcrConstants.ALIAS_NODE);
+ // repositoryReg = bc.registerService(clazzes, nodeRepo, serviceProps);
+ // nodeRepo.waitForInit();
- new JackrabbitDataModel(bc).prepareDataModel(nodeRepo);
- prepareDataModel(nodeRepo);
+ ServiceTracker<JackrabbitRepository, JackrabbitRepository> jackrabbitSt = new ServiceTracker<>(bc,
+ JackrabbitRepository.class, new ServiceTrackerCustomizer<JackrabbitRepository, JackrabbitRepository>() {
- repository = (JackrabbitRepository) bc.getService(nodeSr.getReference());
+ @Override
+ public JackrabbitRepository addingService(ServiceReference<JackrabbitRepository> reference) {
+ JackrabbitRepository nodeRepo = bc.getService(reference);
+ // new
+ // JackrabbitDataModel(bc).prepareDataModel(nodeRepo);
+ prepareDataModel(KernelUtils.openAdminSession( nodeRepo));
+
+ // repository = (JackrabbitRepository)
+ // bc.getService(repositoryReg.getReference());
+ repository = new HomeRepository( nodeRepo);
+ Hashtable<String, String> regProps = new Hashtable<String, String>();
+ regProps.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, ArgeoJcrConstants.ALIAS_NODE);
+ repositoryReg = (ServiceRegistration<? extends Repository>) bc.registerService(Repository.class,
+ repository, regProps);
+
+ // if (repository == null)
+ // repository = new NodeRepository();
+ if (repositoryFactory == null) {
+ repositoryFactory = new OsgiJackrabbitRepositoryFactory();
+ repositoryFactory.setBundleContext(bc);
+ repositoryFactoryReg = bc.registerService(RepositoryFactory.class, repositoryFactory, null);
+ }
+ userAdmin = new NodeUserAdmin(transactionManager, repository);
+ userAdminReg = bc.registerService(UserAdmin.class, userAdmin, userAdmin.currentState());
+ return nodeRepo;
+ }
- if (repository == null)
- repository = new NodeRepository();
- if (repositoryFactory == null) {
- repositoryFactory = new OsgiJackrabbitRepositoryFactory();
- repositoryFactory.setBundleContext(bc);
- }
- userAdmin = new NodeUserAdmin(transactionManager, repository);
+ @Override
+ public void modifiedService(ServiceReference<JackrabbitRepository> reference,
+ JackrabbitRepository service) {
+ }
+
+ @Override
+ public void removedService(ServiceReference<JackrabbitRepository> reference,
+ JackrabbitRepository service) {
+ }
+ });
+ jackrabbitSt.open();
+
+ // new JackrabbitDataModel(bc).prepareDataModel(nodeRepo);
+ // prepareDataModel(nodeRepo);
+ //
+ // repository = (JackrabbitRepository)
+ // bc.getService(repositoryReg.getReference());
+ //
+ //// if (repository == null)
+ //// repository = new NodeRepository();
+ // if (repositoryFactory == null) {
+ // repositoryFactory = new OsgiJackrabbitRepositoryFactory();
+ // repositoryFactory.setBundleContext(bc);
+ // }
+ // userAdmin = new NodeUserAdmin(transactionManager, repository);
// ADMIN UIs
UserUi userUi = new UserUi();
publish();
}
- private Dictionary<String, ?> getNodeConfigFromFrameworkProperties() {
- String repoType = KernelUtils.getFrameworkProp(KernelConstants.NODE_REPO_PROP_PREFIX + RepoConf.type.name());
+ private Dictionary<String, Object> getNodeConfigFromFrameworkProperties() {
+ String repoType = KernelUtils.getFrameworkProp(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()) {
- String value = KernelUtils.getFrameworkProp(KernelConstants.NODE_REPO_PROP_PREFIX + repoConf.name());
+ String value = KernelUtils.getFrameworkProp(NodeConstants.NODE_REPO_PROP_PREFIX + repoConf.name());
if (value != null)
props.put(repoConf.name(), value);
}
return props;
}
- private void prepareDataModel(ManagedJackrabbitRepository nodeRepo) {
- Session adminSession = null;
+ /** Session is logged out. */
+ private void prepareDataModel(Session adminSession) {
try {
Set<String> processed = new HashSet<String>();
- adminSession = nodeRepo.login();
bundles: for (Bundle bundle : bc.getBundles()) {
BundleWiring wiring = bundle.adapt(BundleWiring.class);
if (wiring == null) {
}
processWiring(adminSession, wiring, processed);
}
- } catch (RepositoryException e) {
- throw new CmsException("Cannot prepare data model", e);
} finally {
JcrUtils.logoutQuietly(adminSession);
}
private void maintenanceInit() {
log.info("## MAINTENANCE ##");
- bc.addServiceListener(Kernel.this);
+ // bc.addServiceListener(Kernel.this);
initWebServer(null);
MaintenanceUi maintenanceUi = new MaintenanceUi();
Hashtable<String, String> props = new Hashtable<String, String>();
private void firstInit() {
log.info("## FIRST INIT ##");
- String nodeInit = getFrameworkProp(NODE_INIT);
+ String nodeInit = getFrameworkProp(NodeConstants.NODE_INIT);
if (nodeInit == null)
nodeInit = "../../init";
if (nodeInit.startsWith("http")) {
- remoteFirstInit(nodeInit);
+ // remoteFirstInit(nodeInit);
return;
}
File initDir;
}
}
- private void remoteFirstInit(String uri) {
- try {
- repository = new NodeRepository();
- repositoryFactory = new OsgiJackrabbitRepositoryFactory();
- Repository remoteRepository = ArgeoJcrUtils.getRepositoryByUri(repositoryFactory, uri);
- Session remoteSession = remoteRepository.login(new SimpleCredentials("root", "demo".toCharArray()), "main");
- Session localSession = this.repository.login();
- // FIXME register node type
- // if (false)
- // CndImporter.registerNodeTypes(null, localSession);
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- remoteSession.exportSystemView("/", out, true, false);
- ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
- localSession.importXML("/", in, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
- // JcrUtils.copy(remoteSession.getRootNode(),
- // localSession.getRootNode());
- } catch (Exception e) {
- throw new CmsException("Cannot first init from " + uri, e);
- }
- }
+ // private void remoteFirstInit(String uri) {
+ // try {
+ // repository = new NodeRepository();
+ // repositoryFactory = new OsgiJackrabbitRepositoryFactory();
+ // Repository remoteRepository =
+ // ArgeoJcrUtils.getRepositoryByUri(repositoryFactory, uri);
+ // Session remoteSession = remoteRepository.login(new
+ // SimpleCredentials("root", "demo".toCharArray()), "main");
+ // Session localSession = this.repository.login();
+ // // FIXME register node type
+ // // if (false)
+ // // CndImporter.registerNodeTypes(null, localSession);
+ // ByteArrayOutputStream out = new ByteArrayOutputStream();
+ // remoteSession.exportSystemView("/", out, true, false);
+ // ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
+ // localSession.importXML("/", in,
+ // ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
+ // // JcrUtils.copy(remoteSession.getRootNode(),
+ // // localSession.getRootNode());
+ // } catch (Exception e) {
+ // throw new CmsException("Cannot first init from " + uri, e);
+ // }
+ // }
/** Can be null */
private ConfigurationAdmin findConfigurationAdmin() {
- configurationAdmin = bc.getServiceReference(ConfigurationAdmin.class);
- if (configurationAdmin == null) {
- return null;
- }
- return bc.getService(configurationAdmin);
+ // configurationAdmin =
+ // bc.getServiceReference(ConfigurationAdmin.class);
+ // if (configurationAdmin == null) {
+ // return null;
+ // }
+ // return bc.getService(configurationAdmin);
+ return configurationAdmin.getService();
}
/** Can be null */
// File tmBaseDir = new File(getFrameworkProp(TRANSACTIONS_HOME,
// getOsgiInstancePath(DIR_TRANSACTIONS)));
- File tmBaseDir = bc.getDataFile(DIR_TRANSACTIONS);
+ Bundle bitronixBundle = FrameworkUtil.getBundle(bitronix.tm.Configuration.class);
+ File tmBaseDir = bitronixBundle.getDataFile(DIR_TRANSACTIONS);
+ // File tmBaseDir = bc.getDataFile(DIR_TRANSACTIONS);
File tmDir1 = new File(tmBaseDir, "btm1");
tmDir1.mkdirs();
tmConf.setLogPart1Filename(new File(tmDir1, tmDir1.getName() + ".tlog").getAbsolutePath());
transactionSynchronizationRegistry = getTransactionSynchronizationRegistry();
}
- private void initWebServer(ConfigurationAdmin conf) {
+ private void initWebServer(final ConfigurationAdmin conf) {
String httpPort = getFrameworkProp("org.osgi.service.http.port");
String httpsPort = getFrameworkProp("org.osgi.service.http.port.secure");
try {
if (httpPort != null || httpsPort != null) {
- Hashtable<String, Object> jettyProps = new Hashtable<String, Object>();
+ final Hashtable<String, Object> jettyProps = new Hashtable<String, Object>();
if (httpPort != null) {
jettyProps.put(JettyConstants.HTTP_PORT, httpPort);
jettyProps.put(JettyConstants.HTTP_ENABLED, true);
return;
Configuration jettyConf = conf.createFactoryConfiguration(JETTY_FACTORY_PID, null);
jettyConf.update(jettyProps);
+
} else {
JettyConfigurator.startServer("default", jettyProps);
}
}
}
- @SuppressWarnings("unchecked")
private void publish() {
// Logging
utReg = bc.registerService(UserTransaction.class, transactionManager, null);
tsrReg = bc.registerService(TransactionSynchronizationRegistry.class, transactionSynchronizationRegistry, null);
// User admin
- userAdminReg = bc.registerService(UserAdmin.class, userAdmin, userAdmin.currentState());
+ // userAdminReg = bc.registerService(UserAdmin.class, userAdmin,
+ // userAdmin.currentState());
// JCR
- Hashtable<String, String> regProps = new Hashtable<String, String>();
- regProps.put(JCR_REPOSITORY_ALIAS, ALIAS_NODE);
- repositoryReg = (ServiceRegistration<? extends Repository>) bc.registerService(
- new String[] { Repository.class.getName(), JackrabbitRepository.class.getName() }, repository,
- regProps);
- repositoryFactoryReg = bc.registerService(RepositoryFactory.class, repositoryFactory, null);
+ // Hashtable<String, String> regProps = new Hashtable<String, String>();
+ // regProps.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS,
+ // ArgeoJcrConstants.ALIAS_NODE);
+ // repositoryReg = (ServiceRegistration<? extends Repository>)
+ // bc.registerService(Repository.class, repository,
+ // regProps);
+ // repositoryFactoryReg = bc.registerService(RepositoryFactory.class,
+ // repositoryFactory, null);
}
void destroy() {
nodeHttp.destroy();
if (userAdmin != null)
userAdmin.destroy();
- if (repository != null)
- repository.shutdown();
+ // if (repository != null)
+ // repository.shutdown();
if (transactionManager != null)
transactionManager.shutdown();
- bc.removeServiceListener(this);
+ // bc.removeServiceListener(this);
// Clean hanging threads from Jackrabbit
TransientFileFactory.shutdown();
loggerReg.unregister();
}
- @Override
- public void serviceChanged(ServiceEvent event) {
- ServiceReference<?> sr = event.getServiceReference();
- Object service = bc.getService(sr);
- if (service instanceof Repository) {
- Object jcrRepoAlias = sr.getProperty(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS);
- if (jcrRepoAlias != null) {// JCR repository
- String alias = jcrRepoAlias.toString();
- Repository repository = (Repository) bc.getService(sr);
- Map<String, Object> props = new HashMap<String, Object>();
- for (String key : sr.getPropertyKeys())
- props.put(key, sr.getProperty(key));
- if (ServiceEvent.REGISTERED == event.getType()) {
- try {
- // repositoryFactory.register(repository, props);
- dataHttp.registerRepositoryServlets(alias, repository);
- } catch (Exception e) {
- throw new CmsException("Could not publish JCR repository " + alias, e);
- }
- } else if (ServiceEvent.UNREGISTERING == event.getType()) {
- // repositoryFactory.unregister(repository, props);
- dataHttp.unregisterRepositoryServlets(alias);
- }
- }
- } else if (service instanceof ExtendedHttpService) {
- if (ServiceEvent.REGISTERED == event.getType()) {
- addHttpService(sr);
- } else if (ServiceEvent.UNREGISTERING == event.getType()) {
- dataHttp.destroy();
- dataHttp = null;
- }
- }
- }
-
- private void addHttpService(ServiceReference<?> sr) {
+ // @Override
+ // public void serviceChanged(ServiceEvent event) {
+ // ServiceReference<?> sr = event.getServiceReference();
+ // Object service = bc.getService(sr);
+ // if (service instanceof Repository) {
+ // Object jcrRepoAlias =
+ // sr.getProperty(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS);
+ // if (jcrRepoAlias != null) {// JCR repository
+ // String alias = jcrRepoAlias.toString();
+ // Repository repository = (Repository) bc.getService(sr);
+ // Map<String, Object> props = new HashMap<String, Object>();
+ // for (String key : sr.getPropertyKeys())
+ // props.put(key, sr.getProperty(key));
+ // if (ServiceEvent.REGISTERED == event.getType()) {
+ // try {
+ // // repositoryFactory.register(repository, props);
+ // dataHttp.registerRepositoryServlets(alias, repository);
+ // } catch (Exception e) {
+ // throw new CmsException("Could not publish JCR repository " + alias, e);
+ // }
+ // } else if (ServiceEvent.UNREGISTERING == event.getType()) {
+ // // repositoryFactory.unregister(repository, props);
+ // dataHttp.unregisterRepositoryServlets(alias);
+ // }
+ // }
+ // }
+ // // else if (service instanceof ExtendedHttpService) {
+ // // if (ServiceEvent.REGISTERED == event.getType()) {
+ // // addHttpService(sr);
+ // // } else if (ServiceEvent.UNREGISTERING == event.getType()) {
+ // // dataHttp.destroy();
+ // // dataHttp = null;
+ // // }
+ // // }
+ // }
+
+ private HttpService addHttpService(ServiceReference<HttpService> sr) {
// for (String key : sr.getPropertyKeys())
// log.debug(key + "=" + sr.getProperty(key));
- ExtendedHttpService httpService = (ExtendedHttpService) bc.getService(sr);
+ HttpService httpService = bc.getService(sr);
// TODO find constants
Object httpPort = sr.getProperty("http.port");
Object httpsPort = sr.getProperty("https.port");
nodeHttp = new NodeHttp(httpService, bc);
if (log.isDebugEnabled())
log.debug(httpPortsMsg(httpPort, httpsPort));
+ return httpService;
}
private String httpPortsMsg(Object httpPort, Object httpsPort) {
log.debug("Sleep accuracy: " + String.format("%.2f", 100 - (sleepAccuracy * 100 - 100)) + " %");
}
+ private class PrepareStc<T> implements ServiceTrackerCustomizer<T, T> {
+
+ @Override
+ public T addingService(ServiceReference<T> reference) {
+ T service = bc.getService(reference);
+ System.out.println("addingService " + service);
+ return service;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<T> reference, T service) {
+ System.out.println("modifiedService " + service);
+ }
+
+ @Override
+ public void removedService(ServiceReference<T> reference, T service) {
+ System.out.println("removedService " + service);
+ }
+
+ }
+
+ private class PrepareHttpStc implements ServiceTrackerCustomizer<HttpService, HttpService> {
+
+ @Override
+ public HttpService addingService(ServiceReference<HttpService> reference) {
+ HttpService httpService = addHttpService(reference);
+ return httpService;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<HttpService> reference, HttpService service) {
+ }
+
+ @Override
+ public void removedService(ServiceReference<HttpService> reference, HttpService service) {
+ dataHttp.destroy();
+ dataHttp = null;
+ }
+
+ }
+
/** Workaround for blocking Gogo shell by system shutdown. */
private class GogoShellKiller extends Thread {
package org.argeo.cms.internal.kernel;
public interface KernelConstants {
- final static String NODE_INIT = "argeo.node.init";
+
- // Node
- /** Properties configuring the node repository */
- final static String NODE_REPO_PROP_PREFIX = "argeo.node.repo.";
- // final static String REPO_HOME = "argeo.node.repo.home";
- // final static String REPO_TYPE = "argeo.node.repo.type";
- // final static String REPO_CONFIGURATION = "argeo.node.repo.configuration";
- // final static String REPO_DEFAULT_WORKSPACE =
- // "argeo.node.repo.defaultWorkspace";
- // final static String REPO_DBURL = "argeo.node.repo.dburl";
- // final static String REPO_DBUSER = "argeo.node.repo.dbuser";
- // final static String REPO_DBPASSWORD = "argeo.node.repo.dbpassword";
- // final static String REPO_MAX_POOL_SIZE = "argeo.node.repo.maxPoolSize";
- // final static String REPO_MAX_CACHE_MB = "argeo.node.repo.maxCacheMB";
- // final static String REPO_BUNDLE_CACHE_MB =
- // "argeo.node.repo.bundleCacheMB";
- // final static String REPO_EXTRACTOR_POOL_SIZE =
- // "argeo.node.repo.extractorPoolSize";
- // final static String REPO_SEARCH_CACHE_SIZE =
- // "argeo.node.repo.searchCacheSize";
- // final static String REPO_MAX_VOLATILE_INDEX_SIZE =
- // "argeo.node.repo.maxVolatileIndexSize";
+ //final static String TRANSACTIONS_HOME = "argeo.node.transactions.home";
- final static String TRANSACTIONS_HOME = "argeo.node.transactions.home";
-
- final static String I18N_DEFAULT_LOCALE = "argeo.i18n.defaultLocale";
- final static String I18N_LOCALES = "argeo.i18n.locales";
-
- // Node Security
- final static String ROLES_URI = "argeo.node.roles.uri";
- /** URI to an LDIF file or LDAP server used as initialization or backend */
- final static String USERADMIN_URIS = "argeo.node.useradmin.uris";
final static String[] DEFAULT_CNDS = { "/org/argeo/jcr/argeo.cnd", "/org/argeo/cms/cms.cnd" };
// Directories
import java.io.File;
import java.io.IOException;
import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.PrivilegedAction;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.TreeSet;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import org.apache.commons.logging.Log;
import org.argeo.cms.CmsException;
import org.argeo.cms.auth.AuthConstants;
+import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
/** Package utilities */
class KernelUtils implements KernelConstants {
try {
props.load(cl.getResourceAsStream(resource));
} catch (IOException e) {
- throw new CmsException("Cannot load " + resource
- + " from classpath", e);
+ throw new CmsException("Cannot load " + resource + " from classpath", e);
}
return asDictionary(props);
}
}
static File getOsgiInstanceDir() {
- return new File(Activator.getBundleContext()
- .getProperty(OSGI_INSTANCE_AREA).substring("file:".length()))
+ return new File(getBundleContext().getProperty(OSGI_INSTANCE_AREA).substring("file:".length()))
.getAbsoluteFile();
}
+ static URI getOsgiInstanceUri(String relativePath) {
+ String osgiInstanceBaseUri = getFrameworkProp(OSGI_INSTANCE_AREA);
+ try {
+ return new URI(osgiInstanceBaseUri + (relativePath != null ? relativePath : ""));
+ } catch (URISyntaxException e) {
+ throw new CmsException("Cannot get OSGi instance URI for " + relativePath, e);
+ }
+ }
+
static String getOsgiInstancePath(String relativePath) {
try {
if (relativePath == null)
return getOsgiInstanceDir().getCanonicalPath();
else
- return new File(getOsgiInstanceDir(), relativePath)
- .getCanonicalPath();
+ return new File(getOsgiInstanceDir(), relativePath).getCanonicalPath();
} catch (IOException e) {
- throw new CmsException("Cannot get instance path for "
- + relativePath, e);
+ throw new CmsException("Cannot get instance path for " + relativePath, e);
}
}
static File getOsgiConfigurationFile(String relativePath) {
try {
- return new File(new URI(Activator.getBundleContext().getProperty(
- OSGI_CONFIGURATION_AREA)
- + relativePath)).getCanonicalFile();
+ return new File(new URI(getBundleContext().getProperty(OSGI_CONFIGURATION_AREA) + relativePath))
+ .getCanonicalFile();
} catch (Exception e) {
- throw new CmsException("Cannot get configuration file for "
- + relativePath, e);
+ throw new CmsException("Cannot get configuration file for " + relativePath, e);
}
}
static String getFrameworkProp(String key, String def) {
- String value = Activator.getBundleContext().getProperty(key);
+ String value = getBundleContext().getProperty(key);
if (value == null)
return def;
return value;
Subject subject = new Subject();
LoginContext lc;
try {
- lc = new LoginContext(AuthConstants.LOGIN_CONTEXT_ANONYMOUS,
- subject);
+ lc = new LoginContext(AuthConstants.LOGIN_CONTEXT_ANONYMOUS, subject);
lc.login();
return subject;
} catch (LoginException e) {
static void logRequestHeaders(Log log, HttpServletRequest request) {
if (!log.isDebugEnabled())
return;
- for (Enumeration<String> headerNames = request.getHeaderNames(); headerNames
- .hasMoreElements();) {
+ for (Enumeration<String> headerNames = request.getHeaderNames(); headerNames.hasMoreElements();) {
String headerName = headerNames.nextElement();
Object headerValue = request.getHeader(headerName);
log.debug(headerName + ": " + headerValue);
}
- log.debug(request.getRequestURI()+"\n");
+ log.debug(request.getRequestURI() + "\n");
}
static void logFrameworkProperties(Log log) {
- BundleContext bc = Activator.getBundleContext();
- for (Object sysProp : new TreeSet<Object>(System.getProperties()
- .keySet())) {
+ BundleContext bc = getBundleContext();
+ for (Object sysProp : new TreeSet<Object>(System.getProperties().keySet())) {
log.debug(sysProp + "=" + bc.getProperty(sysProp.toString()));
}
// String[] keys = { Constants.FRAMEWORK_STORAGE,
// log.debug(key + "=" + bc.getProperty(key));
}
+ static Session openAdminSession(Repository repository) {
+ return openAdminSession(repository, null);
+ }
+
+ static Session openAdminSession(final Repository repository, final String workspaceName) {
+ ClassLoader currentCl = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(KernelUtils.class.getClassLoader());
+ LoginContext loginContext;
+ try {
+ loginContext = new LoginContext(AuthConstants.LOGIN_CONTEXT_DATA_ADMIN);
+ loginContext.login();
+ } catch (LoginException e1) {
+ throw new CmsException("Could not login as data admin", e1);
+ } finally {
+ Thread.currentThread().setContextClassLoader(currentCl);
+ }
+ return Subject.doAs(loginContext.getSubject(), new PrivilegedAction<Session>() {
+
+ @Override
+ public Session run() {
+ try {
+ return repository.login(workspaceName);
+ } catch (RepositoryException e) {
+ throw new CmsException("Cannot open admin session", e);
+ }
+ }
+
+ });
+ }
+
+ /**
+ * @return the {@link BundleContext} of the {@link Bundle} which provided
+ * this class, never null.
+ * @throws CmsException
+ * if the related bundle is not active
+ */
+ public static BundleContext getBundleContext(Class<?> clzz) {
+ Bundle bundle = FrameworkUtil.getBundle(clzz);
+ BundleContext bc = bundle.getBundleContext();
+ if (bc == null)
+ throw new CmsException("Bundle " + bundle.getSymbolicName() + " is not active");
+ return bc;
+ }
+
+ private static BundleContext getBundleContext() {
+ return getBundleContext(KernelUtils.class);
+ }
+
private KernelUtils() {
}
import org.argeo.cms.util.CmsUtils;
import org.argeo.jcr.ArgeoJcrConstants;
import org.argeo.jcr.JcrUtils;
-import org.eclipse.equinox.http.servlet.ExtendedHttpService;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.HttpService;
/**
* Intercepts and enriches http access, mainly focusing on security and
private BundleContext bc;
- NodeHttp(ExtendedHttpService httpService, BundleContext bc) {
+ NodeHttp(HttpService httpService, BundleContext bc) {
this.bc = bc;
// rootFilter = new RootFilter();
// dosFilter = new CustomDosFilter();
} else if (severity == LogService.LOG_WARNING)
pluginLog.warn(status.getMessage(), status.getException());
else if (severity == LogService.LOG_INFO && pluginLog.isDebugEnabled())
- pluginLog.debug(status.getMessage(), status.getException());
+ pluginLog.debug(
+ status.getMessage() + (status.getServiceReference() != null ?" "+ status.getServiceReference() : ""),
+ status.getException());
else if (severity == LogService.LOG_DEBUG && pluginLog.isTraceEnabled())
pluginLog.trace(status.getMessage(), status.getException());
}
// ARGEO LOGGER
//
- public synchronized void register(ArgeoLogListener listener,
- Integer numberOfPreviousEvents) {
+ public synchronized void register(ArgeoLogListener listener, Integer numberOfPreviousEvents) {
String username = CurrentUser.getUsername();
if (username == null)
- throw new ArgeoException(
- "Only authenticated users can register a log listener");
+ throw new ArgeoException("Only authenticated users can register a log listener");
if (!userListeners.containsKey(username)) {
- List<ArgeoLogListener> lst = Collections
- .synchronizedList(new ArrayList<ArgeoLogListener>());
+ List<ArgeoLogListener> lst = Collections.synchronizedList(new ArrayList<ArgeoLogListener>());
userListeners.put(username, lst);
}
userListeners.get(username).add(listener);
- List<LogEvent> lastEvents = logDispatcherThread.getLastEvents(username,
- numberOfPreviousEvents);
+ List<LogEvent> lastEvents = logDispatcherThread.getLastEvents(username, numberOfPreviousEvents);
for (LogEvent evt : lastEvents)
dispatchEvent(listener, evt);
}
- public synchronized void registerForAll(ArgeoLogListener listener,
- Integer numberOfPreviousEvents, boolean everything) {
+ public synchronized void registerForAll(ArgeoLogListener listener, Integer numberOfPreviousEvents,
+ boolean everything) {
if (everything)
everythingListeners.add(listener);
else
allUsersListeners.add(listener);
- List<LogEvent> lastEvents = logDispatcherThread.getLastEvents(null,
- numberOfPreviousEvents);
+ List<LogEvent> lastEvents = logDispatcherThread.getLastEvents(null, numberOfPreviousEvents);
for (LogEvent evt : lastEvents)
if (everything || evt.getUsername() != null)
dispatchEvent(listener, evt);
if (username == null)// FIXME
return;
if (!userListeners.containsKey(username))
- throw new ArgeoException("No user listeners " + listener
- + " registered for user " + username);
+ throw new ArgeoException("No user listeners " + listener + " registered for user " + username);
if (!userListeners.get(username).contains(listener))
- throw new ArgeoException("No user listeners " + listener
- + " registered for user " + username);
+ throw new ArgeoException("No user listeners " + listener + " registered for user " + username);
userListeners.get(username).remove(listener);
if (userListeners.get(username).isEmpty())
userListeners.remove(username);
return configuration;
}
- /** Reloads configuration (if the configuration {@link Properties} is set) */
+ /**
+ * Reloads configuration (if the configuration {@link Properties} is set)
+ */
protected void reloadConfiguration() {
if (configuration != null) {
LogManager.resetConfiguration();
try {
log4jLevel = Level.toLevel(level);
} catch (Exception e) {
- System.err
- .println("Log4j level could not be set for level '"
- + level + "', resetting it to null.");
+ System.err.println("Log4j level could not be set for level '" + level + "', resetting it to null.");
e.printStackTrace();
level = null;
}
- if (log4jLevel != null
- && !event.getLoggingEvent().getLevel()
- .isGreaterOrEqual(log4jLevel)) {
+ if (log4jLevel != null && !event.getLoggingEvent().getLevel().isGreaterOrEqual(log4jLevel)) {
return;
}
}
try {
// admin listeners
- Iterator<ArgeoLogListener> everythingIt = everythingListeners
- .iterator();
+ Iterator<ArgeoLogListener> everythingIt = everythingListeners.iterator();
while (everythingIt.hasNext())
dispatchEvent(everythingIt.next(), event);
if (event.getUsername() != null) {
- Iterator<ArgeoLogListener> allUsersIt = allUsersListeners
- .iterator();
+ Iterator<ArgeoLogListener> allUsersIt = allUsersListeners.iterator();
while (allUsersIt.hasNext())
dispatchEvent(allUsersIt.next(), event);
if (userListeners.containsKey(event.getUsername())) {
- Iterator<ArgeoLogListener> userIt = userListeners.get(
- event.getUsername()).iterator();
+ Iterator<ArgeoLogListener> userIt = userListeners.get(event.getUsername()).iterator();
while (userIt.hasNext())
dispatchEvent(userIt.next(), event);
}
protected void dispatchEvent(ArgeoLogListener logListener, LogEvent evt) {
LoggingEvent event = evt.getLoggingEvent();
- logListener.appendLog(evt.getUsername(), event.getTimeStamp(), event
- .getLevel().toString(), event.getLoggerName(), event
- .getThreadName(), event.getMessage(), event
- .getThrowableStrRep());
+ logListener.appendLog(evt.getUsername(), event.getTimeStamp(), event.getLevel().toString(),
+ event.getLoggerName(), event.getThreadName(), event.getMessage(), event.getThrowableStrRep());
}
private class AppenderImpl extends AppenderSkeleton {
lastEvents.add(loggingEvent);
}
- public synchronized List<LogEvent> getLastEvents(String username,
- Integer maxCount) {
+ public synchronized List<LogEvent> getLastEvents(String username, Integer maxCount) {
LinkedList<LogEvent> evts = new LinkedList<LogEvent>();
- ListIterator<LogEvent> it = lastEvents.listIterator(lastEvents
- .size());
+ ListIterator<LogEvent> it = lastEvents.listIterator(lastEvents.size());
int count = 0;
while (it.hasPrevious() && (count < maxCount)) {
LogEvent evt = it.previous();
+++ /dev/null
-package org.argeo.cms.internal.kernel;
-
-import org.argeo.jackrabbit.JackrabbitWrapper;
-import org.argeo.jcr.ArgeoJcrConstants;
-
-/** Jacrabbit based data layer */
-class NodeRepository extends JackrabbitWrapper implements KernelConstants,
- ArgeoJcrConstants {
-// private static Log log = LogFactory.getLog(NodeRepository.class);
-//
-// private RepositoryContext repositoryContext;
-//
-// public NodeRepository() {
-// setBundleContext(Activator.getBundleContext());
-// JackrabbitNodeType type = JackrabbitNodeType.valueOf(prop(REPO_TYPE,
-// h2.name()));
-// try {
-// repositoryContext = createNode(type);
-// setCndFiles(Arrays.asList(DEFAULT_CNDS));
-// prepareDataModel();
-// } catch (Exception e) {
-// throw new ArgeoException(
-// "Cannot create Jackrabbit repository of type " + type, e);
-// }
-// }
-//
-// public void destroy() {
-// ((RepositoryImpl) getRepository()).shutdown();
-// }
-//
-// RepositoryStatisticsImpl getRepositoryStatistics() {
-// return repositoryContext.getRepositoryStatistics();
-// }
-//
-// private RepositoryConfig getConfiguration(JackrabbitNodeType type,
-// Hashtable<String, Object> vars) throws RepositoryException {
-// ClassLoader cl = getClass().getClassLoader();
-// InputStream in = null;
-// try {
-// final String base = "/org/argeo/cms/internal/kernel";
-// switch (type) {
-// case h2:
-// in = cl.getResourceAsStream(base + "/repository-h2.xml");
-// break;
-// case postgresql:
-// in = cl.getResourceAsStream(base + "/repository-postgresql.xml");
-// break;
-// case memory:
-// in = cl.getResourceAsStream(base + "/repository-memory.xml");
-// break;
-// case localfs:
-// in = cl.getResourceAsStream(base + "/repository-localfs.xml");
-// break;
-// default:
-// throw new CmsException("Unsupported node type " + type);
-// }
-//
-// if (in == null)
-// throw new CmsException("Repository configuration not found");
-// InputSource config = new InputSource(in);
-// Properties jackrabbitProps = new Properties();
-// jackrabbitProps.putAll(vars);
-// RepositoryConfig repositoryConfig = RepositoryConfig.create(config,
-// jackrabbitProps);
-// return repositoryConfig;
-// } finally {
-// IOUtils.closeQuietly(in);
-// }
-// }
-//
-// private Hashtable<String, Object> getConfigurationProperties(
-// JackrabbitNodeType type) {
-// // use Hashtable to ease integration with Properties
-// Hashtable<String, Object> defaults = new Hashtable<String, Object>();
-//
-// // home
-// File osgiInstanceDir = KernelUtils.getOsgiInstanceDir();
-// File homeDir = new File(osgiInstanceDir, DIR_NODE);
-// // home cannot be overridden
-// defaults.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
-// homeDir.getAbsolutePath());
-//
-// // common
-// setProp(defaults, REPO_DEFAULT_WORKSPACE, "main");
-// setProp(defaults, REPO_MAX_POOL_SIZE, "10");
-// // Jackrabbit defaults
-// setProp(defaults, REPO_BUNDLE_CACHE_MB, "8");
-// // See http://wiki.apache.org/jackrabbit/Search
-// setProp(defaults, REPO_EXTRACTOR_POOL_SIZE, "0");
-// setProp(defaults, REPO_SEARCH_CACHE_SIZE, "1000");
-// setProp(defaults, REPO_MAX_VOLATILE_INDEX_SIZE, "1048576");
-//
-// // specific
-// String dburl;
-// switch (type) {
-// case h2:
-// dburl = "jdbc:h2:" + homeDir.getPath() + "/h2/repository";
-// setProp(defaults, REPO_DBURL, dburl);
-// setProp(defaults, REPO_DBUSER, "sa");
-// setProp(defaults, REPO_DBPASSWORD, "");
-// break;
-// case postgresql:
-// dburl = "jdbc:postgresql://localhost/demo";
-// setProp(defaults, REPO_DBURL, dburl);
-// setProp(defaults, REPO_DBUSER, "argeo");
-// setProp(defaults, REPO_DBPASSWORD, "argeo");
-// break;
-// case memory:
-// break;
-// case localfs:
-// break;
-// default:
-// throw new CmsException("Unsupported node type " + type);
-// }
-// return defaults;
-// }
-//
-// private void setProp(Dictionary<String, Object> props, String key,
-// String defaultValue) {
-// String value = prop(key, defaultValue);
-// props.put(key, value);
-// }
-//
-// private String prop(String key, String defaultValue) {
-// // TODO use OSGi CM instead of Framework/System properties
-// return KernelUtils.getFrameworkProp(key, defaultValue);
-// }
-//
-// private RepositoryContext createNode(JackrabbitNodeType type)
-// throws RepositoryException {
-// Hashtable<String, Object> vars = getConfigurationProperties(type);
-// RepositoryConfig repositoryConfig = getConfiguration(type, vars);
-// RepositoryContext repositoryContext = createJackrabbitRepository(repositoryConfig);
-// RepositoryImpl repository = repositoryContext.getRepository();
-//
-// // cache
-// String maxCacheMbStr = prop(REPO_MAX_CACHE_MB, null);
-// if (maxCacheMbStr != null) {
-// Integer maxCacheMB = Integer.parseInt(maxCacheMbStr);
-// CacheManager cacheManager = repository.getCacheManager();
-// cacheManager.setMaxMemory(maxCacheMB * 1024l * 1024l);
-// cacheManager.setMaxMemoryPerCache((maxCacheMB / 4) * 1024l * 1024l);
-// }
-//
-// // wrap the repository
-// setRepository(repository);
-// return repositoryContext;
-// }
-//
-// private RepositoryContext createJackrabbitRepository(
-// RepositoryConfig repositoryConfig) throws RepositoryException {
-// long begin = System.currentTimeMillis();
-// //
-// // Actual repository creation
-// //
-// RepositoryContext repositoryContext = RepositoryContext
-// .create(repositoryConfig);
-//
-// double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
-// if (log.isTraceEnabled())
-// log.trace("Created Jackrabbit repository in " + duration
-// + " s, home: " + repositoryConfig.getHomeDir());
-//
-// return repositoryContext;
-// }
-}
import java.util.Map;
import java.util.Set;
-import javax.jcr.Node;
import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.security.Privilege;
import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
import javax.transaction.TransactionManager;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
import org.argeo.cms.CmsException;
import org.argeo.cms.auth.AuthConstants;
-import org.argeo.jcr.ArgeoJcrConstants;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.ArgeoTypes;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.UserJcrUtils;
+import org.argeo.node.NodeConstants;
import org.argeo.osgi.useradmin.LdapUserAdmin;
import org.argeo.osgi.useradmin.LdifUserAdmin;
import org.argeo.osgi.useradmin.UserAdminConf;
import org.argeo.osgi.useradmin.UserDirectory;
import org.argeo.osgi.useradmin.UserDirectoryException;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
import org.osgi.service.useradmin.Authorization;
import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.User;
import org.osgi.service.useradmin.UserAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
import bitronix.tm.resource.ehcache.EhCacheXAResourceProducer;
}
}
+ private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext();
+
// DAOs
private UserAdmin nodeRoles = null;
private Map<LdapName, UserAdmin> userAdmins = new HashMap<LdapName, UserAdmin>();
// JCR
- /** The home base path. */
- private String homeBasePath = "/home";
- private String peopleBasePath = ArgeoJcrConstants.PEOPLE_BASE_PATH;
- private Repository repository;
- private Session adminSession;
+ // private String homeBasePath = "/home";
+ // private String peopleBasePath = ArgeoJcrConstants.PEOPLE_BASE_PATH;
+ // private Repository repository;
+ // private Session adminSession;
private final String cacheName = UserDirectory.class.getName();
- public NodeUserAdmin(TransactionManager transactionManager, Repository repository) {
- this.repository = repository;
- try {
- this.adminSession = this.repository.login();
- } catch (RepositoryException e) {
- throw new CmsException("Cannot log-in", e);
+ public NodeUserAdmin() {
+ // DAOs
+ File nodeBaseDir = new File(getOsgiInstanceDir(), DIR_NODE);
+ nodeBaseDir.mkdirs();
+ String userAdminUri = getFrameworkProp(NodeConstants.USERADMIN_URIS);
+ initUserAdmins(userAdminUri, nodeBaseDir);
+ String nodeRolesUri = getFrameworkProp(NodeConstants.ROLES_URI);
+ initNodeRoles(nodeRolesUri, nodeBaseDir);
+
+ new ServiceTracker<>(bc, TransactionManager.class, new TransactionManagerStc()).open();
+ }
+
+ private class TransactionManagerStc implements ServiceTrackerCustomizer<TransactionManager, TransactionManager> {
+
+ @Override
+ public TransactionManager addingService(ServiceReference<TransactionManager> reference) {
+ TransactionManager transactionManager = bc.getService(reference);
+ ((UserDirectory) nodeRoles).setTransactionManager(transactionManager);
+ for (UserAdmin userAdmin : userAdmins.values()) {
+ if (userAdmin instanceof UserDirectory)
+ ((UserDirectory) userAdmin).setTransactionManager(transactionManager);
+ }
+ if (log.isDebugEnabled())
+ log.debug("Set transaction manager");
+ return transactionManager;
}
+ @Override
+ public void modifiedService(ServiceReference<TransactionManager> reference, TransactionManager service) {
+ }
+
+ @Override
+ public void removedService(ServiceReference<TransactionManager> reference, TransactionManager service) {
+ ((UserDirectory) nodeRoles).setTransactionManager(null);
+ for (UserAdmin userAdmin : userAdmins.values()) {
+ if (userAdmin instanceof UserDirectory)
+ ((UserDirectory) userAdmin).setTransactionManager(null);
+ }
+ }
+
+ }
+
+ @Deprecated
+ public NodeUserAdmin(TransactionManager transactionManager, Repository repository) {
+ // this.repository = repository;
+ // try {
+ // this.adminSession = this.repository.login();
+ // } catch (RepositoryException e) {
+ // throw new CmsException("Cannot log-in", e);
+ // }
+
// DAOs
File nodeBaseDir = new File(getOsgiInstanceDir(), DIR_NODE);
nodeBaseDir.mkdirs();
- String userAdminUri = getFrameworkProp(USERADMIN_URIS);
+ String userAdminUri = getFrameworkProp(NodeConstants.USERADMIN_URIS);
initUserAdmins(userAdminUri, nodeBaseDir);
- String nodeRolesUri = getFrameworkProp(ROLES_URI);
+ String nodeRolesUri = getFrameworkProp(NodeConstants.ROLES_URI);
initNodeRoles(nodeRolesUri, nodeBaseDir);
// Transaction manager
}
// JCR
- initJcr(adminSession);
+ // initJcr(adminSession);
}
- Dictionary<String, ?> currentState() {
+ Dictionary<String, Object> currentState() {
Dictionary<String, Object> res = new Hashtable<String, Object>();
for (LdapName name : userAdmins.keySet()) {
StringBuilder buf = new StringBuilder();
}
Authorization authorization = new NodeAuthorization(rawAuthorization.getName(), rawAuthorization.toString(),
systemRoles, rawAuthorization.getRoles());
- syncJcr(adminSession, authorization);
+ // syncJcr(adminSession, authorization);
return authorization;
}
/*
* JCR
*/
- private void initJcr(Session adminSession) {
- try {
- JcrUtils.mkdirs(adminSession, homeBasePath);
- JcrUtils.mkdirs(adminSession, peopleBasePath);
- adminSession.save();
-
- JcrUtils.addPrivilege(adminSession, homeBasePath, AuthConstants.ROLE_USER_ADMIN, Privilege.JCR_READ);
- JcrUtils.addPrivilege(adminSession, peopleBasePath, AuthConstants.ROLE_USER_ADMIN, Privilege.JCR_ALL);
- adminSession.save();
- } catch (RepositoryException e) {
- throw new CmsException("Cannot initialize node user admin", e);
- }
- }
-
- private Node syncJcr(Session session, Authorization authorization) {
- // TODO check user name validity (e.g. should not start by ROLE_)
- String username = authorization.getName();
- // String[] roles = authorization.getRoles();
- try {
- Node userHome = UserJcrUtils.getUserHome(session, username);
- if (userHome == null) {
- String homePath = generateUserPath(homeBasePath, username);
- if (session.itemExists(homePath))// duplicate user id
- userHome = session.getNode(homePath).getParent().addNode(JcrUtils.lastPathElement(homePath));
- else
- userHome = JcrUtils.mkdirs(session, homePath);
- // userHome = JcrUtils.mkfolders(session, homePath);
- userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME);
- userHome.setProperty(ArgeoNames.ARGEO_USER_ID, username);
- session.save();
-
- JcrUtils.clearAccessControList(session, homePath, username);
- JcrUtils.addPrivilege(session, homePath, username, Privilege.JCR_ALL);
- }
-
- Node userProfile = UserJcrUtils.getUserProfile(session, username);
- // new user
- if (userProfile == null) {
- String personPath = generateUserPath(peopleBasePath, username);
- Node personBase;
- if (session.itemExists(personPath))// duplicate user id
- personBase = session.getNode(personPath).getParent().addNode(JcrUtils.lastPathElement(personPath));
- else
- personBase = JcrUtils.mkdirs(session, personPath);
- userProfile = personBase.addNode(ArgeoNames.ARGEO_PROFILE);
- userProfile.addMixin(ArgeoTypes.ARGEO_USER_PROFILE);
- userProfile.setProperty(ArgeoNames.ARGEO_USER_ID, username);
- userProfile.setProperty(ArgeoNames.ARGEO_ENABLED, true);
- userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED, true);
- userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED, true);
- userProfile.setProperty(ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED, true);
- session.save();
-
- JcrUtils.clearAccessControList(session, userProfile.getPath(), username);
- JcrUtils.addPrivilege(session, userProfile.getPath(), username, Privilege.JCR_READ);
- }
-
- // Remote roles
- // if (roles != null) {
- // writeRemoteRoles(userProfile, roles);
- // }
- if (adminSession.hasPendingChanges())
- adminSession.save();
- return userProfile;
- } catch (RepositoryException e) {
- JcrUtils.discardQuietly(session);
- throw new ArgeoException("Cannot sync node security model for " + username, e);
- }
- }
-
- /** Generate path for a new user home */
- private String generateUserPath(String base, String username) {
- LdapName dn;
- try {
- dn = new LdapName(username);
- } catch (InvalidNameException e) {
- throw new ArgeoException("Invalid name " + username, e);
- }
- String userId = dn.getRdn(dn.size() - 1).getValue().toString();
- int atIndex = userId.indexOf('@');
- if (atIndex > 0) {
- String domain = userId.substring(0, atIndex);
- String name = userId.substring(atIndex + 1);
- return base + '/' + JcrUtils.firstCharsToPath(domain, 2) + '/' + domain + '/'
- + JcrUtils.firstCharsToPath(name, 2) + '/' + name;
- } else if (atIndex == 0 || atIndex == (userId.length() - 1)) {
- throw new ArgeoException("Unsupported username " + userId);
- } else {
- return base + '/' + JcrUtils.firstCharsToPath(userId, 2) + '/' + userId;
- }
- }
+ // private void initJcr(Session adminSession) {
+ // try {
+ // JcrUtils.mkdirs(adminSession, homeBasePath);
+ // JcrUtils.mkdirs(adminSession, peopleBasePath);
+ // adminSession.save();
+ //
+ // JcrUtils.addPrivilege(adminSession, homeBasePath,
+ // AuthConstants.ROLE_USER_ADMIN, Privilege.JCR_READ);
+ // JcrUtils.addPrivilege(adminSession, peopleBasePath,
+ // AuthConstants.ROLE_USER_ADMIN, Privilege.JCR_ALL);
+ // adminSession.save();
+ // } catch (RepositoryException e) {
+ // throw new CmsException("Cannot initialize node user admin", e);
+ // }
+ // }
+ //
+ // private Node syncJcr(Session session, Authorization authorization) {
+ // // TODO check user name validity (e.g. should not start by ROLE_)
+ // String username = authorization.getName();
+ // // String[] roles = authorization.getRoles();
+ // try {
+ // Node userHome = UserJcrUtils.getUserHome(session, username);
+ // if (userHome == null) {
+ // String homePath = generateUserPath(homeBasePath, username);
+ // if (session.itemExists(homePath))// duplicate user id
+ // userHome =
+ // session.getNode(homePath).getParent().addNode(JcrUtils.lastPathElement(homePath));
+ // else
+ // userHome = JcrUtils.mkdirs(session, homePath);
+ // // userHome = JcrUtils.mkfolders(session, homePath);
+ // userHome.addMixin(ArgeoTypes.ARGEO_USER_HOME);
+ // userHome.setProperty(ArgeoNames.ARGEO_USER_ID, username);
+ // session.save();
+ //
+ // JcrUtils.clearAccessControList(session, homePath, username);
+ // JcrUtils.addPrivilege(session, homePath, username, Privilege.JCR_ALL);
+ // }
+ //
+ // Node userProfile = UserJcrUtils.getUserProfile(session, username);
+ // // new user
+ // if (userProfile == null) {
+ // String personPath = generateUserPath(peopleBasePath, username);
+ // Node personBase;
+ // if (session.itemExists(personPath))// duplicate user id
+ // personBase =
+ // session.getNode(personPath).getParent().addNode(JcrUtils.lastPathElement(personPath));
+ // else
+ // personBase = JcrUtils.mkdirs(session, personPath);
+ // userProfile = personBase.addNode(ArgeoNames.ARGEO_PROFILE);
+ // userProfile.addMixin(ArgeoTypes.ARGEO_USER_PROFILE);
+ // userProfile.setProperty(ArgeoNames.ARGEO_USER_ID, username);
+ // userProfile.setProperty(ArgeoNames.ARGEO_ENABLED, true);
+ // userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_EXPIRED, true);
+ // userProfile.setProperty(ArgeoNames.ARGEO_ACCOUNT_NON_LOCKED, true);
+ // userProfile.setProperty(ArgeoNames.ARGEO_CREDENTIALS_NON_EXPIRED, true);
+ // session.save();
+ //
+ // JcrUtils.clearAccessControList(session, userProfile.getPath(), username);
+ // JcrUtils.addPrivilege(session, userProfile.getPath(), username,
+ // Privilege.JCR_READ);
+ // }
+ //
+ // // Remote roles
+ // // if (roles != null) {
+ // // writeRemoteRoles(userProfile, roles);
+ // // }
+ // if (adminSession.hasPendingChanges())
+ // adminSession.save();
+ // return userProfile;
+ // } catch (RepositoryException e) {
+ // JcrUtils.discardQuietly(session);
+ // throw new ArgeoException("Cannot sync node security model for " +
+ // username, e);
+ // }
+ // }
+ //
+ // /** Generate path for a new user home */
+ // private String generateUserPath(String base, String username) {
+ // LdapName dn;
+ // try {
+ // dn = new LdapName(username);
+ // } catch (InvalidNameException e) {
+ // throw new ArgeoException("Invalid name " + username, e);
+ // }
+ // String userId = dn.getRdn(dn.size() - 1).getValue().toString();
+ // int atIndex = userId.indexOf('@');
+ // if (atIndex > 0) {
+ // String domain = userId.substring(0, atIndex);
+ // String name = userId.substring(atIndex + 1);
+ // return base + '/' + JcrUtils.firstCharsToPath(domain, 2) + '/' + domain +
+ // '/'
+ // + JcrUtils.firstCharsToPath(name, 2) + '/' + name;
+ // } else if (atIndex == 0 || atIndex == (userId.length() - 1)) {
+ // throw new ArgeoException("Unsupported username " + userId);
+ // } else {
+ // return base + '/' + JcrUtils.firstCharsToPath(userId, 2) + '/' + userId;
+ // }
+ // }
// /** Write remote roles used by remote access in the home directory */
// private void writeRemoteRoles(Node userHome, String[] roles)
org.argeo.cms.auth.NodeUserLoginModule requisite;
};
-SYSTEM {
- org.argeo.security.core.SystemLoginModule requisite;
+DATA_ADMIN {
+ org.argeo.cms.auth.DataAdminLoginModule requisite;
};
KERNEL {
</list>\r
\r
<reference id="nodeRepository" interface="javax.jcr.Repository"\r
- filter="(argeo.jcr.repository.alias=node)" />\r
+ filter="(argeo.jcr.repository.alias=home)" />\r
<reference id="repositoryFactory" interface="javax.jcr.RepositoryFactory" />\r
<reference id="keyring" interface="org.argeo.util.security.CryptoKeyring" />\r
<reference id="userAdmin" interface="org.osgi.service.useradmin.UserAdmin" />\r
+++ /dev/null
-package org.argeo.security;
-
-import java.security.Principal;
-
-public final class SystemAuth implements Principal {
- private final String name = "init";
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public int hashCode() {
- return name.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- return this == obj;
- }
-
- @Override
- public String toString() {
- return name.toString();
- }
-
-}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.argeo.commons</groupId>
<dependencies>
<dependency>
<groupId>org.argeo.commons</groupId>
- <artifactId>org.argeo.security.core</artifactId>
+ <artifactId>org.argeo.cms.api</artifactId>
<version>2.1.45-SNAPSHOT</version>
</dependency>
+
+ <!-- TESTING -->
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.server.jcr</artifactId>
+ <version>2.1.45-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
\ No newline at end of file
import org.apache.jackrabbit.core.security.SecurityConstants;
import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
-import org.argeo.security.SystemAuth;
+import org.argeo.node.DataAdminPrincipal;
public class SystemJackrabbitLoginModule implements LoginModule {
@Override
public boolean commit() throws LoginException {
- Set<SystemAuth> initPrincipal = subject
- .getPrincipals(SystemAuth.class);
+ Set<DataAdminPrincipal> initPrincipal = subject
+ .getPrincipals(DataAdminPrincipal.class);
if (!initPrincipal.isEmpty()) {
subject.getPrincipals().add(
new AdminPrincipal(SecurityConstants.ADMIN_ID));
+ userPrincipal);
return true;
-
- // Set<Principal> principals = subject.getPrincipals();
- // if (principals.isEmpty()) {// system
- // throw new LoginException("Subject must be pre-authenticated");
- // // subject.getPrincipals().add(new AdminPrincipal("admin"));
- // // return true;
- // }
- // boolean isAdmin = false;
- // boolean isAnonymous = false;
- // // FIXME make it more generic
- // for (Principal principal : principals) {
- // if (principal.getName().equalsIgnoreCase(
- // "cn=admin,ou=roles,ou=node"))
- // isAdmin = true;
- // else if (principal.getName().equalsIgnoreCase(
- // "cn=anonymous,ou=roles,ou=node"))
- // isAnonymous = true;
- // }
- //
- // if (isAnonymous && isAdmin)
- // throw new LoginException("Cannot be admin and anonymous");
- //
- // // Add special Jackrabbit roles
- // if (isAdmin)
- // principals.add(new AdminPrincipal(SecurityConstants.ADMIN_ID));
- // if (isAnonymous)// anonymous
- // principals.add(new AnonymousPrincipal());
- // return true;
}
@Override
@Override
public boolean logout() throws LoginException {
- Set<SystemAuth> initPrincipal = subject
- .getPrincipals(SystemAuth.class);
+ Set<DataAdminPrincipal> initPrincipal = subject
+ .getPrincipals(DataAdminPrincipal.class);
if (!initPrincipal.isEmpty()) {
subject.getPrincipals(AdminPrincipal.class);
return true;
}
- // subject.getPrincipals().removeAll(
- // subject.getPrincipals(AdminPrincipal.class));
return true;
}
}
+++ /dev/null
-package org.argeo.jackrabbit;
-
-import java.io.File;
-import java.io.InputStream;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.jcr.Credentials;
-import javax.jcr.LoginException;
-import javax.jcr.NoSuchWorkspaceException;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-import org.apache.commons.io.IOUtils;
-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.apache.jackrabbit.core.RepositoryImpl;
-import org.apache.jackrabbit.core.cache.CacheManager;
-import org.apache.jackrabbit.core.config.RepositoryConfig;
-import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
-import org.apache.jackrabbit.stats.RepositoryStatisticsImpl;
-import org.argeo.ArgeoException;
-import org.argeo.jcr.ArgeoJcrException;
-import org.argeo.jcr.JcrRepositoryWrapper;
-import org.argeo.jcr.RepoConf;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedService;
-import org.xml.sax.InputSource;
-
-public class ManagedJackrabbitRepository extends JcrRepositoryWrapper implements ManagedService, JackrabbitRepository {
- private final static Log log = LogFactory.getLog(ManagedJackrabbitRepository.class);
-
- // Node
- final static String REPO_TYPE = "repoType";
- // final static String REPO_CONFIGURATION = "argeo.node.repo.configuration";
- // final static String REPO_DEFAULT_WORKSPACE = "defaultWorkspace";
- // final static String REPO_DBURL = "dburl";
- // final static String REPO_DBUSER = "dbuser";
- // final static String REPO_DBPASSWORD = "dbpassword";
- // final static String REPO_MAX_POOL_SIZE = "maxPoolSize";
- // final static String REPO_MAX_CACHE_MB = "maxCacheMB";
- // final static String REPO_BUNDLE_CACHE_MB = "bundleCacheMB";
- // final static String REPO_EXTRACTOR_POOL_SIZE = "extractorPoolSize";
- // final static String REPO_SEARCH_CACHE_SIZE = "searchCacheSize";
- // final static String REPO_MAX_VOLATILE_INDEX_SIZE =
- // "maxVolatileIndexSize";
-
- private Dictionary<String, ?> properties;
-
- @Override
- public void updated(Dictionary<String, ?> properties) throws ConfigurationException {
- this.properties = properties;
- if (properties == null)
- return;
-
- JackrabbitNodeType type = JackrabbitNodeType.valueOf(prop(RepoConf.type).toString());
- try {
- repositoryContext = createNode(type);
- } catch (Exception e) {
- e.printStackTrace();
- throw new ArgeoException("Cannot create Jackrabbit repository of type " + type, e);
- }
- }
-
- private RepositoryContext repositoryContext;
-
- public ManagedJackrabbitRepository() {
- // setBundleContext(Activator.getBundleContext());
- // JackrabbitNodeType type = JackrabbitNodeType.valueOf(prop(REPO_TYPE,
- // JackrabbitNodeType.h2.name()));
- // try {
- // repositoryContext = createNode(type);
- // cndFiles = Arrays.asList(DEFAULT_CNDS);
- // prepareDataModel();
- // } catch (Exception e) {
- // throw new ArgeoException("Cannot create Jackrabbit repository of type
- // " + type, e);
- // }
- }
-
- public void destroy() {
- ((RepositoryImpl) getRepository()).shutdown();
- }
-
- RepositoryStatisticsImpl getRepositoryStatistics() {
- return repositoryContext.getRepositoryStatistics();
- }
-
- private RepositoryConfig getConfiguration(JackrabbitNodeType type, Hashtable<String, Object> props)
- throws RepositoryException {
- ClassLoader cl = getClass().getClassLoader();
- InputStream in = null;
- try {
- final String base = "/org/argeo/jackrabbit";
- switch (type) {
- case h2:
- in = cl.getResourceAsStream(base + "/repository-h2.xml");
- break;
- case postgresql:
- in = cl.getResourceAsStream(base + "/repository-postgresql.xml");
- break;
- case memory:
- in = cl.getResourceAsStream(base + "/repository-memory.xml");
- break;
- case localfs:
- in = cl.getResourceAsStream(base + "/repository-localfs.xml");
- break;
- default:
- throw new ArgeoJcrException("Unsupported node type " + type);
- }
-
- if (in == null)
- throw new ArgeoJcrException("Repository configuration not found");
- InputSource config = new InputSource(in);
- Properties jackrabbitVars = new Properties();
- // convert values to Strings, otherwise they are skipped
- for (String key : props.keySet())
- jackrabbitVars.setProperty(key, props.get(key).toString());
- RepositoryConfig repositoryConfig = RepositoryConfig.create(config, jackrabbitVars);
- return repositoryConfig;
- } finally {
- IOUtils.closeQuietly(in);
- }
- }
-
- private Hashtable<String, Object> getConfigurationProperties(JackrabbitNodeType type) {
- Hashtable<String, Object> props = new Hashtable<String, Object>();
-
- // home
- File osgiInstanceDir = getOsgiInstanceDir();
- File homeDir = new File(osgiInstanceDir, "repos/node");
- homeDir.mkdirs();
- // home cannot be overridden
- props.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, homeDir.getAbsolutePath());
-
- // common
- setProp(props, RepoConf.defaultWorkspace);
- setProp(props, RepoConf.maxPoolSize);
- // Jackrabbit defaults
- setProp(props, RepoConf.bundleCacheMB);
- // See http://wiki.apache.org/jackrabbit/Search
- setProp(props, RepoConf.extractorPoolSize);
- setProp(props, RepoConf.searchCacheSize);
- setProp(props, RepoConf.maxVolatileIndexSize);
-
- // specific
- String dburl;
- switch (type) {
- case h2:
- dburl = "jdbc:h2:" + homeDir.getPath() + "/h2/repository";
- setProp(props, RepoConf.dburl, dburl);
- setProp(props, RepoConf.dbuser, "sa");
- setProp(props, RepoConf.dbpassword, "");
- break;
- case postgresql:
- dburl = "jdbc:postgresql://localhost/demo";
- setProp(props, RepoConf.dburl, dburl);
- setProp(props, RepoConf.dbuser, "argeo");
- setProp(props, RepoConf.dbpassword, "argeo");
- break;
- case memory:
- break;
- case localfs:
- break;
- default:
- throw new ArgeoJcrException("Unsupported node type " + type);
- }
- return props;
- }
-
- private void setProp(Dictionary<String, Object> props, RepoConf key, String def) {
- Object value = prop(key);
- if (value == null)
- value = def;
- props.put(key.name(), value);
- }
-
- private void setProp(Dictionary<String, Object> props, RepoConf key) {
- setProp(props, key, null);
- }
-
- private Object prop(RepoConf key) {
- if (properties == null)
- throw new ArgeoJcrException("Properties are not set");
- Object value = properties.get(key.name());
- if (value == null)
- return key.getDefault();
- else
- return value;
- }
-
- private RepositoryContext createNode(JackrabbitNodeType type) throws RepositoryException {
- Hashtable<String, Object> props = getConfigurationProperties(type);
- RepositoryConfig repositoryConfig = getConfiguration(type, props);
- RepositoryContext repositoryContext = createJackrabbitRepository(repositoryConfig);
- RepositoryImpl repository = repositoryContext.getRepository();
-
- // cache
- Object maxCacheMbStr = prop(RepoConf.maxCacheMB);
- if (maxCacheMbStr != null) {
- Integer maxCacheMB = Integer.parseInt(maxCacheMbStr.toString());
- CacheManager cacheManager = repository.getCacheManager();
- cacheManager.setMaxMemory(maxCacheMB * 1024l * 1024l);
- cacheManager.setMaxMemoryPerCache((maxCacheMB / 4) * 1024l * 1024l);
- }
-
- // wrap the repository
- setRepository(repository);
- return repositoryContext;
- }
-
- private RepositoryContext createJackrabbitRepository(RepositoryConfig repositoryConfig) throws RepositoryException {
- ClassLoader currentContextCl = Thread.currentThread().getContextClassLoader();
- Thread.currentThread().setContextClassLoader(ManagedJackrabbitRepository.class.getClassLoader());
- try {
- long begin = System.currentTimeMillis();
- //
- // Actual repository creation
- //
- RepositoryContext repositoryContext = RepositoryContext.create(repositoryConfig);
-
- double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
- if (log.isTraceEnabled())
- log.trace(
- "Created Jackrabbit repository in " + duration + " s, home: " + repositoryConfig.getHomeDir());
-
- return repositoryContext;
- } finally {
- Thread.currentThread().setContextClassLoader(currentContextCl);
- }
- }
-
- /*
- * DATA MODEL
- */
-
- public synchronized void waitForInit() {
- while (repositoryContext == null)
- try {
- wait(100);
- } catch (InterruptedException e) {
- return;
- }
- }
-
- private final static String OSGI_INSTANCE_AREA = "osgi.instance.area";
-
- private File getOsgiInstanceDir() {
- String instanceArea = System.getProperty(OSGI_INSTANCE_AREA);
- return new File(instanceArea.substring("file:".length())).getAbsoluteFile();
- }
-
- @Override
- public Session login(Credentials credentials, String workspaceName, Map<String, Object> attributes)
- throws LoginException, NoSuchWorkspaceException, RepositoryException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void shutdown() {
- destroy();
-
- }
-
-}
* JCR repository.
*/
public final static String ALIAS_NODE = "node";
+ public final static String ALIAS_HOME = "home";
public final static String BASE_REPO_PID = "argeo.repo.";
public final static String REPO_PID_NODE = BASE_REPO_PID + ALIAS_NODE;
+ public final static String JACKRABBIT_REPO_FACTORY_PID = "argeo.repo.factory.jackrabbit";
}
+++ /dev/null
-package org.argeo.jcr;
-
-/** JCR repository configuration */
-public enum RepoConf {
- /** Repository type */
- type("localfs"),
- /** Default workspace */
- defaultWorkspace("main"),
- /** Database URL */
- dburl(null),
- /** Database user */
- dbuser(null),
- /** Database password */
- dbpassword(null),
-
- //
- // JACKRABBIT SPECIFIC
- //
- /** Maximum database pool size */
- maxPoolSize(10),
- /** Maximum cache size in MB */
- maxCacheMB(null),
- /** Bundle cache size in MB */
- bundleCacheMB(8),
- /** Extractor pool size */
- extractorPoolSize(0),
- /** Search cache size */
- searchCacheSize(1000),
- /** Max volatile index size */
- maxVolatileIndexSize(1048576);
-
- /** The default value. */
- private Object def;
-
- RepoConf(Object def) {
- this.def = def;
- }
-
- public Object getDefault() {
- return def;
- }
-}
--- /dev/null
+package org.argeo.util;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+/**
+ * Access the keys of a {@link String}-keyed {@link Dictionary} (common throughout
+ * the OSGi APIs) as an {@link Iterable} so that they are easily usable in
+ * for-each loops.
+ */
+class DictionaryKeys implements Iterable<String> {
+ private final Dictionary<String, ?> dictionary;
+
+ public DictionaryKeys(Dictionary<String, ?> dictionary) {
+ this.dictionary = dictionary;
+ }
+
+ @Override
+ public Iterator<String> iterator() {
+ return new KeyIterator(dictionary.keys());
+ }
+
+ private static class KeyIterator implements Iterator<String> {
+ private final Enumeration<String> keys;
+
+ KeyIterator(Enumeration<String> keys) {
+ this.keys = keys;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return keys.hasMoreElements();
+ }
+
+ @Override
+ public String next() {
+ return keys.nextElement();
+ }
+
+ }
+}
--- /dev/null
+package org.argeo.util;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+public class LangUtils {
+ /*
+ * NON-API OSGi
+ */
+ /**
+ * Returns an array with the names of the provided classes. Useful when
+ * registering services with multiple interfaces in OSGi.
+ */
+ public static String[] names(Class<?>... clzz) {
+ String[] res = new String[clzz.length];
+ for (int i = 0; i < clzz.length; i++)
+ res[i] = clzz[i].getName();
+ return res;
+ }
+
+ /*
+ * DICTIONARY
+ */
+
+ /**
+ * Creates a new {@link Dictionary} with one key-value pair (neith key not
+ * value should be null)
+ */
+ public static Dictionary<String, Object> init(String key, Object value) {
+ assert key != null;
+ assert value != null;
+ Hashtable<String, Object> props = new Hashtable<>();
+ props.put(key, value);
+ return props;
+ }
+
+ /**
+ * Wraps the keys of the provided {@link Dictionary} as an {@link Iterable}.
+ */
+ public static Iterable<String> keys(Dictionary<String, ?> props) {
+ assert props != null;
+ return new DictionaryKeys(props);
+ }
+
+ public static String toJson(Dictionary<String, ?> props) {
+ return toJson(props, false);
+ }
+
+ public static String toJson(Dictionary<String, ?> props, boolean pretty) {
+ StringBuilder sb = new StringBuilder();
+ sb.append('{');
+ if (pretty)
+ sb.append('\n');
+ Enumeration<String> keys = props.keys();
+ while (keys.hasMoreElements()) {
+ String key = keys.nextElement();
+ if (pretty)
+ sb.append(' ');
+ sb.append('\"').append(key).append('\"');
+ if (pretty)
+ sb.append(" : ");
+ else
+ sb.append(':');
+ sb.append('\"').append(props.get(key)).append('\"');
+ if (keys.hasMoreElements())
+ sb.append(", ");
+ if (pretty)
+ sb.append('\n');
+ }
+ sb.append('}');
+ return sb.toString();
+ }
+
+ /** Singleton constructor. */
+ private LangUtils() {
+
+ }
+
+}
// based on language only
if (defaultIndex == null)
for (int i = 0; i < locales.size(); i++)
- if (locales.get(i).getLanguage()
- .equals(defaultLocale.getLanguage()))
+ if (locales.get(i).getLanguage().equals(defaultLocale.getLanguage()))
defaultIndex = i;
if (defaultIndex == null)
- throw new ArgeoException("Default locale " + defaultLocale
- + " is not in available locales " + locales);
+ throw new ArgeoException("Default locale " + defaultLocale + " is not in available locales " + locales);
this.defaultIndex = defaultIndex;
this.selectedIndex = defaultIndex;
for (int i = 0; i < locales.size(); i++) {
Locale locale = locales.get(i);
if (locale.getCountry().equals(""))
- labels[i] = locale.getDisplayLanguage(locale) + " ["
- + locale.getLanguage() + "]";
+ labels[i] = locale.getDisplayLanguage(locale) + " [" + locale.getLanguage() + "]";
else
- labels[i] = locale.getDisplayLanguage(locale) + " ("
- + locale.getDisplayCountry(locale) + ") ["
- + locale.getLanguage() + "_" + locale.getCountry()
- + "]";
+ labels[i] = locale.getDisplayLanguage(locale) + " (" + locale.getDisplayCountry(locale) + ") ["
+ + locale.getLanguage() + "_" + locale.getCountry() + "]";
}
return labels;
}
/** Returns null if argument is null. */
- public static List<Locale> asLocaleList(String locales) {
+ public static List<Locale> asLocaleList(Object locales) {
if (locales == null)
return null;
ArrayList<Locale> availableLocales = new ArrayList<Locale>();
- String[] codes = locales.split(",");
+ String[] codes = locales.toString().split(",");
for (int i = 0; i < codes.length; i++) {
String code = codes[i];
// variant not supported
public static void main(String[] args) {
for (String isoL : Locale.getISOLanguages()) {
Locale locale = new Locale(isoL);
- System.out.println(isoL + "\t" + locale.getDisplayLanguage() + "\t"
- + locale.getDisplayLanguage(locale));
+ System.out.println(isoL + "\t" + locale.getDisplayLanguage() + "\t" + locale.getDisplayLanguage(locale));
}
}
<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.argeo.commons</groupId>
<artifactId>argeo-commons</artifactId>
<module>org.argeo.server.jcr</module>
<!-- Security -->
<module>org.argeo.security.core</module>
- <module>org.argeo.security.jackrabbit</module>
<!-- Eclipse -->
<module>org.argeo.eclipse.ui</module>
<module>org.argeo.eclipse.ui.rap</module>
<!-- CMS -->
+ <module>org.argeo.cms.api</module>
<module>org.argeo.cms</module>
+ <module>org.argeo.security.jackrabbit</module>
<!-- Workbench -->
<module>org.argeo.eclipse.ui.workbench</module>
<module>org.argeo.eclipse.ui.workbench.rap</module>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>2.3.7</version>
+ <version>3.0.1</version>
<extensions>true</extensions>
<configuration>
<manifestLocation>META-INF</manifestLocation>
</goals>
<configuration>
<target>
- <copy todir="${argeo.rpm.stagingRepository}" quiet="true" failonerror="false">
- <fileset dir="${project.build.directory}/rpm" includes="*/RPMS/**/*.rpm" />
+ <copy todir="${argeo.rpm.stagingRepository}" quiet="true"
+ failonerror="false">
+ <fileset dir="${project.build.directory}/rpm"
+ includes="*/RPMS/**/*.rpm" />
<flattenmapper />
</copy>
</target>
</goals>
<configuration>
<target>
- <copy todir="${argeo.rpm.stagingRepository}" quiet="true" failonerror="false">
- <fileset dir="${project.build.directory}/rpm" includes="*/RPMS/**/*.rpm" />
+ <copy todir="${argeo.rpm.stagingRepository}" quiet="true"
+ failonerror="false">
+ <fileset dir="${project.build.directory}/rpm"
+ includes="*/RPMS/**/*.rpm" />
<flattenmapper />
</copy>
</target>