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