From: Mathieu Baudier Date: Thu, 4 Jun 2020 12:29:45 +0000 (+0200) Subject: Start simplifying and clarifying CMS initialisation. Remove Jackrabbit X-Git-Tag: argeo-commons-2.1.89~133 X-Git-Url: https://git.argeo.org/?a=commitdiff_plain;h=a5041ede454d2cb851aa2908f75e25fce43e639a;hp=c5e7dfede43f8b53710baa406b334792a7603d45;p=lgpl%2Fargeo-commons.git Start simplifying and clarifying CMS initialisation. Remove Jackrabbit fragment. --- diff --git a/dep/org.argeo.dep.cms.node/pom.xml b/dep/org.argeo.dep.cms.node/pom.xml index 5c187a060..e8a9045bb 100644 --- a/dep/org.argeo.dep.cms.node/pom.xml +++ b/dep/org.argeo.dep.cms.node/pom.xml @@ -35,11 +35,11 @@ org.argeo.maintenance 2.1.89-SNAPSHOT - - org.argeo.commons - org.argeo.ext.jackrabbit - 2.1.89-SNAPSHOT - + + + + + org.argeo.commons org.argeo.ext.equinox.jetty diff --git a/org.argeo.api/src/org/argeo/api/NodeDeployment.java b/org.argeo.api/src/org/argeo/api/NodeDeployment.java index 224d244dc..d678bac0b 100644 --- a/org.argeo.api/src/org/argeo/api/NodeDeployment.java +++ b/org.argeo.api/src/org/argeo/api/NodeDeployment.java @@ -1,5 +1,6 @@ package org.argeo.api; +/** A configured node deployment. */ public interface NodeDeployment { Long getAvailableSince(); } diff --git a/org.argeo.api/src/org/argeo/api/NodeState.java b/org.argeo.api/src/org/argeo/api/NodeState.java index 30de09587..a824ac278 100644 --- a/org.argeo.api/src/org/argeo/api/NodeState.java +++ b/org.argeo.api/src/org/argeo/api/NodeState.java @@ -3,6 +3,7 @@ package org.argeo.api; import java.util.List; import java.util.Locale; +/** A running node process. */ public interface NodeState { Locale getDefaultLocale(); @@ -10,8 +11,6 @@ public interface NodeState { String getHostname(); - boolean isClean(); - Long getAvailableSince(); } diff --git a/org.argeo.cms/.settings/org.eclipse.jdt.core.prefs b/org.argeo.cms/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..ce5f46480 --- /dev/null +++ b/org.argeo.cms/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,102 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled +org.eclipse.jdt.core.compiler.problem.APILeak=warning +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled +org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning diff --git a/org.argeo.cms/.settings/org.eclipse.pde.prefs b/org.argeo.cms/.settings/org.eclipse.pde.prefs deleted file mode 100644 index 4f89bcde1..000000000 --- a/org.argeo.cms/.settings/org.eclipse.pde.prefs +++ /dev/null @@ -1,35 +0,0 @@ -compilers.f.unresolved-features=1 -compilers.f.unresolved-plugins=1 -compilers.incompatible-environment=1 -compilers.p.build=1 -compilers.p.build.bin.includes=1 -compilers.p.build.encodings=2 -compilers.p.build.java.compiler=2 -compilers.p.build.java.compliance=1 -compilers.p.build.missing.output=2 -compilers.p.build.output.library=1 -compilers.p.build.source.library=1 -compilers.p.build.src.includes=1 -compilers.p.deprecated=1 -compilers.p.discouraged-class=1 -compilers.p.exec-env-too-low=1 -compilers.p.internal=1 -compilers.p.missing-packages=2 -compilers.p.missing-version-export-package=2 -compilers.p.missing-version-import-package=2 -compilers.p.missing-version-require-bundle=2 -compilers.p.no-required-att=0 -compilers.p.no.automatic.module=1 -compilers.p.not-externalized-att=2 -compilers.p.service.component.without.lazyactivation=2 -compilers.p.unknown-attribute=1 -compilers.p.unknown-class=1 -compilers.p.unknown-element=1 -compilers.p.unknown-identifier=1 -compilers.p.unknown-resource=1 -compilers.p.unresolved-ex-points=0 -compilers.p.unresolved-import=0 -compilers.s.create-docs=false -compilers.s.doc-folder=doc -compilers.s.open-tags=1 -eclipse.preferences.version=1 diff --git a/org.argeo.cms/src/org/argeo/cms/internal/jcr/CustomRepositoryConfigurationParser.java b/org.argeo.cms/src/org/argeo/cms/internal/jcr/CustomRepositoryConfigurationParser.java new file mode 100644 index 000000000..2e703ced8 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/jcr/CustomRepositoryConfigurationParser.java @@ -0,0 +1,48 @@ +package org.argeo.cms.internal.jcr; + +import java.util.Properties; + +import org.apache.jackrabbit.core.config.ConfigurationException; +import org.apache.jackrabbit.core.config.RepositoryConfigurationParser; +import org.apache.jackrabbit.core.config.WorkspaceSecurityConfig; +import org.apache.jackrabbit.core.util.db.ConnectionFactory; +import org.w3c.dom.Element; + +/** + * A {@link RepositoryConfigurationParser} providing more flexibility with + * classloaders. + */ +@SuppressWarnings("restriction") +class CustomRepositoryConfigurationParser extends RepositoryConfigurationParser { + private ClassLoader accessControlProviderClassLoader = null; + + public CustomRepositoryConfigurationParser(Properties variables) { + super(variables); + } + + public CustomRepositoryConfigurationParser(Properties variables, ConnectionFactory connectionFactory) { + super(variables, connectionFactory); + } + + @Override + protected RepositoryConfigurationParser createSubParser(Properties variables) { + Properties props = new Properties(getVariables()); + props.putAll(variables); + CustomRepositoryConfigurationParser subParser = new CustomRepositoryConfigurationParser(props, + connectionFactory); + subParser.setAccessControlProviderClassLoader(accessControlProviderClassLoader); + return subParser; + } + + @Override + public WorkspaceSecurityConfig parseWorkspaceSecurityConfig(Element parent) throws ConfigurationException { + WorkspaceSecurityConfig workspaceSecurityConfig = super.parseWorkspaceSecurityConfig(parent); + workspaceSecurityConfig.getAccessControlProviderConfig().setClassLoader(accessControlProviderClassLoader); + return workspaceSecurityConfig; + } + + public void setAccessControlProviderClassLoader(ClassLoader accessControlProviderClassLoader) { + this.accessControlProviderClassLoader = accessControlProviderClassLoader; + } + +} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/jcr/RepositoryBuilder.java b/org.argeo.cms/src/org/argeo/cms/internal/jcr/RepositoryBuilder.java index 872d8ae53..bc6a82626 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/jcr/RepositoryBuilder.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/jcr/RepositoryBuilder.java @@ -58,7 +58,21 @@ public class RepositoryBuilder { throw new ArgeoJcrException("Repository configuration not found"); InputSource config = new InputSource(in); Properties jackrabbitVars = getConfigurationProperties(type, properties); - RepositoryConfig repositoryConfig = RepositoryConfig.create(config, jackrabbitVars); + // RepositoryConfig repositoryConfig = RepositoryConfig.create(config, + // jackrabbitVars); + + // custom configuration parser + CustomRepositoryConfigurationParser parser = new CustomRepositoryConfigurationParser(jackrabbitVars); + parser.setAccessControlProviderClassLoader(cl); + RepositoryConfig repositoryConfig = parser.parseRepositoryConfig(config); + repositoryConfig.init(); + + // set the proper classloaders + repositoryConfig.getSecurityConfig().getSecurityManagerConfig().setClassLoader(cl); + repositoryConfig.getSecurityConfig().getAccessManagerConfig().setClassLoader(cl); +// for (WorkspaceConfig workspaceConfig : repositoryConfig.getWorkspaceConfigs()) { +// workspaceConfig.getSecurityConfig().getAccessControlProviderConfig().setClassLoader(cl); +// } return repositoryConfig; } } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java index d2d7d25b7..7b2cb78bf 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java @@ -2,10 +2,7 @@ package org.argeo.cms.internal.kernel; import java.io.IOException; import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; import java.security.AllPermission; -import java.util.Dictionary; import java.util.List; import java.util.Locale; import java.util.concurrent.ExecutorService; @@ -22,7 +19,6 @@ import org.argeo.api.NodeInstance; import org.argeo.api.NodeState; import org.argeo.cms.CmsException; import org.argeo.ident.IdentClient; -import org.argeo.util.LangUtils; import org.ietf.jgss.GSSCredential; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; @@ -137,18 +133,18 @@ public class Activator implements BundleActivator { private void initNode() throws IOException { // Node state - Path stateUuidPath = bc.getDataFile("stateUuid").toPath(); - String stateUuid; - if (Files.exists(stateUuidPath)) { - stateUuid = Files.readAllLines(stateUuidPath).get(0); - } else { - stateUuid = bc.getProperty(Constants.FRAMEWORK_UUID); - Files.write(stateUuidPath, stateUuid.getBytes()); - } - nodeState = new CmsState(stateUuid); - Dictionary regProps = LangUtils.dico(Constants.SERVICE_PID, NodeConstants.NODE_STATE_PID); - regProps.put(NodeConstants.CN, stateUuid); - bc.registerService(NodeState.class, nodeState, regProps); +// Path stateUuidPath = bc.getDataFile("stateUuid").toPath(); +// String stateUuid; +// if (Files.exists(stateUuidPath)) { +// stateUuid = Files.readAllLines(stateUuidPath).get(0); +// } else { +// stateUuid = bc.getProperty(Constants.FRAMEWORK_UUID); +// Files.write(stateUuidPath, stateUuid.getBytes()); +// } + nodeState = new CmsState(); +// Dictionary regProps = LangUtils.dico(Constants.SERVICE_PID, NodeConstants.NODE_STATE_PID); +// regProps.put(NodeConstants.CN, stateUuid); + bc.registerService(NodeState.class, nodeState, null); // Node deployment nodeDeployment = new CmsDeployment(); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java index 34b4dd927..34d6e1f24 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java @@ -3,6 +3,7 @@ package org.argeo.cms.internal.kernel; import static org.argeo.api.DataModelNamespace.CMS_DATA_MODEL_NAMESPACE; import java.io.File; +import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.lang.management.ManagementFactory; @@ -65,7 +66,7 @@ public class CmsDeployment implements NodeDeployment { private Long availableSince; - private final boolean cleanState; +// private final boolean cleanState; private NodeHttp nodeHttp; @@ -78,14 +79,14 @@ public class CmsDeployment implements NodeDeployment { private boolean httpAvailable = false; public CmsDeployment() { - ServiceReference nodeStateSr = bc.getServiceReference(NodeState.class); - if (nodeStateSr == null) - throw new CmsException("No node state available"); +// ServiceReference nodeStateSr = bc.getServiceReference(NodeState.class); +// if (nodeStateSr == null) +// throw new CmsException("No node state available"); - NodeState nodeState = bc.getService(nodeStateSr); - cleanState = nodeState.isClean(); +// NodeState nodeState = bc.getService(nodeStateSr); +// cleanState = nodeState.isClean(); - nodeHttp = new NodeHttp(cleanState); + nodeHttp = new NodeHttp(); dataModels = new DataModels(bc); initTrackers(); } @@ -125,17 +126,17 @@ public class CmsDeployment implements NodeDeployment { @Override public ConfigurationAdmin addingService(ServiceReference reference) { ConfigurationAdmin configurationAdmin = bc.getService(reference); - deployConfig = new DeployConfig(configurationAdmin, dataModels, cleanState); + boolean isClean; + try { + Configuration[] confs = configurationAdmin + .listConfigurations("(service.factoryPid=" + NodeConstants.NODE_USER_ADMIN_PID + ")"); + isClean = confs == null || confs.length == 0; + } catch (Exception e) { + throw new CmsException("Cannot analize clean state", e); + } + deployConfig = new DeployConfig(configurationAdmin, dataModels, isClean); httpExpected = deployConfig.getProps(KernelConstants.JETTY_FACTORY_PID, "default") != null; try { - // Configuration[] configs = configurationAdmin - // .listConfigurations("(service.factoryPid=" + - // NodeConstants.NODE_REPOS_FACTORY_PID + ")"); - // for (Configuration config : configs) { - // Object cn = config.getProperties().get(NodeConstants.CN); - // if (log.isDebugEnabled()) - // log.debug("Standalone repo cn: " + cn); - // } Configuration[] configs = configurationAdmin .listConfigurations("(service.factoryPid=" + NodeConstants.NODE_USER_ADMIN_PID + ")"); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsState.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsState.java index ca469f0f5..7ff650254 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsState.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsState.java @@ -42,13 +42,13 @@ public class CmsState implements NodeState { private List stopHooks = new ArrayList<>(); private final String stateUuid; - private final boolean cleanState; +// private final boolean cleanState; private String hostname; - public CmsState(String stateUuid) { - this.stateUuid = stateUuid; - String frameworkUuid = KernelUtils.getFrameworkProp(Constants.FRAMEWORK_UUID); - this.cleanState = stateUuid.equals(frameworkUuid); + public CmsState() { +// this.stateUuid = stateUuid; + this.stateUuid = KernelUtils.getFrameworkProp(Constants.FRAMEWORK_UUID); +// this.cleanState = stateUuid.equals(frameworkUuid); try { this.hostname = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { @@ -57,7 +57,9 @@ public class CmsState implements NodeState { availableSince = System.currentTimeMillis(); if (log.isDebugEnabled()) - log.debug("## CMS starting... stateUuid=" + this.stateUuid + (cleanState ? " (clean state) " : " ")); + // log.debug("## CMS starting... stateUuid=" + this.stateUuid + (cleanState ? " + // (clean state) " : " ")); + log.debug("## CMS starting... (" + stateUuid + ")"); initI18n(); initServices(); @@ -176,13 +178,18 @@ public class CmsState implements NodeState { void shutdown() { if (log.isDebugEnabled()) - log.debug("CMS stopping... stateUuid=" + this.stateUuid + (cleanState ? " (clean state) " : " ")); + log.debug("CMS stopping... (" + this.stateUuid + ")"); if (kernelThread != null) kernelThread.destroyAndJoin(); - // In a different state in order to avois interruptions - new Thread(() -> applyStopHooks(), "Apply Argeo Stop Hooks").start(); - // applyStopHooks(); + // In a different thread in order to avoid interruptions + Thread stopHookThread = new Thread(() -> applyStopHooks(), "Apply Argeo Stop Hooks"); + stopHookThread.start(); + try { + stopHookThread.join(10 * 60 * 1000); + } catch (InterruptedException e) { + // silent + } long duration = ((System.currentTimeMillis() - availableSince) / 1000) / 60; log.info("## ARGEO CMS STOPPED after " + (duration / 60) + "h " + (duration % 60) + "min uptime ##"); @@ -201,10 +208,10 @@ public class CmsState implements NodeState { new GogoShellKiller().start(); } - @Override - public boolean isClean() { - return cleanState; - } +// @Override +// public boolean isClean() { +// return cleanState; +// } @Override public Long getAvailableSince() { diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java index 450b9dba4..2bbd8f219 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java @@ -174,6 +174,7 @@ class DeployConfig implements ConfigurationListener { } catch (Exception e1) { // silent } + tryCount--; } } } catch (Exception e) { @@ -188,6 +189,8 @@ class DeployConfig implements ConfigurationListener { deployConfigs = new LdifParser().read(in); } if (isClean) { + if(log.isDebugEnabled()) + log.debug("Clean state, loading from framework properties..."); setFromFrameworkProperties(isFirstInit); for (LdapName dn : deployConfigs.keySet()) { Rdn lastRdn = dn.getRdn(dn.size() - 1); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java index c391155d7..87b688a6d 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java @@ -46,10 +46,10 @@ public class NodeHttp implements KernelConstants { private String httpRealm = "Argeo"; private String webDavConfig = HttpUtils.WEBDAV_CONFIG; - private final boolean cleanState; +// private final boolean cleanState; - public NodeHttp(boolean cleanState) { - this.cleanState = cleanState; + public NodeHttp() { +// this.cleanState = cleanState; httpServiceTracker = new PrepareHttpStc(); // httpServiceTracker.open(); KernelUtils.asyncOpen(httpServiceTracker); @@ -222,8 +222,11 @@ public class NodeHttp implements KernelConstants { throw new CmsException("An http service is already configured"); repositories = new RepositoriesStc(bc, httpService); // repositories.open(); - if (cleanState) - KernelUtils.asyncOpen(repositories); + + ///if (cleanState) + // FIXME properly publish servlets + //KernelUtils.asyncOpen(repositories); + log.info(httpPortsMsg(httpPort, httpsPort)); // httpAvailable = true; // checkReadiness(); diff --git a/org.argeo.cms/src/org/argeo/security/jackrabbit/ArgeoAccessControlProvider.java b/org.argeo.cms/src/org/argeo/security/jackrabbit/ArgeoAccessControlProvider.java new file mode 100644 index 000000000..bffe531a1 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/security/jackrabbit/ArgeoAccessControlProvider.java @@ -0,0 +1,30 @@ +package org.argeo.security.jackrabbit; + +import java.security.Principal; +import java.util.Map; +import java.util.Set; + +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.jackrabbit.core.security.authorization.acl.ACLProvider; + +/** Argeo specific access control provider */ +public class ArgeoAccessControlProvider extends ACLProvider { + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public void init(Session systemSession, Map configuration) throws RepositoryException { + if (!configuration.containsKey(PARAM_ALLOW_UNKNOWN_PRINCIPALS)) + configuration.put(PARAM_ALLOW_UNKNOWN_PRINCIPALS, "true"); + if (!configuration.containsKey(PARAM_OMIT_DEFAULT_PERMISSIONS)) + configuration.put(PARAM_OMIT_DEFAULT_PERMISSIONS, "true"); + super.init(systemSession, configuration); + } + + @Override + public boolean canAccessRoot(Set principals) throws RepositoryException { + return super.canAccessRoot(principals); + } + +} diff --git a/org.argeo.cms/src/org/argeo/security/jackrabbit/ArgeoAccessManager.java b/org.argeo.cms/src/org/argeo/security/jackrabbit/ArgeoAccessManager.java new file mode 100644 index 000000000..52ea3c984 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/security/jackrabbit/ArgeoAccessManager.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jackrabbit; + +import javax.jcr.PathNotFoundException; +import javax.jcr.RepositoryException; +import javax.jcr.security.Privilege; + +import org.apache.jackrabbit.core.id.ItemId; +import org.apache.jackrabbit.core.security.DefaultAccessManager; +import org.apache.jackrabbit.spi.Path; + +/** + * Intermediary class in order to have a consistent naming in config files. Does + * nothing for the time being, but may in the future. + */ +public class ArgeoAccessManager extends DefaultAccessManager { + + @Override + public boolean canRead(Path itemPath, ItemId itemId) + throws RepositoryException { + return super.canRead(itemPath, itemId); + } + + @Override + public Privilege[] getPrivileges(String absPath) + throws PathNotFoundException, RepositoryException { + return super.getPrivileges(absPath); + } + + @Override + public boolean hasPrivileges(String absPath, Privilege[] privileges) + throws PathNotFoundException, RepositoryException { + return super.hasPrivileges(absPath, privileges); + } + +} diff --git a/org.argeo.cms/src/org/argeo/security/jackrabbit/ArgeoAuthContext.java b/org.argeo.cms/src/org/argeo/security/jackrabbit/ArgeoAuthContext.java new file mode 100644 index 000000000..d679c45f9 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/security/jackrabbit/ArgeoAuthContext.java @@ -0,0 +1,37 @@ +package org.argeo.security.jackrabbit; + +import javax.security.auth.Subject; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; + +import org.apache.jackrabbit.core.security.authentication.AuthContext; + +/** Wraps a regular {@link LoginContext}, using the proper class loader. */ +class ArgeoAuthContext implements AuthContext { + private LoginContext lc; + + public ArgeoAuthContext(String appName, Subject subject, CallbackHandler callbackHandler) { + try { + lc = new LoginContext(appName, subject, callbackHandler); + } catch (LoginException e) { + throw new IllegalStateException("Cannot configure Jackrabbit login context", e); + } + } + + @Override + public void login() throws LoginException { + lc.login(); + } + + @Override + public Subject getSubject() { + return lc.getSubject(); + } + + @Override + public void logout() throws LoginException { + lc.logout(); + } + +} diff --git a/org.argeo.cms/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java b/org.argeo.cms/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java new file mode 100644 index 000000000..c1ac9c72b --- /dev/null +++ b/org.argeo.cms/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.jackrabbit; + +import java.security.Principal; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; + +import javax.jcr.Credentials; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.security.auth.Subject; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.x500.X500Principal; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jackrabbit.api.security.user.UserManager; +import org.apache.jackrabbit.core.DefaultSecurityManager; +import org.apache.jackrabbit.core.security.AMContext; +import org.apache.jackrabbit.core.security.AccessManager; +import org.apache.jackrabbit.core.security.SecurityConstants; +import org.apache.jackrabbit.core.security.SystemPrincipal; +import org.apache.jackrabbit.core.security.authentication.AuthContext; +import org.apache.jackrabbit.core.security.authentication.CallbackHandlerImpl; +import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager; +import org.apache.jackrabbit.core.security.principal.AdminPrincipal; +import org.apache.jackrabbit.core.security.principal.PrincipalProvider; +import org.argeo.api.NodeConstants; +import org.argeo.api.security.AnonymousPrincipal; +import org.argeo.api.security.DataAdminPrincipal; +import org.argeo.cms.auth.CmsSession; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; + +/** Customises Jackrabbit security. */ +public class ArgeoSecurityManager extends DefaultSecurityManager { + private final static Log log = LogFactory.getLog(ArgeoSecurityManager.class); + + private BundleContext cmsBundleContext = null; + + public ArgeoSecurityManager() { + if (FrameworkUtil.getBundle(CmsSession.class) != null) { + cmsBundleContext = FrameworkUtil.getBundle(CmsSession.class).getBundleContext(); + } + } + + public AuthContext getAuthContext(Credentials creds, Subject subject, String workspaceName) + throws RepositoryException { + checkInitialized(); + + CallbackHandler cbHandler = new CallbackHandlerImpl(creds, getSystemSession(), getPrincipalProviderRegistry(), + adminId, anonymousId); + String appName = "Jackrabbit"; + return new ArgeoAuthContext(appName, subject, cbHandler); + } + + @Override + public AccessManager getAccessManager(Session session, AMContext amContext) throws RepositoryException { + synchronized (getSystemSession()) { + return super.getAccessManager(session, amContext); + } + } + + @Override + public UserManager getUserManager(Session session) throws RepositoryException { + synchronized (getSystemSession()) { + return super.getUserManager(session); + } + } + + @Override + protected PrincipalProvider createDefaultPrincipalProvider(Properties[] moduleConfig) throws RepositoryException { + return super.createDefaultPrincipalProvider(moduleConfig); + } + + /** Called once when the session is created */ + @Override + public String getUserID(Subject subject, String workspaceName) throws RepositoryException { + boolean isAnonymous = !subject.getPrincipals(AnonymousPrincipal.class).isEmpty(); + boolean isDataAdmin = !subject.getPrincipals(DataAdminPrincipal.class).isEmpty(); + boolean isJackrabbitSystem = !subject.getPrincipals(SystemPrincipal.class).isEmpty(); + Set userPrincipal = subject.getPrincipals(X500Principal.class); + boolean isRegularUser = !userPrincipal.isEmpty(); + CmsSession cmsSession = null; + if (cmsBundleContext != null) { + cmsSession = CmsSession.getCmsSession(cmsBundleContext, subject); + if (log.isTraceEnabled()) + log.trace("Opening JCR session for CMS session " + cmsSession); + } + + if (isAnonymous) { + if (isDataAdmin || isJackrabbitSystem || isRegularUser) + throw new IllegalStateException("Inconsistent " + subject); + else + return NodeConstants.ROLE_ANONYMOUS; + } else if (isRegularUser) {// must be before DataAdmin + if (isAnonymous || isJackrabbitSystem) + throw new IllegalStateException("Inconsistent " + subject); + else { + if (userPrincipal.size() > 1) { + StringBuilder buf = new StringBuilder(); + for (X500Principal principal : userPrincipal) + buf.append(' ').append('\"').append(principal).append('\"'); + throw new RuntimeException("Multiple user principals:" + buf); + } + return userPrincipal.iterator().next().getName(); + } + } else if (isDataAdmin) { + if (isAnonymous || isJackrabbitSystem || isRegularUser) + throw new IllegalStateException("Inconsistent " + subject); + else { + assert !subject.getPrincipals(AdminPrincipal.class).isEmpty(); + return NodeConstants.ROLE_DATA_ADMIN; + } + } else if (isJackrabbitSystem) { + if (isAnonymous || isDataAdmin || isRegularUser) + throw new IllegalStateException("Inconsistent " + subject); + else + return super.getUserID(subject, workspaceName); + } else { + throw new IllegalStateException("Unrecognized subject type: " + subject); + } + } + + @Override + protected WorkspaceAccessManager createDefaultWorkspaceAccessManager() { + WorkspaceAccessManager wam = super.createDefaultWorkspaceAccessManager(); + ArgeoWorkspaceAccessManagerImpl workspaceAccessManager = new ArgeoWorkspaceAccessManagerImpl(wam); + if (log.isTraceEnabled()) + log.trace("Created workspace access manager"); + return workspaceAccessManager; + } + + private class ArgeoWorkspaceAccessManagerImpl implements SecurityConstants, WorkspaceAccessManager { + private final WorkspaceAccessManager wam; + + public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam) { + super(); + this.wam = wam; + } + + public void init(Session systemSession) throws RepositoryException { + wam.init(systemSession); + Repository repository = systemSession.getRepository(); + if (log.isTraceEnabled()) + log.trace("Initialised workspace access manager on repository " + repository + + ", systemSession workspace: " + systemSession.getWorkspace().getName()); + } + + public void close() throws RepositoryException { + } + + public boolean grants(Set principals, String workspaceName) throws RepositoryException { + // TODO: implements finer access to workspaces + if (log.isTraceEnabled()) + log.trace("Grants " + new HashSet<>(principals) + " access to workspace '" + workspaceName + "'"); + return true; + // return wam.grants(principals, workspaceName); + } + } + +} diff --git a/org.argeo.cms/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java b/org.argeo.cms/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java new file mode 100644 index 000000000..9c70e9b72 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java @@ -0,0 +1,67 @@ +package org.argeo.security.jackrabbit; + +import java.util.Map; +import java.util.Set; + +import javax.security.auth.Subject; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.login.LoginException; +import javax.security.auth.spi.LoginModule; +import javax.security.auth.x500.X500Principal; + +import org.apache.jackrabbit.core.security.AnonymousPrincipal; +import org.apache.jackrabbit.core.security.SecurityConstants; +import org.apache.jackrabbit.core.security.principal.AdminPrincipal; +import org.argeo.api.security.DataAdminPrincipal; + +/** JAAS login module used when initiating a new Jackrabbit session. */ +public class SystemJackrabbitLoginModule implements LoginModule { + private Subject subject; + + @Override + public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, + Map options) { + this.subject = subject; + } + + @Override + public boolean login() throws LoginException { + return true; + } + + @Override + public boolean commit() throws LoginException { + Set anonPrincipal = subject + .getPrincipals(org.argeo.api.security.AnonymousPrincipal.class); + if (!anonPrincipal.isEmpty()) { + subject.getPrincipals().add(new AnonymousPrincipal()); + return true; + } + + Set initPrincipal = subject.getPrincipals(DataAdminPrincipal.class); + if (!initPrincipal.isEmpty()) { + subject.getPrincipals().add(new AdminPrincipal(SecurityConstants.ADMIN_ID)); + return true; + } + + Set userPrincipal = subject.getPrincipals(X500Principal.class); + if (userPrincipal.isEmpty()) + throw new LoginException("Subject must be pre-authenticated"); + if (userPrincipal.size() > 1) + throw new LoginException("Multiple user principals " + userPrincipal); + + return true; + } + + @Override + public boolean abort() throws LoginException { + return true; + } + + @Override + public boolean logout() throws LoginException { + subject.getPrincipals().removeAll(subject.getPrincipals(AnonymousPrincipal.class)); + subject.getPrincipals().removeAll(subject.getPrincipals(AdminPrincipal.class)); + return true; + } +} diff --git a/org.argeo.cms/src/org/argeo/security/jackrabbit/package-info.java b/org.argeo.cms/src/org/argeo/security/jackrabbit/package-info.java new file mode 100644 index 000000000..8529cc207 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/security/jackrabbit/package-info.java @@ -0,0 +1,2 @@ +/** Integration of Jackrabbit with Argeo security model. */ +package org.argeo.security.jackrabbit; \ No newline at end of file diff --git a/org.argeo.ext.equinox.jetty/bnd.bnd b/org.argeo.ext.equinox.jetty/bnd.bnd index c114be661..0f21e73c9 100644 --- a/org.argeo.ext.equinox.jetty/bnd.bnd +++ b/org.argeo.ext.equinox.jetty/bnd.bnd @@ -4,6 +4,4 @@ Import-Package: org.eclipse.jetty.websocket.jsr356,\ org.eclipse.jetty.websocket.api,\ org.eclipse.jetty.websocket.common,\ org.osgi.service.http,\ -org.argeo.cms.auth,\ -org.argeo.api,\ * \ No newline at end of file diff --git a/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoAccessControlProvider.java b/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoAccessControlProvider.java deleted file mode 100644 index bffe531a1..000000000 --- a/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoAccessControlProvider.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.argeo.security.jackrabbit; - -import java.security.Principal; -import java.util.Map; -import java.util.Set; - -import javax.jcr.RepositoryException; -import javax.jcr.Session; - -import org.apache.jackrabbit.core.security.authorization.acl.ACLProvider; - -/** Argeo specific access control provider */ -public class ArgeoAccessControlProvider extends ACLProvider { - - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - public void init(Session systemSession, Map configuration) throws RepositoryException { - if (!configuration.containsKey(PARAM_ALLOW_UNKNOWN_PRINCIPALS)) - configuration.put(PARAM_ALLOW_UNKNOWN_PRINCIPALS, "true"); - if (!configuration.containsKey(PARAM_OMIT_DEFAULT_PERMISSIONS)) - configuration.put(PARAM_OMIT_DEFAULT_PERMISSIONS, "true"); - super.init(systemSession, configuration); - } - - @Override - public boolean canAccessRoot(Set principals) throws RepositoryException { - return super.canAccessRoot(principals); - } - -} diff --git a/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoAccessManager.java b/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoAccessManager.java deleted file mode 100644 index 52ea3c984..000000000 --- a/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoAccessManager.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jackrabbit; - -import javax.jcr.PathNotFoundException; -import javax.jcr.RepositoryException; -import javax.jcr.security.Privilege; - -import org.apache.jackrabbit.core.id.ItemId; -import org.apache.jackrabbit.core.security.DefaultAccessManager; -import org.apache.jackrabbit.spi.Path; - -/** - * Intermediary class in order to have a consistent naming in config files. Does - * nothing for the time being, but may in the future. - */ -public class ArgeoAccessManager extends DefaultAccessManager { - - @Override - public boolean canRead(Path itemPath, ItemId itemId) - throws RepositoryException { - return super.canRead(itemPath, itemId); - } - - @Override - public Privilege[] getPrivileges(String absPath) - throws PathNotFoundException, RepositoryException { - return super.getPrivileges(absPath); - } - - @Override - public boolean hasPrivileges(String absPath, Privilege[] privileges) - throws PathNotFoundException, RepositoryException { - return super.hasPrivileges(absPath, privileges); - } - -} diff --git a/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java b/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java deleted file mode 100644 index 3976f3ba9..000000000 --- a/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.jackrabbit; - -import java.security.Principal; -import java.util.HashSet; -import java.util.Properties; -import java.util.Set; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.security.auth.Subject; -import javax.security.auth.x500.X500Principal; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.jackrabbit.api.security.user.UserManager; -import org.apache.jackrabbit.core.DefaultSecurityManager; -import org.apache.jackrabbit.core.security.AMContext; -import org.apache.jackrabbit.core.security.AccessManager; -import org.apache.jackrabbit.core.security.SecurityConstants; -import org.apache.jackrabbit.core.security.SystemPrincipal; -import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager; -import org.apache.jackrabbit.core.security.principal.AdminPrincipal; -import org.apache.jackrabbit.core.security.principal.PrincipalProvider; -import org.argeo.api.NodeConstants; -import org.argeo.api.security.AnonymousPrincipal; -import org.argeo.api.security.DataAdminPrincipal; -import org.argeo.cms.auth.CmsSession; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; - -/** Customises Jackrabbit security. */ -public class ArgeoSecurityManager extends DefaultSecurityManager { - private final static Log log = LogFactory.getLog(ArgeoSecurityManager.class); - - private BundleContext cmsBundleContext = null; - - public ArgeoSecurityManager() { - if (FrameworkUtil.getBundle(CmsSession.class) != null) { - cmsBundleContext = FrameworkUtil.getBundle(CmsSession.class).getBundleContext(); - } - } - - @Override - public AccessManager getAccessManager(Session session, AMContext amContext) throws RepositoryException { - synchronized (getSystemSession()) { - return super.getAccessManager(session, amContext); - } - } - - @Override - public UserManager getUserManager(Session session) throws RepositoryException { - synchronized (getSystemSession()) { - return super.getUserManager(session); - } - } - - @Override - protected PrincipalProvider createDefaultPrincipalProvider(Properties[] moduleConfig) throws RepositoryException { - return super.createDefaultPrincipalProvider(moduleConfig); - } - - /** Called once when the session is created */ - @Override - public String getUserID(Subject subject, String workspaceName) throws RepositoryException { - boolean isAnonymous = !subject.getPrincipals(AnonymousPrincipal.class).isEmpty(); - boolean isDataAdmin = !subject.getPrincipals(DataAdminPrincipal.class).isEmpty(); - boolean isJackrabbitSystem = !subject.getPrincipals(SystemPrincipal.class).isEmpty(); - Set userPrincipal = subject.getPrincipals(X500Principal.class); - boolean isRegularUser = !userPrincipal.isEmpty(); - CmsSession cmsSession = null; - if (cmsBundleContext != null) { - cmsSession = CmsSession.getCmsSession(cmsBundleContext, subject); - if (log.isTraceEnabled()) - log.trace("Opening JCR session for CMS session " + cmsSession); - } - - if (isAnonymous) { - if (isDataAdmin || isJackrabbitSystem || isRegularUser) - throw new IllegalStateException("Inconsistent " + subject); - else - return NodeConstants.ROLE_ANONYMOUS; - } else if (isRegularUser) {// must be before DataAdmin - if (isAnonymous || isJackrabbitSystem) - throw new IllegalStateException("Inconsistent " + subject); - else { - if (userPrincipal.size() > 1) { - StringBuilder buf = new StringBuilder(); - for (X500Principal principal : userPrincipal) - buf.append(' ').append('\"').append(principal).append('\"'); - throw new RuntimeException("Multiple user principals:" + buf); - } - return userPrincipal.iterator().next().getName(); - } - } else if (isDataAdmin) { - if (isAnonymous || isJackrabbitSystem || isRegularUser) - throw new IllegalStateException("Inconsistent " + subject); - else { - assert !subject.getPrincipals(AdminPrincipal.class).isEmpty(); - return NodeConstants.ROLE_DATA_ADMIN; - } - } else if (isJackrabbitSystem) { - if (isAnonymous || isDataAdmin || isRegularUser) - throw new IllegalStateException("Inconsistent " + subject); - else - return super.getUserID(subject, workspaceName); - } else { - throw new IllegalStateException("Unrecognized subject type: " + subject); - } - } - - @Override - protected WorkspaceAccessManager createDefaultWorkspaceAccessManager() { - WorkspaceAccessManager wam = super.createDefaultWorkspaceAccessManager(); - ArgeoWorkspaceAccessManagerImpl workspaceAccessManager = new ArgeoWorkspaceAccessManagerImpl(wam); - if (log.isTraceEnabled()) - log.trace("Created workspace access manager"); - return workspaceAccessManager; - } - - private class ArgeoWorkspaceAccessManagerImpl implements SecurityConstants, WorkspaceAccessManager { - private final WorkspaceAccessManager wam; - - public ArgeoWorkspaceAccessManagerImpl(WorkspaceAccessManager wam) { - super(); - this.wam = wam; - } - - public void init(Session systemSession) throws RepositoryException { - wam.init(systemSession); - Repository repository = systemSession.getRepository(); - if (log.isTraceEnabled()) - log.trace("Initialised workspace access manager on repository " + repository - + ", systemSession workspace: " + systemSession.getWorkspace().getName()); - } - - public void close() throws RepositoryException { - } - - public boolean grants(Set principals, String workspaceName) throws RepositoryException { - // TODO: implements finer access to workspaces - if (log.isTraceEnabled()) - log.trace("Grants " + new HashSet<>(principals) + " access to workspace '" + workspaceName + "'"); - return true; - // return wam.grants(principals, workspaceName); - } - } - -} diff --git a/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java b/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java deleted file mode 100644 index 4b7734623..000000000 --- a/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.argeo.security.jackrabbit; - -import java.util.Map; -import java.util.Set; - -import javax.security.auth.Subject; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.login.LoginException; -import javax.security.auth.spi.LoginModule; -import javax.security.auth.x500.X500Principal; - -import org.apache.jackrabbit.core.security.AnonymousPrincipal; -import org.apache.jackrabbit.core.security.SecurityConstants; -import org.apache.jackrabbit.core.security.principal.AdminPrincipal; -import org.argeo.api.security.DataAdminPrincipal; - -public class SystemJackrabbitLoginModule implements LoginModule { - private Subject subject; - - @Override - public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, - Map options) { - this.subject = subject; - } - - @Override - public boolean login() throws LoginException { - return true; - } - - @Override - public boolean commit() throws LoginException { - Set anonPrincipal = subject.getPrincipals(org.argeo.api.security.AnonymousPrincipal.class); - if (!anonPrincipal.isEmpty()) { - subject.getPrincipals().add(new AnonymousPrincipal()); - return true; - } - - Set initPrincipal = subject.getPrincipals(DataAdminPrincipal.class); - if (!initPrincipal.isEmpty()) { - subject.getPrincipals().add(new AdminPrincipal(SecurityConstants.ADMIN_ID)); - return true; - } - - Set userPrincipal = subject.getPrincipals(X500Principal.class); - if (userPrincipal.isEmpty()) - throw new LoginException("Subject must be pre-authenticated"); - if (userPrincipal.size() > 1) - throw new LoginException("Multiple user principals " + userPrincipal); - - return true; - } - - @Override - public boolean abort() throws LoginException { - return true; - } - - @Override - public boolean logout() throws LoginException { - subject.getPrincipals().removeAll(subject.getPrincipals(AnonymousPrincipal.class)); - subject.getPrincipals().removeAll(subject.getPrincipals(AdminPrincipal.class)); - return true; - } -} diff --git a/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/package-info.java b/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/package-info.java deleted file mode 100644 index 8529cc207..000000000 --- a/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/package-info.java +++ /dev/null @@ -1,2 +0,0 @@ -/** Integration of Jackrabbit with Argeo security model. */ -package org.argeo.security.jackrabbit; \ No newline at end of file diff --git a/pom.xml b/pom.xml index 446687adf..a9e796642 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,7 @@ org.argeo.cms.e4 org.argeo.cms.e4.rap - org.argeo.ext.jackrabbit + org.argeo.ext.equinox.jetty dep