]> git.argeo.org Git - lgpl/argeo-commons.git/blob - runtime/CmsContextImpl.java
Prepare next development cycle
[lgpl/argeo-commons.git] / runtime / CmsContextImpl.java
1 package org.argeo.cms.internal.runtime;
2
3 import static java.util.Locale.ENGLISH;
4
5 import java.lang.management.ManagementFactory;
6 import java.util.HashMap;
7 import java.util.List;
8 import java.util.Locale;
9 import java.util.Map;
10 import java.util.UUID;
11 import java.util.concurrent.CompletableFuture;
12 import java.util.concurrent.ExecutionException;
13
14 import javax.security.auth.Subject;
15
16 import org.argeo.api.cms.CmsConstants;
17 import org.argeo.api.cms.CmsContext;
18 import org.argeo.api.cms.CmsDeployment;
19 import org.argeo.api.cms.CmsLog;
20 import org.argeo.api.cms.CmsSession;
21 import org.argeo.api.cms.CmsSessionId;
22 import org.argeo.api.cms.CmsState;
23 import org.argeo.cms.LocaleUtils;
24 import org.argeo.cms.internal.auth.CmsSessionImpl;
25 import org.ietf.jgss.GSSCredential;
26 import org.osgi.service.useradmin.UserAdmin;
27
28 public class CmsContextImpl implements CmsContext {
29 private final CmsLog log = CmsLog.getLog(getClass());
30 // private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext();
31
32 // private EgoRepository egoRepository;
33 private static CompletableFuture<CmsContextImpl> instance = new CompletableFuture<CmsContextImpl>();
34
35 private CmsState cmsState;
36 private CmsDeployment cmsDeployment;
37 private UserAdmin userAdmin;
38
39 // i18n
40 private Locale defaultLocale;
41 private List<Locale> locales = null;
42
43 private Long availableSince;
44
45 // CMS sessions
46 private Map<UUID, CmsSessionImpl> cmsSessionsByUuid = new HashMap<>();
47 private Map<String, CmsSessionImpl> cmsSessionsByLocalId = new HashMap<>();
48
49 // public CmsContextImpl() {
50 // initTrackers();
51 // }
52
53 public void start() {
54 Object defaultLocaleValue = KernelUtils.getFrameworkProp(CmsConstants.I18N_DEFAULT_LOCALE);
55 defaultLocale = defaultLocaleValue != null ? new Locale(defaultLocaleValue.toString())
56 : new Locale(ENGLISH.getLanguage());
57 locales = LocaleUtils.asLocaleList(KernelUtils.getFrameworkProp(CmsConstants.I18N_LOCALES));
58 // node repository
59 // new ServiceTracker<Repository, Repository>(bc, Repository.class, null) {
60 // @Override
61 // public Repository addingService(ServiceReference<Repository> reference) {
62 // Object cn = reference.getProperty(NodeConstants.CN);
63 // if (cn != null && cn.equals(NodeConstants.EGO_REPOSITORY)) {
64 //// egoRepository = (EgoRepository) bc.getService(reference);
65 // if (log.isTraceEnabled())
66 // log.trace("Home repository is available");
67 // }
68 // return super.addingService(reference);
69 // }
70 //
71 // @Override
72 // public void removedService(ServiceReference<Repository> reference, Repository service) {
73 // super.removedService(reference, service);
74 //// egoRepository = null;
75 // }
76 //
77 // }.open();
78
79 checkReadiness();
80
81 setInstance(this);
82 }
83
84 public void stop() {
85 setInstance(null);
86 }
87
88 /**
89 * Checks whether the deployment is available according to expectations, and
90 * mark it as available.
91 */
92 private void checkReadiness() {
93 if (isAvailable())
94 return;
95 if (cmsDeployment != null && userAdmin != null) {
96 String data = KernelUtils.getFrameworkProp(KernelUtils.OSGI_INSTANCE_AREA);
97 String state = KernelUtils.getFrameworkProp(KernelUtils.OSGI_CONFIGURATION_AREA);
98 availableSince = System.currentTimeMillis();
99 long jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime();
100 String jvmUptimeStr = " in " + (jvmUptime / 1000) + "." + (jvmUptime % 1000) + "s";
101 log.info("## ARGEO CMS AVAILABLE" + (log.isDebugEnabled() ? jvmUptimeStr : "") + " ##");
102 if (log.isDebugEnabled()) {
103 log.debug("## state: " + state);
104 if (data != null)
105 log.debug("## data: " + data);
106 }
107 long begin = cmsState.getAvailableSince();
108 long initDuration = System.currentTimeMillis() - begin;
109 if (log.isTraceEnabled())
110 log.trace("Kernel initialization took " + initDuration + "ms");
111 tributeToFreeSoftware(initDuration);
112 } else {
113 throw new IllegalStateException("Deployment is not available");
114 }
115 }
116
117 final private void tributeToFreeSoftware(long initDuration) {
118 if (log.isTraceEnabled()) {
119 long ms = initDuration / 100;
120 log.trace("Spend " + ms + "ms" + " reflecting on the progress brought to mankind" + " by Free Software...");
121 long beginNano = System.nanoTime();
122 try {
123 Thread.sleep(ms, 0);
124 } catch (InterruptedException e) {
125 // silent
126 }
127 long durationNano = System.nanoTime() - beginNano;
128 final double M = 1000d * 1000d;
129 double sleepAccuracy = ((double) durationNano) / (ms * M);
130 log.trace("Sleep accuracy: " + String.format("%.2f", 100 - (sleepAccuracy * 100 - 100)) + " %");
131 }
132 }
133
134 @Override
135 public void createWorkgroup(String dn) {
136 // if (egoRepository == null)
137 // throw new CmsException("Ego repository is not available");
138 // // TODO add check that the group exists
139 // egoRepository.createWorkgroup(dn);
140 throw new UnsupportedOperationException();
141 }
142
143 public void setCmsDeployment(CmsDeployment cmsDeployment) {
144 this.cmsDeployment = cmsDeployment;
145 }
146
147 public void setCmsState(CmsState cmsState) {
148 this.cmsState = cmsState;
149 }
150
151 public void setUserAdmin(UserAdmin userAdmin) {
152 this.userAdmin = userAdmin;
153 }
154
155 @Override
156 public Locale getDefaultLocale() {
157 return defaultLocale;
158 }
159
160 @Override
161 public List<Locale> getLocales() {
162 return locales;
163 }
164
165 @Override
166 public synchronized Long getAvailableSince() {
167 return availableSince;
168 }
169
170 public synchronized boolean isAvailable() {
171 return availableSince != null;
172 }
173
174 /*
175 * STATIC
176 */
177
178 public synchronized static CmsContextImpl getCmsContext() {
179 return getInstance();
180 }
181
182 // /** Required by USER login module. */
183 // public synchronized static UserAdmin getUserAdmin() {
184 // return getInstance().userAdmin;
185 // }
186
187 /** Required by SPNEGO login module. */
188 @Deprecated
189 public synchronized static GSSCredential getAcceptorCredentials() {
190 // FIXME find a cleaner way
191 return ((CmsUserAdmin) getInstance().userAdmin).getAcceptorCredentials();
192 }
193
194 private synchronized static void setInstance(CmsContextImpl cmsContextImpl) {
195 if (cmsContextImpl != null) {
196 if (instance.isDone())
197 throw new IllegalStateException("CMS Context is already set");
198 instance.complete(cmsContextImpl);
199 } else {
200 instance = new CompletableFuture<CmsContextImpl>();
201 }
202 }
203
204 private synchronized static CmsContextImpl getInstance() {
205 try {
206 return instance.get();
207 } catch (InterruptedException | ExecutionException e) {
208 throw new IllegalStateException("Cannot retrieve CMS Context", e);
209 }
210 }
211
212 public UserAdmin getUserAdmin() {
213 return userAdmin;
214 }
215
216 /*
217 * CMS Sessions
218 */
219
220 @Override
221 public synchronized CmsSession getCmsSession(Subject subject) {
222 if (subject.getPrivateCredentials(CmsSessionId.class).isEmpty())
223 return null;
224 CmsSessionId cmsSessionId = subject.getPrivateCredentials(CmsSessionId.class).iterator().next();
225 return getCmsSessionByUuid(cmsSessionId.getUuid());
226 }
227
228 public synchronized void registerCmsSession(CmsSessionImpl cmsSession) {
229 if (cmsSessionsByUuid.containsKey(cmsSession.getUuid())
230 || cmsSessionsByLocalId.containsKey(cmsSession.getLocalId()))
231 throw new IllegalStateException("CMS session " + cmsSession + " is already registered.");
232 cmsSessionsByUuid.put(cmsSession.getUuid(), cmsSession);
233 cmsSessionsByLocalId.put(cmsSession.getLocalId(), cmsSession);
234 }
235
236 public synchronized void unregisterCmsSession(CmsSessionImpl cmsSession) {
237 if (!cmsSessionsByUuid.containsKey(cmsSession.getUuid())
238 || !cmsSessionsByLocalId.containsKey(cmsSession.getLocalId()))
239 throw new IllegalStateException("CMS session " + cmsSession + " is not registered.");
240 CmsSession removed = cmsSessionsByUuid.remove(cmsSession.getUuid());
241 assert removed == cmsSession;
242 cmsSessionsByLocalId.remove(cmsSession.getLocalId());
243 }
244
245 /**
246 * The {@link CmsSession} related to this UUID, or <code>null</null> if not
247 * registered.
248 */
249 public synchronized CmsSessionImpl getCmsSessionByUuid(UUID uuid) {
250 return cmsSessionsByUuid.get(uuid);
251 }
252
253 /**
254 * The {@link CmsSession} related to this local id, or <code>null</null> if not
255 * registered.
256 */
257 public synchronized CmsSessionImpl getCmsSessionByLocalId(String localId) {
258 return cmsSessionsByLocalId.get(localId);
259 }
260
261 }