From f4da6777015da3fc392138f0c01cea2f2add9ed3 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sun, 9 Jan 2022 08:42:55 +0100 Subject: [PATCH] Refactor CMS life cycle. --- .../src/org/argeo/api/cms/CmsContext.java | 10 + .../src/org/argeo/api/cms/CmsDeployment.java | 5 +- .../src/org/argeo/api/cms/CmsState.java | 7 - .../e4/maintenance/DeploymentEntryPoint.java | 7 +- .../src/org/argeo/cms/swt/auth/CmsLogin.java | 9 +- org.argeo.cms/OSGI-INF/cmsContext.xml | 10 + org.argeo.cms/OSGI-INF/cmsDeployment.xml | 9 + org.argeo.cms/OSGI-INF/cmsState.xml | 7 + org.argeo.cms/OSGI-INF/deployConfig.xml | 8 + org.argeo.cms/OSGI-INF/nodeUserAdmin.xml | 10 + .../OSGI-INF/simpleTransactionManager.xml | 8 + org.argeo.cms/bnd.bnd | 16 +- org.argeo.cms/build.properties | 8 +- .../src/org/argeo/cms/auth/CurrentUser.java | 8 +- .../org/argeo/cms/auth/IdentLoginModule.java | 4 +- .../cms/auth/RemoteSessionLoginModule.java | 5 +- .../org/argeo/cms/auth/SpnegoLoginModule.java | 7 +- .../argeo/cms/auth/UserAdminLoginModule.java | 7 +- .../http/client/SpnegoAuthScheme.java | 2 +- .../argeo/cms/internal/kernel/Activator.java | 292 ------------------ .../cms/internal/kernel/CmsContextImpl.java | 54 ---- .../internal/kernel/CmsDeploymentImpl.java | 243 --------------- .../argeo/cms/internal/osgi/CmsActivator.java | 269 ++++++++++++++++ .../{kernel => osgi}/CmsShutdown.java | 4 +- .../{kernel => osgi}/DeployConfig.java | 91 ++++-- .../internal/{kernel => osgi}/NodeLogger.java | 6 +- .../{kernel => osgi}/NodeUserAdmin.java | 124 +++++--- .../{kernel => osgi}/SecurityProfile.java | 2 +- .../internal/{kernel => runtime}/.gitignore | 0 .../cms/internal/runtime/CmsContextImpl.java | 201 ++++++++++++ .../internal/runtime/CmsDeploymentImpl.java | 207 +++++++++++++ .../{kernel => runtime}/CmsStateImpl.java | 145 +++++---- .../{kernel => runtime}/GogoShellKiller.java | 2 +- .../{kernel => runtime}/InitUtils.java | 15 +- .../{kernel => runtime}/KernelConstants.java | 2 +- .../{kernel => runtime}/KernelUtils.java | 57 ++-- .../{kernel => runtime}/PkiUtils.java | 2 +- .../dc=example,dc=com.ldif | 0 .../example-ou=roles,ou=node.ldif | 0 .../internal/{kernel => runtime}/jaas-ipa.cfg | 0 .../cms/internal/{kernel => runtime}/jaas.cfg | 0 .../{kernel => runtime}/ou=roles,ou=node.ldif | 0 .../ou=tokens,ou=node.ldif | 0 .../osgi/useradmin/AggregatingUserAdmin.java | 1 + 44 files changed, 1070 insertions(+), 794 deletions(-) create mode 100644 org.argeo.cms/OSGI-INF/cmsContext.xml create mode 100644 org.argeo.cms/OSGI-INF/cmsDeployment.xml create mode 100644 org.argeo.cms/OSGI-INF/cmsState.xml create mode 100644 org.argeo.cms/OSGI-INF/deployConfig.xml create mode 100644 org.argeo.cms/OSGI-INF/nodeUserAdmin.xml create mode 100644 org.argeo.cms/OSGI-INF/simpleTransactionManager.xml delete mode 100644 org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java delete mode 100644 org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsContextImpl.java delete mode 100644 org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeploymentImpl.java create mode 100644 org.argeo.cms/src/org/argeo/cms/internal/osgi/CmsActivator.java rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => osgi}/CmsShutdown.java (96%) rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => osgi}/DeployConfig.java (85%) rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => osgi}/NodeLogger.java (98%) rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => osgi}/NodeUserAdmin.java (79%) rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => osgi}/SecurityProfile.java (99%) rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => runtime}/.gitignore (100%) create mode 100644 org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java create mode 100644 org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => runtime}/CmsStateImpl.java (61%) rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => runtime}/GogoShellKiller.java (97%) rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => runtime}/InitUtils.java (96%) rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => runtime}/KernelConstants.java (97%) rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => runtime}/KernelUtils.java (83%) rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => runtime}/PkiUtils.java (99%) rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => runtime}/dc=example,dc=com.ldif (100%) rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => runtime}/example-ou=roles,ou=node.ldif (100%) rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => runtime}/jaas-ipa.cfg (100%) rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => runtime}/jaas.cfg (100%) rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => runtime}/ou=roles,ou=node.ldif (100%) rename org.argeo.cms/src/org/argeo/cms/internal/{kernel => runtime}/ou=tokens,ou=node.ldif (100%) diff --git a/org.argeo.api/src/org/argeo/api/cms/CmsContext.java b/org.argeo.api/src/org/argeo/api/cms/CmsContext.java index a9616c8ae..fa26b253a 100644 --- a/org.argeo.api/src/org/argeo/api/cms/CmsContext.java +++ b/org.argeo.api/src/org/argeo/api/cms/CmsContext.java @@ -1,5 +1,8 @@ package org.argeo.api.cms; +import java.util.List; +import java.util.Locale; + /** * A logical view on this CMS instance, independently of a particular launch or * deployment. @@ -11,6 +14,13 @@ public interface CmsContext { */ public final static String WORKGROUP = "workgroup"; + Locale getDefaultLocale(); + + List getLocales(); + + Long getAvailableSince(); + + /** Mark this group as a workgroup */ void createWorkgroup(String groupDn); } diff --git a/org.argeo.api/src/org/argeo/api/cms/CmsDeployment.java b/org.argeo.api/src/org/argeo/api/cms/CmsDeployment.java index 9498f96f3..5893d2ec5 100644 --- a/org.argeo.api/src/org/argeo/api/cms/CmsDeployment.java +++ b/org.argeo.api/src/org/argeo/api/cms/CmsDeployment.java @@ -4,9 +4,8 @@ import java.util.Dictionary; /** A configured node deployment. */ public interface CmsDeployment { - Long getAvailableSince(); - + void addFactoryDeployConfig(String factoryPid, Dictionary props); - Dictionary getProps(String factoryPid, String cn); + Dictionary getProps(String factoryPid, String cn); } diff --git a/org.argeo.api/src/org/argeo/api/cms/CmsState.java b/org.argeo.api/src/org/argeo/api/cms/CmsState.java index 26427003e..ed8698fca 100644 --- a/org.argeo.api/src/org/argeo/api/cms/CmsState.java +++ b/org.argeo.api/src/org/argeo/api/cms/CmsState.java @@ -1,14 +1,7 @@ package org.argeo.api.cms; -import java.util.List; -import java.util.Locale; - /** A running node process. */ public interface CmsState { - Locale getDefaultLocale(); - - List getLocales(); - String getHostname(); Long getAvailableSince(); diff --git a/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/DeploymentEntryPoint.java b/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/DeploymentEntryPoint.java index 6aaa1692f..e713f53e1 100644 --- a/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/DeploymentEntryPoint.java +++ b/org.argeo.cms.e4/src/org/argeo/cms/e4/maintenance/DeploymentEntryPoint.java @@ -3,9 +3,10 @@ package org.argeo.cms.e4.maintenance; import java.util.GregorianCalendar; import java.util.TimeZone; -import org.argeo.api.cms.CmsState; import org.argeo.api.cms.CmsConstants; +import org.argeo.api.cms.CmsContext; import org.argeo.api.cms.CmsDeployment; +import org.argeo.api.cms.CmsState; import org.argeo.cms.swt.CmsSwtUtils; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FillLayout; @@ -66,14 +67,14 @@ class DeploymentEntryPoint { if (nodeStateRef == null) throw new IllegalStateException("No CMS state available"); CmsState nodeState = bc.getService(nodeStateRef); - ServiceReference nodeDeploymentRef = bc.getServiceReference(CmsDeployment.class); + ServiceReference nodeDeploymentRef = bc.getServiceReference(CmsContext.class); Label label = new Label(composite, SWT.WRAP); CmsSwtUtils.markup(label); if (nodeDeploymentRef == null) { label.setText("Not yet deployed on
" + nodeState.getHostname() + "
, please configure below."); } else { Object stateUuid = nodeStateRef.getProperty(CmsConstants.CN); - CmsDeployment nodeDeployment = bc.getService(nodeDeploymentRef); + CmsContext nodeDeployment = bc.getService(nodeDeploymentRef); GregorianCalendar calendar = new GregorianCalendar(); calendar.setTimeInMillis(nodeDeployment.getAvailableSince()); calendar.setTimeZone(TimeZone.getDefault()); diff --git a/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CmsLogin.java b/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CmsLogin.java index 42eedf1a3..9c8680c4d 100644 --- a/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CmsLogin.java +++ b/org.argeo.cms.swt/src/org/argeo/cms/swt/auth/CmsLogin.java @@ -17,10 +17,10 @@ import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; -import org.argeo.api.cms.CmsView; -import org.argeo.api.cms.CmsLog; import org.argeo.api.cms.CmsAuth; -import org.argeo.api.cms.CmsState; +import org.argeo.api.cms.CmsContext; +import org.argeo.api.cms.CmsLog; +import org.argeo.api.cms.CmsView; import org.argeo.cms.CmsMsg; import org.argeo.cms.LocaleUtils; import org.argeo.cms.auth.RemoteAuthCallback; @@ -64,7 +64,8 @@ public class CmsLogin implements CmsStyles, CallbackHandler { public CmsLogin(CmsView cmsView) { this.cmsView = cmsView; - CmsState nodeState = null;// = Activator.getNodeState(); + CmsContext nodeState = null;// = Activator.getNodeState(); + // FIXME reactivate locales if (nodeState != null) { defaultLocale = nodeState.getDefaultLocale(); List locales = nodeState.getLocales(); diff --git a/org.argeo.cms/OSGI-INF/cmsContext.xml b/org.argeo.cms/OSGI-INF/cmsContext.xml new file mode 100644 index 000000000..c46b3a4e1 --- /dev/null +++ b/org.argeo.cms/OSGI-INF/cmsContext.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/org.argeo.cms/OSGI-INF/cmsDeployment.xml b/org.argeo.cms/OSGI-INF/cmsDeployment.xml new file mode 100644 index 000000000..4093f3e21 --- /dev/null +++ b/org.argeo.cms/OSGI-INF/cmsDeployment.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/org.argeo.cms/OSGI-INF/cmsState.xml b/org.argeo.cms/OSGI-INF/cmsState.xml new file mode 100644 index 000000000..9e9ecc4df --- /dev/null +++ b/org.argeo.cms/OSGI-INF/cmsState.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.argeo.cms/OSGI-INF/deployConfig.xml b/org.argeo.cms/OSGI-INF/deployConfig.xml new file mode 100644 index 000000000..10fcb547f --- /dev/null +++ b/org.argeo.cms/OSGI-INF/deployConfig.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/org.argeo.cms/OSGI-INF/nodeUserAdmin.xml b/org.argeo.cms/OSGI-INF/nodeUserAdmin.xml new file mode 100644 index 000000000..7becce748 --- /dev/null +++ b/org.argeo.cms/OSGI-INF/nodeUserAdmin.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/org.argeo.cms/OSGI-INF/simpleTransactionManager.xml b/org.argeo.cms/OSGI-INF/simpleTransactionManager.xml new file mode 100644 index 000000000..c331aa430 --- /dev/null +++ b/org.argeo.cms/OSGI-INF/simpleTransactionManager.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/org.argeo.cms/bnd.bnd b/org.argeo.cms/bnd.bnd index 61cb6cbab..e75adcdc3 100644 --- a/org.argeo.cms/bnd.bnd +++ b/org.argeo.cms/bnd.bnd @@ -1,10 +1,18 @@ -Bundle-Activator: org.argeo.cms.internal.kernel.Activator +Bundle-Activator: org.argeo.cms.internal.osgi.CmsActivator -Import-Package: org.apache.commons.httpclient.cookie;resolution:=optional,\ +Import-Package: \ +org.argeo.osgi.transaction, \ +org.apache.commons.httpclient.cookie;resolution:=optional,\ !com.sun.security.jgss,\ org.osgi.*;version=0.0.0,\ * -#Service-Component:\ -#OSGI-INF/cmsUserManager.xml,\ +Service-Component:\ +OSGI-INF/cmsState.xml,\ +OSGI-INF/simpleTransactionManager.xml,\ +OSGI-INF/nodeUserAdmin.xml,\ +OSGI-INF/cmsUserManager.xml,\ +OSGI-INF/deployConfig.xml,\ +OSGI-INF/cmsDeployment.xml,\ +OSGI-INF/cmsContext.xml,\ diff --git a/org.argeo.cms/build.properties b/org.argeo.cms/build.properties index 67b98f4d0..db86d95a5 100644 --- a/org.argeo.cms/build.properties +++ b/org.argeo.cms/build.properties @@ -2,5 +2,11 @@ output.. = bin/ bin.includes = META-INF/,\ .,\ bin/,\ - OSGI-INF/ + OSGI-INF/,\ + OSGI-INF/simpleTransactionManager.xml,\ + OSGI-INF/cmsState.xml,\ + OSGI-INF/nodeUserAdmin.xml,\ + OSGI-INF/deployConfig.xml,\ + OSGI-INF/cmsDeployment.xml,\ + OSGI-INF/cmsContext.xml source.. = src/ diff --git a/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java b/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java index afb6360b4..85a482464 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java @@ -13,12 +13,12 @@ import java.util.UUID; import javax.security.auth.Subject; import javax.security.auth.x500.X500Principal; +import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsSession; import org.argeo.api.cms.CmsSessionId; -import org.argeo.api.cms.CmsConstants; import org.argeo.cms.internal.auth.CmsSessionImpl; import org.argeo.cms.internal.auth.ImpliedByPrincipal; -import org.argeo.cms.internal.kernel.Activator; +import org.argeo.cms.internal.runtime.CmsContextImpl; import org.osgi.service.useradmin.Authorization; /** @@ -107,7 +107,7 @@ public final class CurrentUser { public final static Locale locale(Subject subject) { Set locales = subject.getPublicCredentials(Locale.class); if (locales.isEmpty()) { - Locale defaultLocale = Activator.getNodeState().getDefaultLocale(); + Locale defaultLocale = CmsContextImpl.getCmsContext().getDefaultLocale(); return defaultLocale; } else return locales.iterator().next(); @@ -152,7 +152,7 @@ public final class CurrentUser { else return false; CmsSessionImpl cmsSession = CmsSessionImpl.getByUuid(nodeSessionId.toString()); - + // FIXME logout all views // TODO check why it is sometimes null if (cmsSession != null) diff --git a/org.argeo.cms/src/org/argeo/cms/auth/IdentLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/IdentLoginModule.java index ccf7fc724..097e588e4 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/IdentLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/IdentLoginModule.java @@ -12,7 +12,7 @@ import javax.security.auth.spi.LoginModule; import org.argeo.api.cms.CmsLog; import org.argeo.cms.auth.ident.IdentClient; -import org.argeo.cms.internal.kernel.Activator; +import org.argeo.cms.internal.runtime.CmsStateImpl; /** Use an ident service to identify. */ public class IdentLoginModule implements LoginModule { @@ -44,7 +44,7 @@ public class IdentLoginModule implements LoginModule { RemoteAuthRequest request = httpCallback.getRequest(); if (request == null) return false; - IdentClient identClient = Activator.getIdentClient(request.getRemoteAddr()); + IdentClient identClient = CmsStateImpl.getIdentClient(request.getRemoteAddr()); if (identClient == null) return false; String identUsername; diff --git a/org.argeo.cms/src/org/argeo/cms/auth/RemoteSessionLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/RemoteSessionLoginModule.java index 4d3617eef..962094d4a 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/RemoteSessionLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/RemoteSessionLoginModule.java @@ -14,9 +14,10 @@ import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; +import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsLog; import org.argeo.cms.internal.auth.CmsSessionImpl; -import org.argeo.cms.internal.kernel.Activator; +import org.argeo.cms.internal.runtime.KernelUtils; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.osgi.service.http.HttpContext; @@ -211,7 +212,7 @@ public class RemoteSessionLoginModule implements LoginModule { if (log.isDebugEnabled()) log.debug("Client certificate " + certDn + " verified by servlet container"); } // Reverse proxy verified the client certificate - String clientDnHttpHeader = Activator.getHttpProxySslHeader(); + String clientDnHttpHeader = KernelUtils.getFrameworkProp(CmsConstants.HTTP_PROXY_SSL_DN); if (clientDnHttpHeader != null) { String certDn = req.getHeader(clientDnHttpHeader); // TODO retrieve more cf. https://httpd.apache.org/docs/current/mod/mod_ssl.html diff --git a/org.argeo.cms/src/org/argeo/cms/auth/SpnegoLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/SpnegoLoginModule.java index c94480cb5..2dbad96d2 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/SpnegoLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/SpnegoLoginModule.java @@ -9,7 +9,7 @@ import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; import org.argeo.api.cms.CmsLog; -import org.argeo.cms.internal.kernel.Activator; +import org.argeo.cms.internal.runtime.CmsContextImpl; import org.ietf.jgss.GSSContext; import org.ietf.jgss.GSSCredential; import org.ietf.jgss.GSSException; @@ -111,7 +111,7 @@ public class SpnegoLoginModule implements LoginModule { private GSSContext checkToken(byte[] authToken) { GSSManager manager = GSSManager.getInstance(); try { - GSSContext gContext = manager.createContext(Activator.getAcceptorCredentials()); + GSSContext gContext = manager.createContext(CmsContextImpl.getAcceptorCredentials()); if (gContext == null) { log.debug("SpnegoUserRealm: failed to establish GSSContext"); @@ -132,7 +132,8 @@ public class SpnegoLoginModule implements LoginModule { } + @Deprecated public static boolean hasAcceptorCredentials() { - return Activator.getAcceptorCredentials() != null; + return CmsContextImpl.getAcceptorCredentials() != null; } } diff --git a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java index b9f8d4a51..738b507e7 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java @@ -26,7 +26,8 @@ import javax.security.auth.spi.LoginModule; import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsLog; -import org.argeo.cms.internal.kernel.Activator; +import org.argeo.cms.internal.osgi.NodeUserAdmin; +import org.argeo.cms.internal.runtime.CmsContextImpl; import org.argeo.cms.security.CryptoKeyring; import org.argeo.osgi.useradmin.AuthenticatingUser; import org.argeo.osgi.useradmin.IpaUtils; @@ -79,7 +80,7 @@ public class UserAdminLoginModule implements LoginModule { @Override public boolean login() throws LoginException { - UserAdmin userAdmin = Activator.getUserAdmin(); + UserAdmin userAdmin = CmsContextImpl.getUserAdmin(); final String username; final char[] password; Object certificateChain = null; @@ -211,7 +212,7 @@ public class UserAdminLoginModule implements LoginModule { // if (singleUser) { // OsUserUtils.loginAsSystemUser(subject); // } - UserAdmin userAdmin = Activator.getUserAdmin(); + UserAdmin userAdmin = CmsContextImpl.getUserAdmin(); Authorization authorization; if (callbackHandler == null) {// anonymous authorization = userAdmin.getAuthorization(null); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/client/SpnegoAuthScheme.java b/org.argeo.cms/src/org/argeo/cms/internal/http/client/SpnegoAuthScheme.java index 334e43c85..4abdd1458 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/http/client/SpnegoAuthScheme.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/http/client/SpnegoAuthScheme.java @@ -20,7 +20,7 @@ import org.apache.commons.httpclient.auth.MalformedChallengeException; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.params.DefaultHttpParams; import org.apache.commons.httpclient.params.HttpParams; -import org.argeo.cms.internal.kernel.KernelConstants; +import org.argeo.cms.internal.runtime.KernelConstants; import org.ietf.jgss.GSSContext; import org.ietf.jgss.GSSException; import org.ietf.jgss.GSSManager; 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 deleted file mode 100644 index f50594210..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java +++ /dev/null @@ -1,292 +0,0 @@ -package org.argeo.cms.internal.kernel; - -import java.io.IOException; -import java.net.URL; -import java.security.AllPermission; -import java.util.Dictionary; -import java.util.List; -import java.util.Locale; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import javax.security.auth.login.Configuration; - -import org.argeo.api.cms.CmsState; -import org.argeo.api.cms.CmsLog; -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsContext; -import org.argeo.api.cms.CmsDeployment; -import org.argeo.cms.ArgeoLogger; -import org.argeo.cms.auth.ident.IdentClient; -import org.ietf.jgss.GSSCredential; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; -import org.osgi.framework.Constants; -import org.osgi.framework.FrameworkUtil; -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.log.LogReaderService; -import org.osgi.service.permissionadmin.PermissionInfo; -import org.osgi.service.useradmin.UserAdmin; -import org.osgi.util.tracker.ServiceTracker; - -/** - * Activates the kernel. Gives access to kernel information for the rest of the - * bundle (and only it) - */ -public class Activator implements BundleActivator { - private final static CmsLog log = CmsLog.getLog(Activator.class); - - private static Activator instance; - - // TODO make it configurable - private boolean hardened = false; - - private static BundleContext bundleContext; - - private LogReaderService logReaderService; - - private NodeLogger logger; - private CmsStateImpl nodeState; - private CmsDeploymentImpl nodeDeployment; - private CmsContextImpl nodeInstance; - - private ServiceTracker userAdminSt; - private ExecutorService internalExecutorService; - - static { - Bundle bundle = FrameworkUtil.getBundle(Activator.class); - if (bundle != null) { - bundleContext = bundle.getBundleContext(); - } - } - - void init() { - Runtime.getRuntime().addShutdownHook(new CmsShutdown()); - instance = this; -// this.bc = bundleContext; - if (bundleContext != null) - this.logReaderService = getService(LogReaderService.class); - this.internalExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); - - try { - initSecurity(); -// initArgeoLogger(); - initNode(); - - if (log.isTraceEnabled()) - log.trace("Kernel bundle started"); - } catch (Throwable e) { - log.error("## FATAL: CMS activator failed", e); - } - } - - void destroy() { - try { - if (nodeInstance != null) - nodeInstance.shutdown(); - if (nodeDeployment != null) - nodeDeployment.shutdown(); - if (nodeState != null) - nodeState.shutdown(); - - if (userAdminSt != null) - userAdminSt.close(); - - internalExecutorService.shutdown(); - instance = null; - bundleContext = null; - this.logReaderService = null; - // this.configurationAdmin = null; - } catch (Exception e) { - log.error("CMS activator shutdown failed", e); - } - } - - private void initSecurity() { - if (System.getProperty(KernelConstants.JAAS_CONFIG_PROP) == null) { - String jaasConfig = KernelConstants.JAAS_CONFIG; - URL url = getClass().getResource(jaasConfig); - // System.setProperty(KernelConstants.JAAS_CONFIG_PROP, - // url.toExternalForm()); - KernelUtils.setJaasConfiguration(url); - } - // explicitly load JAAS configuration - Configuration.getConfiguration(); - - // code-level permissions - String osgiSecurity = KernelUtils.getFrameworkProp(Constants.FRAMEWORK_SECURITY); - if (osgiSecurity != null && Constants.FRAMEWORK_SECURITY_OSGI.equals(osgiSecurity)) { - // TODO rather use a tracker? - ConditionalPermissionAdmin permissionAdmin = bundleContext - .getService(bundleContext.getServiceReference(ConditionalPermissionAdmin.class)); - if (!hardened) { - // All permissions to all bundles - ConditionalPermissionUpdate update = permissionAdmin.newConditionalPermissionUpdate(); - update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null, - new ConditionInfo[] { - new ConditionInfo(BundleLocationCondition.class.getName(), new String[] { "*" }) }, - new PermissionInfo[] { new PermissionInfo(AllPermission.class.getName(), null, null) }, - ConditionalPermissionInfo.ALLOW)); - // TODO data admin permission -// PermissionInfo dataAdminPerm = new PermissionInfo(AuthPermission.class.getName(), -// "createLoginContext." + NodeConstants.LOGIN_CONTEXT_DATA_ADMIN, null); -// update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null, -// new ConditionInfo[] { -// new ConditionInfo(BundleLocationCondition.class.getName(), new String[] { "*" }) }, -// new PermissionInfo[] { dataAdminPerm }, ConditionalPermissionInfo.DENY)); -// update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null, -// new ConditionInfo[] { -// new ConditionInfo(BundleSignerCondition.class.getName(), new String[] { "CN=\"Eclipse.org Foundation, Inc.\", OU=IT, O=\"Eclipse.org Foundation, Inc.\", L=Nepean, ST=Ontario, C=CA" }) }, -// new PermissionInfo[] { dataAdminPerm }, ConditionalPermissionInfo.ALLOW)); - update.commit(); - } else { - SecurityProfile securityProfile = new SecurityProfile() { - }; - securityProfile.applySystemPermissions(permissionAdmin); - } - } - - } - - private void initArgeoLogger() { - logger = new NodeLogger(logReaderService); - if (bundleContext != null) - bundleContext.registerService(ArgeoLogger.class, logger, null); - } - - private void initNode() throws IOException { - // Node state - nodeState = new CmsStateImpl(); - registerService(CmsState.class, nodeState, null); - - // Node deployment - nodeDeployment = new CmsDeploymentImpl(); -// registerService(NodeDeployment.class, nodeDeployment, null); - - // Node instance - nodeInstance = new CmsContextImpl(); - registerService(CmsContext.class, nodeInstance, null); - } - - public static void registerService(Class clss, T service, Dictionary properties) { - if (bundleContext != null) { - bundleContext.registerService(clss, service, properties); - } - - } - - public static T getService(Class clss) { - if (bundleContext != null) { - return bundleContext.getService(bundleContext.getServiceReference(clss)); - } else { - return null; - } - } - - /* - * OSGi - */ - - @Override - public void start(BundleContext bc) throws Exception { - if (!bc.getBundle().equals(bundleContext.getBundle())) - throw new IllegalStateException( - "Bundle " + bc.getBundle() + " is not consistent with " + bundleContext.getBundle()); - init(); - userAdminSt = new ServiceTracker<>(bundleContext, UserAdmin.class, null); - userAdminSt.open(); - } - - @Override - public void stop(BundleContext bc) throws Exception { - if (!bc.getBundle().equals(bundleContext.getBundle())) - throw new IllegalStateException( - "Bundle " + bc.getBundle() + " is not consistent with " + bundleContext.getBundle()); - destroy(); - } - -// private T getService(Class clazz) { -// ServiceReference sr = bundleContext.getServiceReference(clazz); -// if (sr == null) -// throw new IllegalStateException("No service available for " + clazz); -// return bundleContext.getService(sr); -// } - - public static CmsState getNodeState() { - return instance.nodeState; - } - - public static GSSCredential getAcceptorCredentials() { - return getNodeUserAdmin().getAcceptorCredentials(); - } - - @Deprecated - public static boolean isSingleUser() { - return getNodeUserAdmin().isSingleUser(); - } - - public static UserAdmin getUserAdmin() { - return (UserAdmin) getNodeUserAdmin(); - } - - public static String getHttpProxySslHeader() { - return KernelUtils.getFrameworkProp(CmsConstants.HTTP_PROXY_SSL_DN); - } - - public static IdentClient getIdentClient(String remoteAddr) { - if (!IdentClient.isDefaultAuthdPassphraseFileAvailable()) - return null; - // TODO make passphrase more configurable - return new IdentClient(remoteAddr); - } - - private static NodeUserAdmin getNodeUserAdmin() { - NodeUserAdmin res; - try { - res = instance.userAdminSt.waitForService(60000); - } catch (InterruptedException e) { - throw new IllegalStateException("Cannot retrieve Node user admin", e); - } - if (res == null) - throw new IllegalStateException("No Node user admin found"); - - return res; - // ServiceReference sr = - // instance.bc.getServiceReference(UserAdmin.class); - // NodeUserAdmin userAdmin = (NodeUserAdmin) instance.bc.getService(sr); - // return userAdmin; - - } - - static ExecutorService getInternalExecutorService() { - return instance.internalExecutorService; - } - - // static CmsSecurity getCmsSecurity() { - // return instance.nodeSecurity; - // } - - public String[] getLocales() { - // TODO optimize? - List locales = getNodeState().getLocales(); - String[] res = new String[locales.size()]; - for (int i = 0; i < locales.size(); i++) - res[i] = locales.get(i).toString(); - return res; - } - - static BundleContext getBundleContext() { - return bundleContext; - } - - public static void main(String[] args) { - instance = new Activator(); - instance.init(); - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsContextImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsContextImpl.java deleted file mode 100644 index 822959b63..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsContextImpl.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.argeo.cms.internal.kernel; - -import org.argeo.api.cms.CmsContext; -import org.argeo.api.cms.CmsLog; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; - -public class CmsContextImpl implements CmsContext { - private final CmsLog log = CmsLog.getLog(getClass()); - private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); - -// private EgoRepository egoRepository; - - public CmsContextImpl() { - initTrackers(); - } - - private void initTrackers() { - // node repository -// new ServiceTracker(bc, Repository.class, null) { -// @Override -// public Repository addingService(ServiceReference reference) { -// Object cn = reference.getProperty(NodeConstants.CN); -// if (cn != null && cn.equals(NodeConstants.EGO_REPOSITORY)) { -//// egoRepository = (EgoRepository) bc.getService(reference); -// if (log.isTraceEnabled()) -// log.trace("Home repository is available"); -// } -// return super.addingService(reference); -// } -// -// @Override -// public void removedService(ServiceReference reference, Repository service) { -// super.removedService(reference, service); -//// egoRepository = null; -// } -// -// }.open(); - } - - public void shutdown() { - - } - - @Override - public void createWorkgroup(String dn) { -// if (egoRepository == null) -// throw new CmsException("Ego repository is not available"); -// // TODO add check that the group exists -// egoRepository.createWorkgroup(dn); - throw new UnsupportedOperationException(); - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeploymentImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeploymentImpl.java deleted file mode 100644 index 4c7cb1dbe..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeploymentImpl.java +++ /dev/null @@ -1,243 +0,0 @@ -package org.argeo.cms.internal.kernel; - -import java.io.IOException; -import java.lang.management.ManagementFactory; -import java.net.URL; -import java.util.Dictionary; - -import org.argeo.api.cms.CmsState; -import org.argeo.api.cms.CmsLog; -import org.argeo.api.cms.CmsConstants; -import org.argeo.api.cms.CmsDeployment; -import org.argeo.osgi.transaction.WorkTransaction; -import org.argeo.osgi.useradmin.UserAdminConf; -import org.eclipse.equinox.http.jetty.JettyConfigurator; -import org.osgi.framework.BundleContext; -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.http.HttpService; -import org.osgi.service.useradmin.Group; -import org.osgi.service.useradmin.Role; -import org.osgi.service.useradmin.UserAdmin; -import org.osgi.util.tracker.ServiceTracker; - -/** Implementation of a CMS deployment. */ -public class CmsDeploymentImpl implements CmsDeployment { - private final CmsLog log = CmsLog.getLog(getClass()); - private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); - - private DeployConfig deployConfig; - - private Long availableSince; - - // Readiness - private boolean nodeAvailable = false; - private boolean userAdminAvailable = false; - private boolean httpExpected = false; - private boolean httpAvailable = false; - - public CmsDeploymentImpl() { -// ServiceReference nodeStateSr = bc.getServiceReference(NodeState.class); -// if (nodeStateSr == null) -// throw new CmsException("No node state available"); - -// NodeState nodeState = bc.getService(nodeStateSr); -// cleanState = nodeState.isClean(); - -// nodeHttp = new NodeHttp(); - initTrackers(); - } - - private void initTrackers() { - ServiceTracker httpSt = new ServiceTracker(bc, HttpService.class, null) { - - @Override - public HttpService addingService(ServiceReference sr) { - httpAvailable = true; - Object httpPort = sr.getProperty("http.port"); - Object httpsPort = sr.getProperty("https.port"); - log.info(httpPortsMsg(httpPort, httpsPort)); - checkReadiness(); - return super.addingService(sr); - } - }; - // httpSt.open(); - KernelUtils.asyncOpen(httpSt); - - ServiceTracker userAdminSt = new ServiceTracker(bc, UserAdmin.class, null) { - @Override - public UserAdmin addingService(ServiceReference reference) { - UserAdmin userAdmin = super.addingService(reference); - addStandardSystemRoles(userAdmin); - userAdminAvailable = true; - checkReadiness(); - return userAdmin; - } - }; - // userAdminSt.open(); - KernelUtils.asyncOpen(userAdminSt); - - ServiceTracker confAdminSt = new ServiceTracker(bc, - ConfigurationAdmin.class, null) { - @Override - public ConfigurationAdmin addingService(ServiceReference reference) { - ConfigurationAdmin configurationAdmin = bc.getService(reference); - boolean isClean; - try { - Configuration[] confs = configurationAdmin - .listConfigurations("(service.factoryPid=" + CmsConstants.NODE_USER_ADMIN_PID + ")"); - isClean = confs == null || confs.length == 0; - } catch (Exception e) { - throw new IllegalStateException("Cannot analyse clean state", e); - } - deployConfig = new DeployConfig(configurationAdmin, isClean); - Activator.registerService(CmsDeployment.class, CmsDeploymentImpl.this, null); -// JcrInitUtils.addToDeployment(CmsDeployment.this); - httpExpected = deployConfig.getProps(KernelConstants.JETTY_FACTORY_PID, "default") != null; - try { - Configuration[] configs = configurationAdmin - .listConfigurations("(service.factoryPid=" + CmsConstants.NODE_USER_ADMIN_PID + ")"); - - boolean hasDomain = false; - for (Configuration config : configs) { - Object realm = config.getProperties().get(UserAdminConf.realm.name()); - if (realm != null) { - log.debug("Found realm: " + realm); - hasDomain = true; - } - } - if (hasDomain) { - loadIpaJaasConfiguration(); - } - } catch (Exception e) { - throw new IllegalStateException("Cannot initialize config", e); - } - return super.addingService(reference); - } - }; - // confAdminSt.open(); - KernelUtils.asyncOpen(confAdminSt); - } - - public void addFactoryDeployConfig(String factoryPid, Dictionary props) { - deployConfig.putFactoryDeployConfig(factoryPid, props); - deployConfig.save(); - try { - deployConfig.loadConfigs(); - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - - public Dictionary getProps(String factoryPid, String cn) { - return deployConfig.getProps(factoryPid, cn); - } - - private String httpPortsMsg(Object httpPort, Object httpsPort) { - return (httpPort != null ? "HTTP " + httpPort + " " : " ") + (httpsPort != null ? "HTTPS " + httpsPort : ""); - } - - private void addStandardSystemRoles(UserAdmin userAdmin) { - // we assume UserTransaction is already available (TODO make it more robust) - WorkTransaction userTransaction = bc.getService(bc.getServiceReference(WorkTransaction.class)); - try { - userTransaction.begin(); - Role adminRole = userAdmin.getRole(CmsConstants.ROLE_ADMIN); - if (adminRole == null) { - adminRole = userAdmin.createRole(CmsConstants.ROLE_ADMIN, Role.GROUP); - } - if (userAdmin.getRole(CmsConstants.ROLE_USER_ADMIN) == null) { - Group userAdminRole = (Group) userAdmin.createRole(CmsConstants.ROLE_USER_ADMIN, Role.GROUP); - userAdminRole.addMember(adminRole); - } - userTransaction.commit(); - } catch (Exception e) { - try { - userTransaction.rollback(); - } catch (Exception e1) { - // silent - } - throw new IllegalStateException("Cannot add standard system roles", e); - } - } - - private void loadIpaJaasConfiguration() { - if (System.getProperty(KernelConstants.JAAS_CONFIG_PROP) == null) { - String jaasConfig = KernelConstants.JAAS_CONFIG_IPA; - URL url = getClass().getClassLoader().getResource(jaasConfig); - KernelUtils.setJaasConfiguration(url); - log.debug("Set IPA JAAS configuration."); - } - } - - public void shutdown() { -// if (nodeHttp != null) -// nodeHttp.destroy(); - - try { - JettyConfigurator.stopServer(KernelConstants.DEFAULT_JETTY_SERVER); - } catch (Exception e) { - log.error("Cannot stop default Jetty server.", e); - } - - if (deployConfig != null) { - new Thread(() -> deployConfig.save(), "Save Argeo Deploy Config").start(); - } - } - - /** - * Checks whether the deployment is available according to expectations, and - * mark it as available. - */ - private synchronized void checkReadiness() { - if (isAvailable()) - return; - if (nodeAvailable && userAdminAvailable && (httpExpected ? httpAvailable : true)) { - String data = KernelUtils.getFrameworkProp(KernelUtils.OSGI_INSTANCE_AREA); - String state = KernelUtils.getFrameworkProp(KernelUtils.OSGI_CONFIGURATION_AREA); - availableSince = System.currentTimeMillis(); - long jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime(); - String jvmUptimeStr = " in " + (jvmUptime / 1000) + "." + (jvmUptime % 1000) + "s"; - log.info("## ARGEO NODE AVAILABLE" + (log.isDebugEnabled() ? jvmUptimeStr : "") + " ##"); - if (log.isDebugEnabled()) { - log.debug("## state: " + state); - if (data != null) - log.debug("## data: " + data); - } - long begin = bc.getService(bc.getServiceReference(CmsState.class)).getAvailableSince(); - long initDuration = System.currentTimeMillis() - begin; - if (log.isTraceEnabled()) - log.trace("Kernel initialization took " + initDuration + "ms"); - tributeToFreeSoftware(initDuration); - } - } - - final private void tributeToFreeSoftware(long initDuration) { - if (log.isTraceEnabled()) { - long ms = initDuration / 100; - log.trace("Spend " + ms + "ms" + " reflecting on the progress brought to mankind" + " by Free Software..."); - long beginNano = System.nanoTime(); - try { - Thread.sleep(ms, 0); - } catch (InterruptedException e) { - // silent - } - long durationNano = System.nanoTime() - beginNano; - final double M = 1000d * 1000d; - double sleepAccuracy = ((double) durationNano) / (ms * M); - log.trace("Sleep accuracy: " + String.format("%.2f", 100 - (sleepAccuracy * 100 - 100)) + " %"); - } - } - - @Override - public synchronized Long getAvailableSince() { - return availableSince; - } - - public synchronized boolean isAvailable() { - return availableSince != null; - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/osgi/CmsActivator.java b/org.argeo.cms/src/org/argeo/cms/internal/osgi/CmsActivator.java new file mode 100644 index 000000000..d28ffdbb2 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/osgi/CmsActivator.java @@ -0,0 +1,269 @@ +package org.argeo.cms.internal.osgi; + +import java.security.AllPermission; +import java.util.Dictionary; + +import org.argeo.api.cms.CmsLog; +import org.argeo.cms.ArgeoLogger; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; +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.util.tracker.ServiceTracker; + +/** + * Activates the kernel. Gives access to kernel information for the rest of the + * bundle (and only it) + */ +public class CmsActivator implements BundleActivator { + private final static CmsLog log = CmsLog.getLog(CmsActivator.class); + +// private static Activator instance; + + // TODO make it configurable + private boolean hardened = false; + + private static BundleContext bundleContext; + + private LogReaderService logReaderService; + + private NodeLogger logger; +// private CmsStateImpl nodeState; +// private CmsDeploymentImpl nodeDeployment; +// private CmsContextImpl nodeInstance; + +// private ServiceTracker userAdminSt; + +// static { +// Bundle bundle = FrameworkUtil.getBundle(Activator.class); +// if (bundle != null) { +// bundleContext = bundle.getBundleContext(); +// } +// } + + void init() { +// Runtime.getRuntime().addShutdownHook(new CmsShutdown()); +// instance = this; +// this.bc = bundleContext; + if (bundleContext != null) + this.logReaderService = getService(LogReaderService.class); +// this.internalExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); +// +// try { +// initSecurity(); +//// initArgeoLogger(); +// initNode(); +// +// if (log.isTraceEnabled()) +// log.trace("Kernel bundle started"); +// } catch (Throwable e) { +// log.error("## FATAL: CMS activator failed", e); +// } + } + + void destroy() { + try { +// if (nodeInstance != null) +// nodeInstance.shutdown(); +// if (nodeDeployment != null) +// nodeDeployment.shutdown(); +// if (nodeState != null) +// nodeState.shutdown(); +// +// if (userAdminSt != null) +// userAdminSt.close(); + +// internalExecutorService.shutdown(); +// instance = null; + bundleContext = null; + this.logReaderService = null; + // this.configurationAdmin = null; + } catch (Exception e) { + log.error("CMS activator shutdown failed", e); + } + } + + private void initSecurity() { + // code-level permissions + String osgiSecurity = bundleContext.getProperty(Constants.FRAMEWORK_SECURITY); + if (osgiSecurity != null && Constants.FRAMEWORK_SECURITY_OSGI.equals(osgiSecurity)) { + // TODO rather use a tracker? + ConditionalPermissionAdmin permissionAdmin = bundleContext + .getService(bundleContext.getServiceReference(ConditionalPermissionAdmin.class)); + if (!hardened) { + // All permissions to all bundles + ConditionalPermissionUpdate update = permissionAdmin.newConditionalPermissionUpdate(); + update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null, + new ConditionInfo[] { + new ConditionInfo(BundleLocationCondition.class.getName(), new String[] { "*" }) }, + new PermissionInfo[] { new PermissionInfo(AllPermission.class.getName(), null, null) }, + ConditionalPermissionInfo.ALLOW)); + // TODO data admin permission +// PermissionInfo dataAdminPerm = new PermissionInfo(AuthPermission.class.getName(), +// "createLoginContext." + NodeConstants.LOGIN_CONTEXT_DATA_ADMIN, null); +// update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null, +// new ConditionInfo[] { +// new ConditionInfo(BundleLocationCondition.class.getName(), new String[] { "*" }) }, +// new PermissionInfo[] { dataAdminPerm }, ConditionalPermissionInfo.DENY)); +// update.getConditionalPermissionInfos().add(permissionAdmin.newConditionalPermissionInfo(null, +// new ConditionInfo[] { +// new ConditionInfo(BundleSignerCondition.class.getName(), new String[] { "CN=\"Eclipse.org Foundation, Inc.\", OU=IT, O=\"Eclipse.org Foundation, Inc.\", L=Nepean, ST=Ontario, C=CA" }) }, +// new PermissionInfo[] { dataAdminPerm }, ConditionalPermissionInfo.ALLOW)); + update.commit(); + } else { + SecurityProfile securityProfile = new SecurityProfile() { + }; + securityProfile.applySystemPermissions(permissionAdmin); + } + } + + } + + private void initArgeoLogger() { + logger = new NodeLogger(logReaderService); + if (bundleContext != null) + bundleContext.registerService(ArgeoLogger.class, logger, null); + } + +// private void initNode() throws IOException { +// // Node state +// nodeState = new CmsStateImpl(); +// registerService(CmsState.class, nodeState, null); +// +// // Node deployment +// nodeDeployment = new CmsDeploymentImpl(); +//// registerService(NodeDeployment.class, nodeDeployment, null); +// +// // Node instance +// nodeInstance = new CmsContextImpl(); +// registerService(CmsContext.class, nodeInstance, null); +// } + + public static void registerService(Class clss, T service, Dictionary properties) { + if (bundleContext != null) { + bundleContext.registerService(clss, service, properties); + } + + } + + public static T getService(Class clss) { + if (bundleContext != null) { + return bundleContext.getService(bundleContext.getServiceReference(clss)); + } else { + return null; + } + } + + /* + * OSGi + */ + + @Override + public void start(BundleContext bc) throws Exception { + bundleContext = bc; +// if (!bc.getBundle().equals(bundleContext.getBundle())) +// throw new IllegalStateException( +// "Bundle " + bc.getBundle() + " is not consistent with " + bundleContext.getBundle()); + init(); +// userAdminSt = new ServiceTracker<>(bundleContext, UserAdmin.class, null); +// userAdminSt.open(); + + ServiceTracker httpSt = new ServiceTracker(bc, HttpService.class, null) { + + @Override + public HttpService addingService(ServiceReference sr) { + Object httpPort = sr.getProperty("http.port"); + Object httpsPort = sr.getProperty("https.port"); + log.info(httpPortsMsg(httpPort, httpsPort)); + close(); + return super.addingService(sr); + } + }; + httpSt.open(); + } + + private String httpPortsMsg(Object httpPort, Object httpsPort) { + return (httpPort != null ? "HTTP " + httpPort + " " : " ") + (httpsPort != null ? "HTTPS " + httpsPort : ""); + } + + @Override + public void stop(BundleContext bc) throws Exception { +// if (!bc.getBundle().equals(bundleContext.getBundle())) +// throw new IllegalStateException( +// "Bundle " + bc.getBundle() + " is not consistent with " + bundleContext.getBundle()); + destroy(); + bundleContext = null; + } + +// private T getService(Class clazz) { +// ServiceReference sr = bundleContext.getServiceReference(clazz); +// if (sr == null) +// throw new IllegalStateException("No service available for " + clazz); +// return bundleContext.getService(sr); +// } + +// public static GSSCredential getAcceptorCredentials() { +// return getNodeUserAdmin().getAcceptorCredentials(); +// } +// +// @Deprecated +// public static boolean isSingleUser() { +// return getNodeUserAdmin().isSingleUser(); +// } +// +// public static UserAdmin getUserAdmin() { +// return (UserAdmin) getNodeUserAdmin(); +// } +// +// public static String getHttpProxySslHeader() { +// return KernelUtils.getFrameworkProp(CmsConstants.HTTP_PROXY_SSL_DN); +// } +// +// private static NodeUserAdmin getNodeUserAdmin() { +// NodeUserAdmin res; +// try { +// res = instance.userAdminSt.waitForService(60000); +// } catch (InterruptedException e) { +// throw new IllegalStateException("Cannot retrieve Node user admin", e); +// } +// if (res == null) +// throw new IllegalStateException("No Node user admin found"); +// +// return res; +// // ServiceReference sr = +// // instance.bc.getServiceReference(UserAdmin.class); +// // NodeUserAdmin userAdmin = (NodeUserAdmin) instance.bc.getService(sr); +// // return userAdmin; +// +// } + +// public static ExecutorService getInternalExecutorService() { +// return instance.internalExecutorService; +// } + + // static CmsSecurity getCmsSecurity() { + // return instance.nodeSecurity; + // } + +// public String[] getLocales() { +// // TODO optimize? +// List locales = CmsStateImpl.getNodeState().getLocales(); +// String[] res = new String[locales.size()]; +// for (int i = 0; i < locales.size(); i++) +// res[i] = locales.get(i).toString(); +// return res; +// } + + public static BundleContext getBundleContext() { + return bundleContext; + } + +} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsShutdown.java b/org.argeo.cms/src/org/argeo/cms/internal/osgi/CmsShutdown.java similarity index 96% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsShutdown.java rename to org.argeo.cms/src/org/argeo/cms/internal/osgi/CmsShutdown.java index eb7657edc..324462d39 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsShutdown.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/osgi/CmsShutdown.java @@ -1,4 +1,4 @@ -package org.argeo.cms.internal.kernel; +package org.argeo.cms.internal.osgi; import org.argeo.api.cms.CmsLog; import org.osgi.framework.Bundle; @@ -7,7 +7,7 @@ import org.osgi.framework.FrameworkUtil; import org.osgi.framework.launch.Framework; /** Shutdowns the OSGi framework */ -class CmsShutdown extends Thread { +public class CmsShutdown extends Thread { public final int EXIT_OK = 0; public final int EXIT_ERROR = 1; public final int EXIT_TIMEOUT = 2; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java b/org.argeo.cms/src/org/argeo/cms/internal/osgi/DeployConfig.java similarity index 85% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java rename to org.argeo.cms/src/org/argeo/cms/internal/osgi/DeployConfig.java index 4a88dd1b4..c31f50ded 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/osgi/DeployConfig.java @@ -1,4 +1,4 @@ -package org.argeo.cms.internal.kernel; +package org.argeo.cms.internal.osgi; import java.io.IOException; import java.io.InputStream; @@ -20,22 +20,25 @@ import javax.naming.ldap.Rdn; import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsLog; +import org.argeo.cms.internal.runtime.InitUtils; +import org.argeo.cms.internal.runtime.KernelConstants; +import org.argeo.cms.internal.runtime.KernelUtils; import org.argeo.osgi.useradmin.UserAdminConf; import org.argeo.util.naming.AttributesDictionary; import org.argeo.util.naming.LdifParser; import org.argeo.util.naming.LdifWriter; import org.eclipse.equinox.http.jetty.JettyConfigurator; -import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; import org.osgi.service.cm.Configuration; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.cm.ConfigurationEvent; import org.osgi.service.cm.ConfigurationListener; /** Manages the LDIF-based deployment configuration. */ -class DeployConfig implements ConfigurationListener { +public class DeployConfig implements ConfigurationListener { private final CmsLog log = CmsLog.getLog(getClass()); - private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); +// private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); private static Path deployConfigPath = KernelUtils.getOsgiInstancePath(KernelConstants.DEPLOY_CONFIG_PATH); private SortedMap deployConfigs = new TreeMap<>(); @@ -44,23 +47,23 @@ class DeployConfig implements ConfigurationListener { private boolean isFirstInit = false; private final static String ROLES = "roles"; - + private ConfigurationAdmin configurationAdmin; - public DeployConfig(ConfigurationAdmin configurationAdmin, boolean isClean) { + public DeployConfig() { // this.dataModels = dataModels; // ConfigurationAdmin configurationAdmin = - // bc.getService(bc.getServiceReference(ConfigurationAdmin.class)); - try { - if (!isInitialized()) { // first init - isFirstInit = true; - firstInit(); - } - this.configurationAdmin = configurationAdmin; - init(configurationAdmin, isClean, isFirstInit); - } catch (IOException e) { - throw new RuntimeException("Could not init deploy configs", e); - } +// // bc.getService(bc.getServiceReference(ConfigurationAdmin.class)); +// try { +// if (!isInitialized()) { // first init +// isFirstInit = true; +// firstInit(); +// } +// this.configurationAdmin = configurationAdmin; +//// init(configurationAdmin, isClean, isFirstInit); +// } catch (IOException e) { +// throw new RuntimeException("Could not init deploy configs", e); +// } // FIXME check race conditions during initialization // bc.registerService(ConfigurationListener.class, this, null); } @@ -175,7 +178,20 @@ class DeployConfig implements ConfigurationListener { } - private void init(ConfigurationAdmin configurationAdmin, boolean isClean, boolean isFirstInit) throws IOException { + public void init() throws IOException { + if (!isInitialized()) { // first init + isFirstInit = true; + firstInit(); + } + + boolean isClean; + try { + Configuration[] confs = configurationAdmin + .listConfigurations("(service.factoryPid=" + CmsConstants.NODE_USER_ADMIN_PID + ")"); + isClean = confs == null || confs.length == 0; + } catch (Exception e) { + throw new IllegalStateException("Cannot analyse clean state", e); + } try (InputStream in = Files.newInputStream(deployConfigPath)) { deployConfigs = new LdifParser().read(in); @@ -188,7 +204,11 @@ class DeployConfig implements ConfigurationListener { } // TODO check consistency if not clean } - + + public void destroy() { + + } + public void loadConfigs() throws IOException { // FIXME make it more robust Configuration systemRolesConf = null; @@ -235,14 +255,13 @@ class DeployConfig implements ConfigurationListener { if (systemRolesConf == null) throw new IllegalStateException("System roles are not configured."); systemRolesConf.update(new AttributesDictionary(deployConfigs.get(systemRolesDn))); - + } @Override public void configurationEvent(ConfigurationEvent event) { try { if (ConfigurationEvent.CM_UPDATED == event.getType()) { - ConfigurationAdmin configurationAdmin = bc.getService(event.getReference()); Configuration conf = configurationAdmin.getConfiguration(event.getPid(), null); LdapName serviceDn = null; String factoryPid = conf.getFactoryPid(); @@ -297,7 +316,7 @@ class DeployConfig implements ConfigurationListener { } } - void putFactoryDeployConfig(String factoryPid, Dictionary props) { + public void putFactoryDeployConfig(String factoryPid, Dictionary props) { Object cn = props.get(CmsConstants.CN); if (cn == null) throw new IllegalArgumentException("cn must be set in properties"); @@ -317,7 +336,7 @@ class DeployConfig implements ConfigurationListener { deployConfigs.put(serviceDn, attrs); } - void save() { + public void save() { try (Writer writer = Files.newBufferedWriter(deployConfigPath)) { new LdifWriter(writer).write(deployConfigs); } catch (IOException e) { @@ -326,6 +345,30 @@ class DeployConfig implements ConfigurationListener { } } + public void setConfigurationAdmin(ConfigurationAdmin configurationAdmin) { + this.configurationAdmin = configurationAdmin; + } + + public boolean hasDomain() { + Configuration[] configs; + try { + configs = configurationAdmin + .listConfigurations("(service.factoryPid=" + CmsConstants.NODE_USER_ADMIN_PID + ")"); + } catch (IOException | InvalidSyntaxException e) { + throw new IllegalStateException("Cannot list user directories", e); + } + + boolean hasDomain = false; + for (Configuration config : configs) { + Object realm = config.getProperties().get(UserAdminConf.realm.name()); + if (realm != null) { + log.debug("Found realm: " + realm); + hasDomain = true; + } + } + return hasDomain; + } + /* * UTILITIES */ @@ -353,7 +396,7 @@ class DeployConfig implements ConfigurationListener { } } -public Dictionary getProps(String factoryPid, String cn) { + public Dictionary getProps(String factoryPid, String cn) { Attributes attrs = deployConfigs.get(serviceDn(factoryPid, cn)); if (attrs != null) return new AttributesDictionary(attrs); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeLogger.java b/org.argeo.cms/src/org/argeo/cms/internal/osgi/NodeLogger.java similarity index 98% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeLogger.java rename to org.argeo.cms/src/org/argeo/cms/internal/osgi/NodeLogger.java index 0b4103794..69dbec9f7 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeLogger.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/osgi/NodeLogger.java @@ -1,4 +1,4 @@ -package org.argeo.cms.internal.kernel; +package org.argeo.cms.internal.osgi; import java.io.IOException; import java.net.URI; @@ -29,6 +29,8 @@ import org.argeo.cms.ArgeoLogListener; import org.argeo.cms.ArgeoLogger; import org.argeo.cms.CmsException; import org.argeo.cms.auth.CurrentUser; +import org.argeo.cms.internal.runtime.KernelConstants; +import org.argeo.cms.internal.runtime.KernelUtils; import org.argeo.osgi.useradmin.UserAdminConf; import org.osgi.framework.Bundle; import org.osgi.framework.Constants; @@ -40,7 +42,7 @@ import org.osgi.service.log.LogListener; import org.osgi.service.log.LogReaderService; /** Not meant to be used directly in standard log4j config */ -class NodeLogger implements ArgeoLogger, LogListener { +public class NodeLogger implements ArgeoLogger, LogListener { /** Internal debug for development purposes. */ private static Boolean debug = false; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java b/org.argeo.cms/src/org/argeo/cms/internal/osgi/NodeUserAdmin.java similarity index 79% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java rename to org.argeo.cms/src/org/argeo/cms/internal/osgi/NodeUserAdmin.java index 17daa3e14..d9524e897 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/osgi/NodeUserAdmin.java @@ -1,4 +1,4 @@ -package org.argeo.cms.internal.kernel; +package org.argeo.cms.internal.osgi; import java.io.IOException; import java.net.Inet6Address; @@ -34,10 +34,10 @@ import org.apache.commons.httpclient.params.HttpParams; import org.argeo.api.cms.CmsAuth; import org.argeo.api.cms.CmsConstants; import org.argeo.api.cms.CmsLog; -import org.argeo.cms.CmsUserManager; -import org.argeo.cms.internal.auth.CmsUserManagerImpl; import org.argeo.cms.internal.http.client.HttpCredentialProvider; import org.argeo.cms.internal.http.client.SpnegoAuthScheme; +import org.argeo.cms.internal.runtime.KernelConstants; +import org.argeo.cms.internal.runtime.KernelUtils; import org.argeo.osgi.transaction.WorkControl; import org.argeo.osgi.transaction.WorkTransaction; import org.argeo.osgi.useradmin.AbstractUserDirectory; @@ -53,22 +53,20 @@ import org.ietf.jgss.GSSException; import org.ietf.jgss.GSSManager; import org.ietf.jgss.GSSName; import org.ietf.jgss.Oid; -import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; -import org.osgi.framework.ServiceReference; import org.osgi.service.cm.ConfigurationException; import org.osgi.service.cm.ManagedServiceFactory; import org.osgi.service.useradmin.Authorization; +import org.osgi.service.useradmin.Group; +import org.osgi.service.useradmin.Role; import org.osgi.service.useradmin.UserAdmin; -import org.osgi.util.tracker.ServiceTracker; /** * Aggregates multiple {@link UserDirectory} and integrates them with system * roles. */ -class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactory, KernelConstants { +public class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactory, KernelConstants { private final static CmsLog log = CmsLog.getLog(NodeUserAdmin.class); -// private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); // OSGi private Map pidToBaseDn = new HashMap<>(); @@ -76,7 +74,7 @@ class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactor // private ServiceRegistration userAdminReg; // JTA - private final ServiceTracker tmTracker; +// private final ServiceTracker tmTracker; // private final String cacheName = UserDirectory.class.getName(); // GSS API @@ -86,29 +84,37 @@ class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactor private boolean singleUser = false; // private boolean systemRolesAvailable = false; - CmsUserManagerImpl userManager; +// CmsUserManagerImpl userManager; + private WorkControl transactionManager; + private WorkTransaction userTransaction; - public NodeUserAdmin(String systemRolesBaseDn, String tokensBaseDn) { - super(systemRolesBaseDn, tokensBaseDn); - BundleContext bc = Activator.getBundleContext(); - if (bc != null) { - tmTracker = new ServiceTracker<>(bc, WorkControl.class, null) { + public NodeUserAdmin() { + super(CmsConstants.ROLES_BASEDN, CmsConstants.TOKENS_BASEDN); +// BundleContext bc = Activator.getBundleContext(); +// if (bc != null) { +// tmTracker = new ServiceTracker<>(bc, WorkControl.class, null) { +// +// @Override +// public WorkControl addingService(ServiceReference reference) { +// WorkControl workControl = super.addingService(reference); +// userManager = new CmsUserManagerImpl(); +// userManager.setUserAdmin(NodeUserAdmin.this); +// // FIXME make it more robust +// userManager.setUserTransaction((WorkTransaction) workControl); +// bc.registerService(CmsUserManager.class, userManager, null); +// return workControl; +// } +// }; +// tmTracker.open(); +// } else { +// tmTracker = null; +// } + } - @Override - public WorkControl addingService(ServiceReference reference) { - WorkControl workControl = super.addingService(reference); - userManager = new CmsUserManagerImpl(); - userManager.setUserAdmin(NodeUserAdmin.this); - // FIXME make it more robust - userManager.setUserTransaction((WorkTransaction) workControl); - bc.registerService(CmsUserManager.class, userManager, null); - return workControl; - } - }; - tmTracker.open(); - } else { - tmTracker = null; - } + public void init() { + } + + public void destroy() { } @Override @@ -153,8 +159,8 @@ class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactor regProps.put(UserAdminConf.baseDn.name(), baseDn); // ServiceRegistration reg = // bc.registerService(UserDirectory.class, userDirectory, regProps); - Activator.registerService(UserDirectory.class, userDirectory, regProps); - userManager.addUserDirectory(userDirectory, regProps); + CmsActivator.getBundleContext().registerService(UserDirectory.class, userDirectory, regProps); +// userManager.addUserDirectory(userDirectory, regProps); pidToBaseDn.put(pid, baseDn); // pidToServiceRegs.put(pid, reg); @@ -164,11 +170,13 @@ class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactor } if (isSystemRolesBaseDn(baseDn)) { - // publishes only when system roles are available + addStandardSystemRoles(); + + // publishes itself as user admin only when system roles are available Dictionary userAdminregProps = new Hashtable<>(); userAdminregProps.put(CmsConstants.CN, CmsConstants.DEFAULT); userAdminregProps.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE); - Activator.registerService(UserAdmin.class, this, userAdminregProps); + CmsActivator.getBundleContext().registerService(UserAdmin.class, this, userAdminregProps); } // if (isSystemRolesBaseDn(baseDn)) @@ -188,6 +196,29 @@ class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactor // } } + private void addStandardSystemRoles() { + // we assume UserTransaction is already available (TODO make it more robust) + try { + userTransaction.begin(); + Role adminRole = getRole(CmsConstants.ROLE_ADMIN); + if (adminRole == null) { + adminRole = createRole(CmsConstants.ROLE_ADMIN, Role.GROUP); + } + if (getRole(CmsConstants.ROLE_USER_ADMIN) == null) { + Group userAdminRole = (Group) createRole(CmsConstants.ROLE_USER_ADMIN, Role.GROUP); + userAdminRole.addMember(adminRole); + } + userTransaction.commit(); + } catch (Exception e) { + try { + userTransaction.rollback(); + } catch (Exception e1) { + // silent + } + throw new IllegalStateException("Cannot add standard system roles", e); + } + } + @Override public void deleted(String pid) { // assert pidToServiceRegs.get(pid) != null; @@ -213,10 +244,10 @@ class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactor protected void postAdd(AbstractUserDirectory userDirectory) { // JTA - WorkControl tm = tmTracker != null ? tmTracker.getService() : null; - if (tm == null) - throw new IllegalStateException("A JTA transaction manager must be available."); - userDirectory.setTransactionControl(tm); +// WorkControl tm = tmTracker != null ? tmTracker.getService() : null; +// if (tm == null) +// throw new IllegalStateException("A JTA transaction manager must be available."); + userDirectory.setTransactionControl(transactionManager); // if (tmTracker.getService() instanceof BitronixTransactionManager) // EhCacheXAResourceProducer.registerXAResource(cacheName, userDirectory.getXaResource()); @@ -333,10 +364,26 @@ class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactor return acceptorCredentials; } + public boolean hasAcceptorCredentials() { + return acceptorCredentials != null; + } + public boolean isSingleUser() { return singleUser; } + public void setTransactionManager(WorkControl transactionManager) { + this.transactionManager = transactionManager; + } + + public void setUserTransaction(WorkTransaction userTransaction) { + this.userTransaction = userTransaction; + } + + /* + * STATIC + */ + public final static Oid KERBEROS_OID; static { try { @@ -345,5 +392,4 @@ class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactor throw new IllegalStateException("Cannot create Kerberos OID", e); } } - } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/SecurityProfile.java b/org.argeo.cms/src/org/argeo/cms/internal/osgi/SecurityProfile.java similarity index 99% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/SecurityProfile.java rename to org.argeo.cms/src/org/argeo/cms/internal/osgi/SecurityProfile.java index 34ec9bcba..7055538c3 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/SecurityProfile.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/osgi/SecurityProfile.java @@ -1,4 +1,4 @@ -package org.argeo.cms.internal.kernel; +package org.argeo.cms.internal.osgi; import java.io.FilePermission; import java.lang.reflect.ReflectPermission; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/.gitignore b/org.argeo.cms/src/org/argeo/cms/internal/runtime/.gitignore similarity index 100% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/.gitignore rename to org.argeo.cms/src/org/argeo/cms/internal/runtime/.gitignore diff --git a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java new file mode 100644 index 000000000..7ce2e8bd5 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsContextImpl.java @@ -0,0 +1,201 @@ +package org.argeo.cms.internal.runtime; + +import static java.util.Locale.ENGLISH; + +import java.lang.management.ManagementFactory; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import org.argeo.api.cms.CmsConstants; +import org.argeo.api.cms.CmsContext; +import org.argeo.api.cms.CmsDeployment; +import org.argeo.api.cms.CmsLog; +import org.argeo.api.cms.CmsState; +import org.argeo.cms.LocaleUtils; +import org.argeo.cms.internal.osgi.NodeUserAdmin; +import org.ietf.jgss.GSSCredential; +import org.osgi.service.useradmin.UserAdmin; + +public class CmsContextImpl implements CmsContext { + private final CmsLog log = CmsLog.getLog(getClass()); +// private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); + +// private EgoRepository egoRepository; + private static CompletableFuture instance = new CompletableFuture(); + + private CmsState cmsState; + private CmsDeployment cmsDeployment; + private UserAdmin userAdmin; + + // i18n + private Locale defaultLocale; + private List locales = null; + + private Long availableSince; + +// public CmsContextImpl() { +// initTrackers(); +// } + + public void init() { + Object defaultLocaleValue = KernelUtils.getFrameworkProp(CmsConstants.I18N_DEFAULT_LOCALE); + defaultLocale = defaultLocaleValue != null ? new Locale(defaultLocaleValue.toString()) + : new Locale(ENGLISH.getLanguage()); + locales = LocaleUtils.asLocaleList(KernelUtils.getFrameworkProp(CmsConstants.I18N_LOCALES)); + // node repository +// new ServiceTracker(bc, Repository.class, null) { +// @Override +// public Repository addingService(ServiceReference reference) { +// Object cn = reference.getProperty(NodeConstants.CN); +// if (cn != null && cn.equals(NodeConstants.EGO_REPOSITORY)) { +//// egoRepository = (EgoRepository) bc.getService(reference); +// if (log.isTraceEnabled()) +// log.trace("Home repository is available"); +// } +// return super.addingService(reference); +// } +// +// @Override +// public void removedService(ServiceReference reference, Repository service) { +// super.removedService(reference, service); +//// egoRepository = null; +// } +// +// }.open(); + + checkReadiness(); + + setInstance(this); + } + + public void destroy() { + setInstance(null); + } + + /** + * Checks whether the deployment is available according to expectations, and + * mark it as available. + */ + private void checkReadiness() { + if (isAvailable()) + return; + if (cmsDeployment != null && userAdmin != null) { + String data = KernelUtils.getFrameworkProp(KernelUtils.OSGI_INSTANCE_AREA); + String state = KernelUtils.getFrameworkProp(KernelUtils.OSGI_CONFIGURATION_AREA); + availableSince = System.currentTimeMillis(); + long jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime(); + String jvmUptimeStr = " in " + (jvmUptime / 1000) + "." + (jvmUptime % 1000) + "s"; + log.info("## ARGEO CMS AVAILABLE" + (log.isDebugEnabled() ? jvmUptimeStr : "") + " ##"); + if (log.isDebugEnabled()) { + log.debug("## state: " + state); + if (data != null) + log.debug("## data: " + data); + } + long begin = cmsState.getAvailableSince(); + long initDuration = System.currentTimeMillis() - begin; + if (log.isTraceEnabled()) + log.trace("Kernel initialization took " + initDuration + "ms"); + tributeToFreeSoftware(initDuration); + } else { + throw new IllegalStateException("Deployment is not available"); + } + } + + final private void tributeToFreeSoftware(long initDuration) { + if (log.isTraceEnabled()) { + long ms = initDuration / 100; + log.trace("Spend " + ms + "ms" + " reflecting on the progress brought to mankind" + " by Free Software..."); + long beginNano = System.nanoTime(); + try { + Thread.sleep(ms, 0); + } catch (InterruptedException e) { + // silent + } + long durationNano = System.nanoTime() - beginNano; + final double M = 1000d * 1000d; + double sleepAccuracy = ((double) durationNano) / (ms * M); + log.trace("Sleep accuracy: " + String.format("%.2f", 100 - (sleepAccuracy * 100 - 100)) + " %"); + } + } + + @Override + public void createWorkgroup(String dn) { +// if (egoRepository == null) +// throw new CmsException("Ego repository is not available"); +// // TODO add check that the group exists +// egoRepository.createWorkgroup(dn); + throw new UnsupportedOperationException(); + } + + public void setCmsDeployment(CmsDeployment cmsDeployment) { + this.cmsDeployment = cmsDeployment; + } + + public void setCmsState(CmsState cmsState) { + this.cmsState = cmsState; + } + + public void setUserAdmin(UserAdmin userAdmin) { + this.userAdmin = userAdmin; + } + + @Override + public Locale getDefaultLocale() { + return defaultLocale; + } + + @Override + public List getLocales() { + return locales; + } + + @Override + public synchronized Long getAvailableSince() { + return availableSince; + } + + public synchronized boolean isAvailable() { + return availableSince != null; + } + + /* + * STATIC + */ + + public synchronized static CmsContext getCmsContext() { + return getInstance(); + } + + /** Required by USER login module. */ + public synchronized static UserAdmin getUserAdmin() { + return getInstance().userAdmin; + } + + /** Required by SPNEGO login module. */ + @Deprecated + public synchronized static GSSCredential getAcceptorCredentials() { + // FIXME find a cleaner way + return ((NodeUserAdmin) getInstance().userAdmin).getAcceptorCredentials(); + } + + private synchronized static void setInstance(CmsContextImpl cmsContextImpl) { + if (cmsContextImpl != null) { + if (instance.isDone()) + throw new IllegalStateException("CMS Context is already set"); + instance.complete(cmsContextImpl); + } else { + instance = new CompletableFuture(); + } + } + + private synchronized static CmsContextImpl getInstance() { + try { + return instance.get(); + } catch (InterruptedException | ExecutionException e) { + throw new IllegalStateException("Cannot retrieve CMS Context", e); + } + } + +} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java new file mode 100644 index 000000000..83f688a6a --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsDeploymentImpl.java @@ -0,0 +1,207 @@ +package org.argeo.cms.internal.runtime; + +import java.io.IOException; +import java.net.URL; +import java.util.Dictionary; + +import org.argeo.api.cms.CmsDeployment; +import org.argeo.api.cms.CmsLog; +import org.argeo.api.cms.CmsState; +import org.argeo.cms.internal.osgi.DeployConfig; +import org.eclipse.equinox.http.jetty.JettyConfigurator; +import org.osgi.service.http.HttpService; + +/** Implementation of a CMS deployment. */ +public class CmsDeploymentImpl implements CmsDeployment { + private final CmsLog log = CmsLog.getLog(getClass()); +// private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); + +// private Long availableSince; + + // Readiness +// private boolean nodeAvailable = false; +// private boolean userAdminAvailable = false; + private boolean httpExpected = false; +// private boolean httpAvailable = false; + private HttpService httpService; + + private CmsState cmsState; + private DeployConfig deployConfig; + + public CmsDeploymentImpl() { +// ServiceReference nodeStateSr = bc.getServiceReference(NodeState.class); +// if (nodeStateSr == null) +// throw new CmsException("No node state available"); + +// NodeState nodeState = bc.getService(nodeStateSr); +// cleanState = nodeState.isClean(); + +// nodeHttp = new NodeHttp(); + initTrackers(); + } + + private void initTrackers() { +// ServiceTracker httpSt = new ServiceTracker(bc, HttpService.class, null) { +// +// @Override +// public HttpService addingService(ServiceReference sr) { +// httpAvailable = true; +// Object httpPort = sr.getProperty("http.port"); +// Object httpsPort = sr.getProperty("https.port"); +// log.info(httpPortsMsg(httpPort, httpsPort)); +// checkReadiness(); +// return super.addingService(sr); +// } +// }; +// // httpSt.open(); +// KernelUtils.asyncOpen(httpSt); + +// ServiceTracker userAdminSt = new ServiceTracker(bc, UserAdmin.class, null) { +// @Override +// public UserAdmin addingService(ServiceReference reference) { +// UserAdmin userAdmin = super.addingService(reference); +// addStandardSystemRoles(userAdmin); +// userAdminAvailable = true; +// checkReadiness(); +// return userAdmin; +// } +// }; +// // userAdminSt.open(); +// KernelUtils.asyncOpen(userAdminSt); + +// ServiceTracker confAdminSt = new ServiceTracker(bc, +// ConfigurationAdmin.class, null) { +// @Override +// public ConfigurationAdmin addingService(ServiceReference reference) { +// ConfigurationAdmin configurationAdmin = bc.getService(reference); +//// boolean isClean; +//// try { +//// Configuration[] confs = configurationAdmin +//// .listConfigurations("(service.factoryPid=" + CmsConstants.NODE_USER_ADMIN_PID + ")"); +//// isClean = confs == null || confs.length == 0; +//// } catch (Exception e) { +//// throw new IllegalStateException("Cannot analyse clean state", e); +//// } +// deployConfig = new DeployConfig(configurationAdmin, isClean); +// Activator.registerService(CmsDeployment.class, CmsDeploymentImpl.this, null); +//// JcrInitUtils.addToDeployment(CmsDeployment.this); +// httpExpected = deployConfig.getProps(KernelConstants.JETTY_FACTORY_PID, "default") != null; +// try { +// Configuration[] configs = configurationAdmin +// .listConfigurations("(service.factoryPid=" + CmsConstants.NODE_USER_ADMIN_PID + ")"); +// +// boolean hasDomain = false; +// for (Configuration config : configs) { +// Object realm = config.getProperties().get(UserAdminConf.realm.name()); +// if (realm != null) { +// log.debug("Found realm: " + realm); +// hasDomain = true; +// } +// } +// if (hasDomain) { +// loadIpaJaasConfiguration(); +// } +// } catch (Exception e) { +// throw new IllegalStateException("Cannot initialize config", e); +// } +// return super.addingService(reference); +// } +// }; +// // confAdminSt.open(); +// KernelUtils.asyncOpen(confAdminSt); + } + + public void init() { + httpExpected = deployConfig.getProps(KernelConstants.JETTY_FACTORY_PID, "default") != null; + if (deployConfig.hasDomain()) { + loadIpaJaasConfiguration(); + } + +// while (!isHttpAvailableOrNotExpected()) { +// try { +// Thread.sleep(100); +// } catch (InterruptedException e) { +// log.error("Interrupted while waiting for http"); +// } +// } + } + + public void addFactoryDeployConfig(String factoryPid, Dictionary props) { + deployConfig.putFactoryDeployConfig(factoryPid, props); + deployConfig.save(); + try { + deployConfig.loadConfigs(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + public Dictionary getProps(String factoryPid, String cn) { + return deployConfig.getProps(factoryPid, cn); + } + +// private void addStandardSystemRoles(UserAdmin userAdmin) { +// // we assume UserTransaction is already available (TODO make it more robust) +// WorkTransaction userTransaction = bc.getService(bc.getServiceReference(WorkTransaction.class)); +// try { +// userTransaction.begin(); +// Role adminRole = userAdmin.getRole(CmsConstants.ROLE_ADMIN); +// if (adminRole == null) { +// adminRole = userAdmin.createRole(CmsConstants.ROLE_ADMIN, Role.GROUP); +// } +// if (userAdmin.getRole(CmsConstants.ROLE_USER_ADMIN) == null) { +// Group userAdminRole = (Group) userAdmin.createRole(CmsConstants.ROLE_USER_ADMIN, Role.GROUP); +// userAdminRole.addMember(adminRole); +// } +// userTransaction.commit(); +// } catch (Exception e) { +// try { +// userTransaction.rollback(); +// } catch (Exception e1) { +// // silent +// } +// throw new IllegalStateException("Cannot add standard system roles", e); +// } +// } + + public boolean isHttpAvailableOrNotExpected() { + return (httpExpected ? httpService != null : true); + } + + private void loadIpaJaasConfiguration() { + if (System.getProperty(KernelConstants.JAAS_CONFIG_PROP) == null) { + String jaasConfig = KernelConstants.JAAS_CONFIG_IPA; + URL url = getClass().getClassLoader().getResource(jaasConfig); + KernelUtils.setJaasConfiguration(url); + log.debug("Set IPA JAAS configuration."); + } + } + + public void destroy() { +// if (nodeHttp != null) +// nodeHttp.destroy(); + + try { + JettyConfigurator.stopServer(KernelConstants.DEFAULT_JETTY_SERVER); + } catch (Exception e) { + log.error("Cannot stop default Jetty server.", e); + } + + if (deployConfig != null) { + new Thread(() -> deployConfig.save(), "Save Argeo Deploy Config").start(); + } + } + + public void setDeployConfig(DeployConfig deployConfig) { + this.deployConfig = deployConfig; + } + + public void setCmsState(CmsState cmsState) { + this.cmsState = cmsState; + } + + public void setHttpService(HttpService httpService) { + this.httpService = httpService; + } + +} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsStateImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsStateImpl.java similarity index 61% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsStateImpl.java rename to org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsStateImpl.java index 6bc8ac888..7b47b520d 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsStateImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/CmsStateImpl.java @@ -1,23 +1,18 @@ -package org.argeo.cms.internal.kernel; - -import static java.util.Locale.ENGLISH; +package org.argeo.cms.internal.runtime; import java.net.InetAddress; +import java.net.URL; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; -import java.util.Locale; -import org.argeo.api.cms.CmsState; +import javax.security.auth.login.Configuration; + import org.argeo.api.cms.CmsLog; -import org.argeo.api.cms.CmsConstants; -import org.argeo.cms.LocaleUtils; -import org.argeo.osgi.transaction.SimpleTransactionManager; -import org.argeo.osgi.transaction.WorkControl; -import org.argeo.osgi.transaction.WorkTransaction; -import org.argeo.util.LangUtils; +import org.argeo.api.cms.CmsState; +import org.argeo.cms.auth.ident.IdentClient; +import org.argeo.cms.internal.osgi.CmsShutdown; import org.osgi.framework.Constants; -import org.osgi.service.cm.ManagedServiceFactory; /** * Implementation of a {@link CmsState}, initialising the required services. @@ -26,22 +21,38 @@ public class CmsStateImpl implements CmsState { private final static CmsLog log = CmsLog.getLog(CmsStateImpl.class); // private final BundleContext bc = FrameworkUtil.getBundle(CmsState.class).getBundleContext(); +// private static CmsStateImpl instance; + +// private ExecutorService internalExecutorService; + // REFERENCES private Long availableSince; - // i18n - private Locale defaultLocale; - private List locales = null; - private ThreadGroup threadGroup = new ThreadGroup("CMS"); +// private ThreadGroup threadGroup = new ThreadGroup("CMS"); private List stopHooks = new ArrayList<>(); - private final String stateUuid; + private String stateUuid; // private final boolean cleanState; private String hostname; - public CmsStateImpl() { -// this.stateUuid = stateUuid; + public void init() { +// instance = this; + + Runtime.getRuntime().addShutdownHook(new CmsShutdown()); +// this.internalExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); + + try { + initSecurity(); +// initArgeoLogger(); +// initNode(); + + if (log.isTraceEnabled()) + log.trace("CMS State started"); + } catch (Throwable e) { + log.error("## FATAL: CMS activator failed", e); + } + this.stateUuid = KernelUtils.getFrameworkProp(Constants.FRAMEWORK_UUID); // this.cleanState = stateUuid.equals(frameworkUuid); try { @@ -56,31 +67,43 @@ public class CmsStateImpl implements CmsState { // (clean state) " : " ")); log.debug("## CMS starting... (" + stateUuid + ")"); - initI18n(); - initServices(); +// initI18n(); +// initServices(); } - private void initI18n() { - Object defaultLocaleValue = KernelUtils.getFrameworkProp(CmsConstants.I18N_DEFAULT_LOCALE); - defaultLocale = defaultLocaleValue != null ? new Locale(defaultLocaleValue.toString()) - : new Locale(ENGLISH.getLanguage()); - locales = LocaleUtils.asLocaleList(KernelUtils.getFrameworkProp(CmsConstants.I18N_LOCALES)); + private void initSecurity() { + if (System.getProperty(KernelConstants.JAAS_CONFIG_PROP) == null) { + String jaasConfig = KernelConstants.JAAS_CONFIG; + URL url = getClass().getResource(jaasConfig); + // System.setProperty(KernelConstants.JAAS_CONFIG_PROP, + // url.toExternalForm()); + KernelUtils.setJaasConfiguration(url); + } + // explicitly load JAAS configuration + Configuration.getConfiguration(); } +// private void initI18n() { +// Object defaultLocaleValue = KernelUtils.getFrameworkProp(CmsConstants.I18N_DEFAULT_LOCALE); +// defaultLocale = defaultLocaleValue != null ? new Locale(defaultLocaleValue.toString()) +// : new Locale(ENGLISH.getLanguage()); +// locales = LocaleUtils.asLocaleList(KernelUtils.getFrameworkProp(CmsConstants.I18N_LOCALES)); +// } + private void initServices() { // JTA - String tmType = KernelUtils.getFrameworkProp(CmsConstants.TRANSACTION_MANAGER, - CmsConstants.TRANSACTION_MANAGER_SIMPLE); - if (CmsConstants.TRANSACTION_MANAGER_SIMPLE.equals(tmType)) { - initSimpleTransactionManager(); - } else if (CmsConstants.TRANSACTION_MANAGER_BITRONIX.equals(tmType)) { -// initBitronixTransactionManager(); - throw new UnsupportedOperationException( - "Bitronix is not supported anymore, but could be again if there is enough interest."); - } else { - throw new IllegalArgumentException("Usupported transaction manager type " + tmType); - } +// String tmType = KernelUtils.getFrameworkProp(CmsConstants.TRANSACTION_MANAGER, +// CmsConstants.TRANSACTION_MANAGER_SIMPLE); +// if (CmsConstants.TRANSACTION_MANAGER_SIMPLE.equals(tmType)) { +// initSimpleTransactionManager(); +// } else if (CmsConstants.TRANSACTION_MANAGER_BITRONIX.equals(tmType)) { +//// initBitronixTransactionManager(); +// throw new UnsupportedOperationException( +// "Bitronix is not supported anymore, but could be again if there is enough interest."); +// } else { +// throw new IllegalArgumentException("Usupported transaction manager type " + tmType); +// } // POI // POIXMLTypeLoader.setClassLoader(CTConnection.class.getClassLoader()); @@ -106,21 +129,21 @@ public class CmsStateImpl implements CmsState { // Activator.registerService(RepositoryFactory.class, repositoryFactory, null); // Security - NodeUserAdmin userAdmin = new NodeUserAdmin(CmsConstants.ROLES_BASEDN, CmsConstants.TOKENS_BASEDN); - stopHooks.add(() -> userAdmin.destroy()); - Activator.registerService(ManagedServiceFactory.class, userAdmin, - LangUtils.dict(Constants.SERVICE_PID, CmsConstants.NODE_USER_ADMIN_PID)); +// NodeUserAdmin userAdmin = new NodeUserAdmin(CmsConstants.ROLES_BASEDN, CmsConstants.TOKENS_BASEDN); +// stopHooks.add(() -> userAdmin.destroy()); +// Activator.registerService(ManagedServiceFactory.class, userAdmin, +// LangUtils.dict(Constants.SERVICE_PID, CmsConstants.NODE_USER_ADMIN_PID)); } - private void initSimpleTransactionManager() { - SimpleTransactionManager transactionManager = new SimpleTransactionManager(); - Activator.registerService(WorkControl.class, transactionManager, null); - Activator.registerService(WorkTransaction.class, transactionManager, null); -// Activator.registerService(TransactionManager.class, transactionManager, null); -// Activator.registerService(UserTransaction.class, transactionManager, null); - // TODO TransactionSynchronizationRegistry - } +// private void initSimpleTransactionManager() { +// SimpleTransactionManager transactionManager = new SimpleTransactionManager(); +// Activator.registerService(WorkControl.class, transactionManager, null); +// Activator.registerService(WorkTransaction.class, transactionManager, null); +//// Activator.registerService(TransactionManager.class, transactionManager, null); +//// Activator.registerService(UserTransaction.class, transactionManager, null); +// // TODO TransactionSynchronizationRegistry +// } // private void initBitronixTransactionManager() { // // TODO manage it in a managed service, as startup could be long @@ -155,7 +178,7 @@ public class CmsStateImpl implements CmsState { // log.debug("Initialised default Bitronix transaction manager"); // } - void shutdown() { + public void destroy() { if (log.isDebugEnabled()) log.debug("CMS stopping... (" + this.stateUuid + ")"); @@ -168,6 +191,8 @@ public class CmsStateImpl implements CmsState { // silent } +// internalExecutorService.shutdown(); + long duration = ((System.currentTimeMillis() - availableSince) / 1000) / 60; log.info("## ARGEO CMS STOPPED after " + (duration / 60) + "h " + (duration % 60) + "min uptime ##"); } @@ -183,6 +208,8 @@ public class CmsStateImpl implements CmsState { } // Clean hanging Gogo shell thread new GogoShellKiller().start(); + +// instance = null; } // @Override @@ -198,15 +225,17 @@ public class CmsStateImpl implements CmsState { /* * ACCESSORS */ - public Locale getDefaultLocale() { - return defaultLocale; - } - - public List getLocales() { - return locales; - } - public String getHostname() { return hostname; } + + /* + * STATIC + */ + public static IdentClient getIdentClient(String remoteAddr) { + if (!IdentClient.isDefaultAuthdPassphraseFileAvailable()) + return null; + // TODO make passphrase more configurable + return new IdentClient(remoteAddr); + } } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/GogoShellKiller.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/GogoShellKiller.java similarity index 97% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/GogoShellKiller.java rename to org.argeo.cms/src/org/argeo/cms/internal/runtime/GogoShellKiller.java index 39b11a531..56df43a8a 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/GogoShellKiller.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/GogoShellKiller.java @@ -1,4 +1,4 @@ -package org.argeo.cms.internal.kernel; +package org.argeo.cms.internal.runtime; /** * Workaround for killing Gogo shell by system shutdown. diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/InitUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/InitUtils.java similarity index 96% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/InitUtils.java rename to org.argeo.cms/src/org/argeo/cms/internal/runtime/InitUtils.java index a2006a704..70ea9ec48 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/InitUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/InitUtils.java @@ -1,6 +1,6 @@ -package org.argeo.cms.internal.kernel; +package org.argeo.cms.internal.runtime; -import static org.argeo.cms.internal.kernel.KernelUtils.getFrameworkProp; +import static org.argeo.cms.internal.runtime.KernelUtils.getFrameworkProp; import java.io.File; import java.io.FileFilter; @@ -30,12 +30,11 @@ import org.argeo.osgi.useradmin.UserAdminConf; * Interprets framework properties in order to generate the initial deploy * configuration. */ -class InitUtils { +public class InitUtils { private final static CmsLog log = CmsLog.getLog(InitUtils.class); - /** Override the provided config with the framework properties */ - static Dictionary getHttpServerConfig(Dictionary provided) { + public static Dictionary getHttpServerConfig(Dictionary provided) { String httpPort = getFrameworkProp("org.osgi.service.http.port"); String httpsPort = getFrameworkProp("org.osgi.service.http.port.secure"); /// TODO make it more generic @@ -122,7 +121,7 @@ class InitUtils { return props; } - static List> getUserDirectoryConfigs() { + public static List> getUserDirectoryConfigs() { List> res = new ArrayList<>(); File nodeBaseDir = KernelUtils.getOsgiInstancePath(KernelConstants.DIR_NODE).toFile(); List uris = new ArrayList<>(); @@ -218,7 +217,7 @@ class InitUtils { * Called before node initialisation, in order populate OSGi instance are with * some files (typically LDIF, etc). */ - static void prepareFirstInitInstanceArea() { + public static void prepareFirstInitInstanceArea() { String nodeInits = getFrameworkProp(CmsConstants.NODE_INIT); if (nodeInits == null) nodeInits = "../../init"; @@ -227,7 +226,7 @@ class InitUtils { if (nodeInit.startsWith("http")) { // TODO reconnect it - //registerRemoteInit(nodeInit); + // registerRemoteInit(nodeInit); } else { // TODO use java.nio.file diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/KernelConstants.java similarity index 97% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java rename to org.argeo.cms/src/org/argeo/cms/internal/runtime/KernelConstants.java index 90f2382d7..7c397de6c 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/KernelConstants.java @@ -1,4 +1,4 @@ -package org.argeo.cms.internal.kernel; +package org.argeo.cms.internal.runtime; import org.argeo.api.cms.CmsConstants; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/KernelUtils.java similarity index 83% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java rename to org.argeo.cms/src/org/argeo/cms/internal/runtime/KernelUtils.java index f267933cf..afcb9ff26 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/KernelUtils.java @@ -1,4 +1,4 @@ -package org.argeo.cms.internal.kernel; +package org.argeo.cms.internal.runtime; import java.io.File; import java.io.IOException; @@ -16,12 +16,10 @@ import java.util.TreeMap; import java.util.TreeSet; import org.argeo.api.cms.CmsLog; -import org.argeo.cms.osgi.DataModelNamespace; -import org.osgi.framework.BundleContext; -import org.osgi.util.tracker.ServiceTracker; +import org.argeo.cms.internal.osgi.CmsActivator; /** Package utilities */ -class KernelUtils implements KernelConstants { +public class KernelUtils implements KernelConstants { final static String OSGI_INSTANCE_AREA = "osgi.instance.area"; final static String OSGI_CONFIGURATION_AREA = "osgi.configuration.area"; @@ -66,15 +64,15 @@ class KernelUtils implements KernelConstants { } static File getOsgiInstanceDir() { - return new File(getBundleContext().getProperty(OSGI_INSTANCE_AREA).substring("file:".length())) + return new File(CmsActivator.getBundleContext().getProperty(OSGI_INSTANCE_AREA).substring("file:".length())) .getAbsoluteFile(); } - static Path getOsgiInstancePath(String relativePath) { + public static Path getOsgiInstancePath(String relativePath) { return Paths.get(getOsgiInstanceUri(relativePath)); } - static URI getOsgiInstanceUri(String relativePath) { + public static URI getOsgiInstanceUri(String relativePath) { String osgiInstanceBaseUri = getFrameworkProp(OSGI_INSTANCE_AREA); if (osgiInstanceBaseUri != null) return safeUri(osgiInstanceBaseUri + (relativePath != null ? relativePath : "")); @@ -84,7 +82,7 @@ class KernelUtils implements KernelConstants { static File getOsgiConfigurationFile(String relativePath) { try { - return new File(new URI(getBundleContext().getProperty(OSGI_CONFIGURATION_AREA) + relativePath)) + return new File(new URI(CmsActivator.getBundleContext().getProperty(OSGI_CONFIGURATION_AREA) + relativePath)) .getCanonicalFile(); } catch (Exception e) { throw new IllegalArgumentException("Cannot get configuration file for " + relativePath, e); @@ -92,10 +90,9 @@ class KernelUtils implements KernelConstants { } static String getFrameworkProp(String key, String def) { - BundleContext bundleContext = Activator.getBundleContext(); String value; - if (bundleContext != null) - value = bundleContext.getProperty(key); + if (CmsActivator.getBundleContext() != null) + value = CmsActivator.getBundleContext().getProperty(key); else value = System.getProperty(key); if (value == null) @@ -103,7 +100,7 @@ class KernelUtils implements KernelConstants { return value; } - static String getFrameworkProp(String key) { + public static String getFrameworkProp(String key) { return getFrameworkProp(key, null); } @@ -121,9 +118,8 @@ class KernelUtils implements KernelConstants { // } static void logFrameworkProperties(CmsLog log) { - BundleContext bc = getBundleContext(); for (Object sysProp : new TreeSet(System.getProperties().keySet())) { - log.debug(sysProp + "=" + bc.getProperty(sysProp.toString())); + log.debug(sysProp + "=" + getFrameworkProp(sysProp.toString())); } // String[] keys = { Constants.FRAMEWORK_STORAGE, // Constants.FRAMEWORK_OS_NAME, Constants.FRAMEWORK_OS_VERSION, @@ -206,21 +202,21 @@ class KernelUtils implements KernelConstants { // }); // } - static void asyncOpen(ServiceTracker st) { - Runnable run = new Runnable() { - - @Override - public void run() { - st.open(); - } - }; - Activator.getInternalExecutorService().execute(run); -// new Thread(run, "Open service tracker " + st).start(); - } +// public static void asyncOpen(ServiceTracker st) { +// Runnable run = new Runnable() { +// +// @Override +// public void run() { +// st.open(); +// } +// }; +// Activator.getInternalExecutorService().execute(run); +//// new Thread(run, "Open service tracker " + st).start(); +// } - static BundleContext getBundleContext() { - return Activator.getBundleContext(); - } +// static BundleContext getBundleContext() { +// return Activator.getBundleContext(); +// } static boolean asBoolean(String value) { if (value == null) @@ -231,8 +227,7 @@ class KernelUtils implements KernelConstants { case "false": return false; default: - throw new IllegalArgumentException( - "Unsupported value for attribute " + DataModelNamespace.ABSTRACT + ": " + value); + throw new IllegalArgumentException("Unsupported value for boolean attribute : " + value); } } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/PkiUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/runtime/PkiUtils.java similarity index 99% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/PkiUtils.java rename to org.argeo.cms/src/org/argeo/cms/internal/runtime/PkiUtils.java index 2105e05d0..474a89950 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/PkiUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/runtime/PkiUtils.java @@ -1,4 +1,4 @@ -package org.argeo.cms.internal.kernel; +package org.argeo.cms.internal.runtime; import java.io.IOException; import java.io.InputStream; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/dc=example,dc=com.ldif b/org.argeo.cms/src/org/argeo/cms/internal/runtime/dc=example,dc=com.ldif similarity index 100% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/dc=example,dc=com.ldif rename to org.argeo.cms/src/org/argeo/cms/internal/runtime/dc=example,dc=com.ldif diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/example-ou=roles,ou=node.ldif b/org.argeo.cms/src/org/argeo/cms/internal/runtime/example-ou=roles,ou=node.ldif similarity index 100% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/example-ou=roles,ou=node.ldif rename to org.argeo.cms/src/org/argeo/cms/internal/runtime/example-ou=roles,ou=node.ldif diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg b/org.argeo.cms/src/org/argeo/cms/internal/runtime/jaas-ipa.cfg similarity index 100% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg rename to org.argeo.cms/src/org/argeo/cms/internal/runtime/jaas-ipa.cfg diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg b/org.argeo.cms/src/org/argeo/cms/internal/runtime/jaas.cfg similarity index 100% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg rename to org.argeo.cms/src/org/argeo/cms/internal/runtime/jaas.cfg diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/ou=roles,ou=node.ldif b/org.argeo.cms/src/org/argeo/cms/internal/runtime/ou=roles,ou=node.ldif similarity index 100% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/ou=roles,ou=node.ldif rename to org.argeo.cms/src/org/argeo/cms/internal/runtime/ou=roles,ou=node.ldif diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/ou=tokens,ou=node.ldif b/org.argeo.cms/src/org/argeo/cms/internal/runtime/ou=tokens,ou=node.ldif similarity index 100% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/ou=tokens,ou=node.ldif rename to org.argeo.cms/src/org/argeo/cms/internal/runtime/ou=tokens,ou=node.ldif diff --git a/org.argeo.util/src/org/argeo/osgi/useradmin/AggregatingUserAdmin.java b/org.argeo.util/src/org/argeo/osgi/useradmin/AggregatingUserAdmin.java index bee513546..c274ed97e 100644 --- a/org.argeo.util/src/org/argeo/osgi/useradmin/AggregatingUserAdmin.java +++ b/org.argeo.util/src/org/argeo/osgi/useradmin/AggregatingUserAdmin.java @@ -31,6 +31,7 @@ public class AggregatingUserAdmin implements UserAdmin { private AbstractUserDirectory tokens = null; private Map businessRoles = new HashMap(); + // TODO rather use an empty constructor and an init method public AggregatingUserAdmin(String systemRolesBaseDn, String tokensBaseDn) { try { this.systemRolesBaseDn = new LdapName(systemRolesBaseDn); -- 2.30.2