import java.lang.management.ManagementFactory;
+import javax.jcr.Repository;
import javax.jcr.RepositoryFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jackrabbit.util.TransientFileFactory;
import org.argeo.ArgeoException;
+import org.argeo.cms.CmsException;
import org.argeo.jackrabbit.OsgiJackrabbitRepositoryFactory;
+import org.argeo.jcr.ArgeoJcrConstants;
import org.argeo.security.core.InternalAuthentication;
+import org.eclipse.equinox.http.servlet.ExtendedHttpService;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
import org.springframework.security.core.context.SecurityContextHolder;
/**
* <li>OS access</li>
* </ul>
*/
-final class Kernel {
+final class Kernel implements ServiceListener {
private final static Log log = LogFactory.getLog(Kernel.class);
- // private static final String PROP_WORKBENCH_AUTOSTART =
- // "org.eclipse.rap.workbenchAutostart";
private final BundleContext bundleContext;
+ private final ThreadGroup threadGroup = new ThreadGroup("Argeo CMS Kernel");
private JackrabbitNode node;
private RepositoryFactory repositoryFactory;
}
void init() {
- ClassLoader currentContextCl = Thread.currentThread()
- .getContextClassLoader();
- // We use the CMS bundle classloader during initialization
- Thread.currentThread().setContextClassLoader(
- Kernel.class.getClassLoader());
+ new Thread(threadGroup, "init") {
+ @Override
+ public void run() {
+ // CMS bundle classloader used during initialisation
+ Thread.currentThread().setContextClassLoader(
+ Kernel.class.getClassLoader());
+ doInit();
+ }
+ }.start();
+ }
+ /** Run asynchronously */
+ protected void doInit() {
long begin = System.currentTimeMillis();
InternalAuthentication initAuth = new InternalAuthentication(
KernelConstants.DEFAULT_SECURITY_KEY);
node = new JackrabbitNode(bundleContext);
repositoryFactory = new OsgiJackrabbitRepositoryFactory();
nodeSecurity = new NodeSecurity(bundleContext, node);
- nodeHttp = new NodeHttp(bundleContext, node, nodeSecurity);
+
+ // Equinox dependency
+ ExtendedHttpService httpService = waitForHttpService();
+ nodeHttp = new NodeHttp(httpService, node, nodeSecurity);
// Publish services to OSGi
nodeSecurity.publish();
node.publish();
bundleContext.registerService(RepositoryFactory.class,
repositoryFactory, null);
- nodeHttp.publish();
+
+ bundleContext.addServiceListener(Kernel.this);
} catch (Exception e) {
log.error("Cannot initialize Argeo CMS", e);
throw new ArgeoException("Cannot initialize", e);
- } finally {
- Thread.currentThread().setContextClassLoader(currentContextCl);
}
long jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime();
void destroy() {
long begin = System.currentTimeMillis();
- nodeHttp = null;
- nodeSecurity.destroy();
- node.destroy();
+ if (nodeHttp != null)
+ nodeHttp.destroy();
+ if (nodeSecurity != null)
+ nodeSecurity.destroy();
+ if (node != null)
+ node.destroy();
+
+ bundleContext.removeServiceListener(this);
// Clean hanging threads from Jackrabbit
TransientFileFactory.shutdown();
+ (duration % 1000) + "s ##");
}
- private void directorsCut(long initDuration) {
+ @Override
+ public void serviceChanged(ServiceEvent event) {
+ ServiceReference<?> sr = event.getServiceReference();
+ Object jcrRepoAlias = sr
+ .getProperty(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS);
+ if (jcrRepoAlias != null) {// JCR repository
+ String alias = jcrRepoAlias.toString();
+ Repository repository = (Repository) bundleContext.getService(sr);
+ if (ServiceEvent.REGISTERED == event.getType()) {
+ try {
+ nodeHttp.registerWebdavServlet(alias, repository, true);
+ nodeHttp.registerWebdavServlet(alias, repository, false);
+ nodeHttp.registerRemotingServlet(alias, repository, true);
+ nodeHttp.registerRemotingServlet(alias, repository, false);
+ } catch (Exception e) {
+ throw new CmsException("Could not publish JCR repository "
+ + alias, e);
+ }
+ } else if (ServiceEvent.UNREGISTERING == event.getType()) {
+ }
+ }
+
+ }
+
+ final private static void directorsCut(long initDuration) {
// final long ms = 128l + (long) (Math.random() * 128d);
long ms = initDuration / 10;
log.info("Spend " + ms + "ms"
long durationNano = System.nanoTime() - beginNano;
final double M = 1000d * 1000d;
double sleepAccuracy = ((double) durationNano) / (ms * M);
- if (log.isDebugEnabled())
- log.debug("Sleep accuracy: "
+ if (log.isTraceEnabled())
+ log.trace("Sleep accuracy: "
+ String.format("%.2f", sleepAccuracy * 100) + " %");
}
+ private ExtendedHttpService waitForHttpService() {
+ final ServiceTracker<ExtendedHttpService, ExtendedHttpService> st = new ServiceTracker<ExtendedHttpService, ExtendedHttpService>(
+ bundleContext, ExtendedHttpService.class, null);
+ st.open();
+ ExtendedHttpService httpService;
+ try {
+ httpService = st.waitForService(1000);
+ } catch (InterruptedException e) {
+ httpService = null;
+ }
+
+ if (httpService == null)
+ throw new CmsException("Could not find "
+ + ExtendedHttpService.class + " service.");
+ return httpService;
+ }
}
package org.argeo.cms.internal.kernel;
+import static org.argeo.jackrabbit.servlet.WebdavServlet.INIT_PARAM_RESOURCE_CONFIG;
+
import java.io.IOException;
import java.util.Enumeration;
import java.util.Properties;
import java.util.StringTokenizer;
+import javax.jcr.Repository;
import javax.servlet.FilterChain;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import org.argeo.jackrabbit.servlet.RemotingServlet;
import org.argeo.jackrabbit.servlet.WebdavServlet;
import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.security.NodeAuthenticationToken;
import org.eclipse.equinox.http.servlet.ExtendedHttpService;
-import org.osgi.framework.BundleContext;
import org.osgi.service.http.NamespaceException;
-import org.osgi.util.tracker.ServiceTracker;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
private final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
private final AuthenticationManager authenticationManager;
- private final BundleContext bundleContext;
- private ExtendedHttpService httpService;
+ private final ExtendedHttpService httpService;
// FIXME Make it more unique
private String httpAuthRealm = "Argeo";
// private final DoSFilter dosFilter;
// private final QoSFilter qosFilter;
- // remoting
+ // WebDav / JCR remoting
private OpenInViewSessionProvider sessionProvider;
- private WebdavServlet publicWebdavServlet;
- private WebdavServlet privateWebdavServlet;
- private RemotingServlet publicRemotingServlet;
- private RemotingServlet privateRemotingServlet;
- NodeHttp(BundleContext bundleContext, JackrabbitNode node,
+ NodeHttp(ExtendedHttpService httpService, JackrabbitNode node,
NodeSecurity authenticationManager) {
- this.bundleContext = bundleContext;
+ // this.bundleContext = bundleContext;
this.authenticationManager = authenticationManager;
- // Equinox dependency
- ServiceTracker<ExtendedHttpService, ExtendedHttpService> st = new ServiceTracker<ExtendedHttpService, ExtendedHttpService>(
- bundleContext, ExtendedHttpService.class, null);
- st.open();
- try {
- httpService = st.waitForService(1000);
- } catch (InterruptedException e) {
- httpService = null;
- }
-
- if (httpService == null)
- throw new CmsException("Could not find "
- + ExtendedHttpService.class + " service.");
+ this.httpService = httpService;
// Filters
rootFilter = new RootFilter();
// DAV
sessionProvider = new OpenInViewSessionProvider();
- publicWebdavServlet = new WebdavServlet(node, sessionProvider);
- privateWebdavServlet = new WebdavServlet(node, sessionProvider);
- publicRemotingServlet = new RemotingServlet(node, sessionProvider);
- privateRemotingServlet = new RemotingServlet(node, sessionProvider);
- }
- void publish() {
try {
- registerWebdavServlet(PATH_WEBDAV_PUBLIC, ALIAS_NODE, true,
- publicWebdavServlet);
- registerWebdavServlet(PATH_WEBDAV_PRIVATE, ALIAS_NODE, false,
- privateWebdavServlet);
- registerRemotingServlet(PATH_REMOTING_PUBLIC, ALIAS_NODE, true,
- publicRemotingServlet);
- registerRemotingServlet(PATH_REMOTING_PRIVATE, ALIAS_NODE, false,
- privateRemotingServlet);
-
- // httpService.registerFilter("/", dosFilter, null, null);
+ registerWebdavServlet(ALIAS_NODE, node, true);
+ registerWebdavServlet(ALIAS_NODE, node, false);
+ registerRemotingServlet(ALIAS_NODE, node, true);
+ registerRemotingServlet(ALIAS_NODE, node, false);
+
httpService.registerFilter("/", rootFilter, null, null);
- // httpService.registerFilter("/", qosFilter, null, null);
} catch (Exception e) {
- throw new CmsException("Cannot publish HTTP services to OSGi", e);
+ throw new CmsException("Could not initialise http", e);
}
}
- private void registerWebdavServlet(String pathPrefix, String alias,
- Boolean anonymous, WebdavServlet webdavServlet)
- throws NamespaceException, ServletException {
+ public void destroy() {
+ sessionProvider.destroy();
+ }
+
+ void registerWebdavServlet(String alias, Repository repository,
+ boolean anonymous) throws NamespaceException, ServletException {
+ WebdavServlet webdavServlet = new WebdavServlet(repository,
+ sessionProvider);
+ String pathPrefix = anonymous ? WEBDAV_PUBLIC : WEBDAV_PRIVATE;
String path = pathPrefix + "/" + alias;
- Properties initParameters = new Properties();
- initParameters.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_CONFIG,
- KernelConstants.WEBDAV_CONFIG);
- initParameters.setProperty(
- WebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path);
+ Properties ip = new Properties();
+ ip.setProperty(INIT_PARAM_RESOURCE_CONFIG, WEBDAV_CONFIG);
+ ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path);
httpService.registerFilter(path, anonymous ? new AnonymousFilter()
: new DavFilter(), null, null);
// Cast to servlet because of a weird behaviour in Eclipse
- httpService.registerServlet(path, (Servlet) webdavServlet,
- initParameters, null);
+ httpService.registerServlet(path, (Servlet) webdavServlet, ip, null);
}
- private void registerRemotingServlet(String pathPrefix, String alias,
- Boolean anonymous, RemotingServlet remotingServlet)
- throws NamespaceException, ServletException {
+ void registerRemotingServlet(String alias, Repository repository,
+ boolean anonymous) throws NamespaceException, ServletException {
+ String pathPrefix = anonymous ? REMOTING_PUBLIC : REMOTING_PRIVATE;
+ RemotingServlet remotingServlet = new RemotingServlet(repository,
+ sessionProvider);
String path = pathPrefix + "/" + alias;
- Properties initParameters = new Properties();
- initParameters.setProperty(
- RemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path);
+ Properties ip = new Properties();
+ ip.setProperty(RemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path);
// Looks like a bug in Jackrabbit remoting init
- initParameters.setProperty(RemotingServlet.INIT_PARAM_HOME,
- KernelUtils.getOsgiInstanceDir(bundleContext)
- + "/tmp/jackrabbit");
- initParameters.setProperty(RemotingServlet.INIT_PARAM_TMP_DIRECTORY,
- "remoting");
+ ip.setProperty(RemotingServlet.INIT_PARAM_HOME,
+ KernelUtils.getOsgiInstanceDir() + "/tmp/jackrabbit");
+ ip.setProperty(RemotingServlet.INIT_PARAM_TMP_DIRECTORY, "remoting");
// Cast to servlet because of a weird behaviour in Eclipse
httpService.registerFilter(path, anonymous ? new AnonymousFilter()
: new DavFilter(), null, null);
- httpService.registerServlet(path, (Servlet) remotingServlet,
- initParameters, null);
+ httpService.registerServlet(path, (Servlet) remotingServlet, ip, null);
}
private Boolean isSessionAuthenticated(HttpSession httpSession) {
httpSession.setAttribute(ATTR_AUTH, Boolean.TRUE);
}
- private UsernamePasswordAuthenticationToken basicAuth(String authHeader) {
+ private NodeAuthenticationToken basicAuth(String authHeader) {
if (authHeader != null) {
StringTokenizer st = new StringTokenizer(authHeader);
if (st.hasMoreTokens()) {
String password = credentials.substring(p + 1)
.trim();
- return new UsernamePasswordAuthenticationToken(
- login, password.toCharArray());
+ return new NodeAuthenticationToken(login,
+ password.toCharArray());
} else {
throw new CmsException(
"Invalid authentication token");
}
/** Intercepts all requests. Authenticates. */
- class AnonymousFilter extends HttpFilter {
+ private class AnonymousFilter extends HttpFilter {
@Override
public void doFilter(HttpSession httpSession,
HttpServletRequest request, HttpServletResponse response,
}
/** Intercepts all requests. Authenticates. */
- class DavFilter extends HttpFilter {
+ private class DavFilter extends HttpFilter {
@Override
public void doFilter(HttpSession httpSession,