X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.cms%2Fsrc%2Forg%2Fargeo%2Fcms%2Finternal%2Fkernel%2FCmsDeployment.java;h=d7be37226000a2b4747491523620c7554c2a2368;hb=6c4d496d34b9eda2f5f965a5eb6db861ff483770;hp=dc64590874f5d50358a9d067be381391065efd35;hpb=2afabd9e7b225f80b341063e25188314394c9aef;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java index dc6459087..d7be37226 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java @@ -1,12 +1,16 @@ package org.argeo.cms.internal.kernel; -import static org.argeo.node.DataModelNamespace.CMS_DATA_MODEL_NAMESPACE; +import static org.argeo.api.DataModelNamespace.CMS_DATA_MODEL_NAMESPACE; +import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX; import java.io.File; +import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.lang.management.ManagementFactory; import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -19,6 +23,7 @@ import javax.jcr.Repository; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.security.auth.callback.CallbackHandler; +import javax.servlet.Servlet; import javax.transaction.UserTransaction; import org.apache.commons.logging.Log; @@ -26,15 +31,18 @@ import org.apache.commons.logging.LogFactory; import org.apache.jackrabbit.commons.cnd.CndImporter; import org.apache.jackrabbit.core.RepositoryContext; import org.apache.jackrabbit.core.RepositoryImpl; +import org.argeo.api.DataModelNamespace; +import org.argeo.api.NodeConstants; +import org.argeo.api.NodeDeployment; +import org.argeo.api.NodeState; +import org.argeo.api.security.CryptoKeyring; +import org.argeo.api.security.Keyring; import org.argeo.cms.ArgeoNames; import org.argeo.cms.CmsException; +import org.argeo.cms.internal.http.CmsRemotingServlet; +import org.argeo.cms.internal.http.CmsWebDavServlet; +import org.argeo.cms.internal.http.HttpUtils; import org.argeo.jcr.JcrUtils; -import org.argeo.node.DataModelNamespace; -import org.argeo.node.NodeConstants; -import org.argeo.node.NodeDeployment; -import org.argeo.node.NodeState; -import org.argeo.node.security.CryptoKeyring; -import org.argeo.node.security.Keyring; import org.argeo.osgi.useradmin.UserAdminConf; import org.argeo.util.LangUtils; import org.eclipse.equinox.http.jetty.JettyConfigurator; @@ -50,6 +58,8 @@ import org.osgi.framework.wiring.BundleWiring; import org.osgi.service.cm.Configuration; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.cm.ManagedService; +import org.osgi.service.http.HttpService; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; import org.osgi.service.useradmin.Group; import org.osgi.service.useradmin.Role; import org.osgi.service.useradmin.UserAdmin; @@ -65,9 +75,10 @@ public class CmsDeployment implements NodeDeployment { private Long availableSince; - private final boolean cleanState; +// private final boolean cleanState; - private NodeHttp nodeHttp; +// private NodeHttp nodeHttp; + private String webDavConfig = HttpUtils.WEBDAV_CONFIG; private boolean argeoDataModelExtensionsAvailable = false; @@ -78,26 +89,29 @@ public class CmsDeployment implements NodeDeployment { private boolean httpAvailable = false; public CmsDeployment() { - ServiceReference nodeStateSr = bc.getServiceReference(NodeState.class); - if (nodeStateSr == null) - throw new CmsException("No node state available"); +// ServiceReference nodeStateSr = bc.getServiceReference(NodeState.class); +// if (nodeStateSr == null) +// throw new CmsException("No node state available"); - NodeState nodeState = bc.getService(nodeStateSr); - cleanState = nodeState.isClean(); +// NodeState nodeState = bc.getService(nodeStateSr); +// cleanState = nodeState.isClean(); - nodeHttp = new NodeHttp(cleanState); +// nodeHttp = new NodeHttp(); dataModels = new DataModels(bc); initTrackers(); } private void initTrackers() { - ServiceTracker httpSt = new ServiceTracker(bc, NodeHttp.class, null) { + ServiceTracker httpSt = new ServiceTracker(bc, HttpService.class, null) { @Override - public NodeHttp addingService(ServiceReference reference) { + 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(reference); + return super.addingService(sr); } }; // httpSt.open(); @@ -125,17 +139,17 @@ public class CmsDeployment implements NodeDeployment { @Override public ConfigurationAdmin addingService(ServiceReference reference) { ConfigurationAdmin configurationAdmin = bc.getService(reference); - deployConfig = new DeployConfig(configurationAdmin, dataModels, cleanState); + boolean isClean; + try { + Configuration[] confs = configurationAdmin + .listConfigurations("(service.factoryPid=" + NodeConstants.NODE_USER_ADMIN_PID + ")"); + isClean = confs == null || confs.length == 0; + } catch (Exception e) { + throw new CmsException("Cannot analize clean state", e); + } + deployConfig = new DeployConfig(configurationAdmin, dataModels, isClean); httpExpected = deployConfig.getProps(KernelConstants.JETTY_FACTORY_PID, "default") != null; try { - // Configuration[] configs = configurationAdmin - // .listConfigurations("(service.factoryPid=" + - // NodeConstants.NODE_REPOS_FACTORY_PID + ")"); - // for (Configuration config : configs) { - // Object cn = config.getProperties().get(NodeConstants.CN); - // if (log.isDebugEnabled()) - // log.debug("Standalone repo cn: " + cn); - // } Configuration[] configs = configurationAdmin .listConfigurations("(service.factoryPid=" + NodeConstants.NODE_USER_ADMIN_PID + ")"); @@ -160,6 +174,10 @@ public class CmsDeployment implements NodeDeployment { KernelUtils.asyncOpen(confAdminSt); } + 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) UserTransaction userTransaction = bc.getService(bc.getServiceReference(UserTransaction.class)); @@ -194,8 +212,8 @@ public class CmsDeployment implements NodeDeployment { } public void shutdown() { - if (nodeHttp != null) - nodeHttp.destroy(); +// if (nodeHttp != null) +// nodeHttp.destroy(); try { for (ServiceReference sr : bc @@ -267,7 +285,7 @@ public class CmsDeployment implements NodeDeployment { } // home - prepareDataModel(NodeConstants.NODE, deployedNodeRepository); + prepareDataModel(NodeConstants.NODE_REPOSITORY, deployedNodeRepository); } private void prepareHomeRepository(RepositoryImpl deployedRepository) { @@ -285,10 +303,11 @@ public class CmsDeployment implements NodeDeployment { // Publish home with the highest service ranking Hashtable regProps = new Hashtable<>(); - regProps.put(NodeConstants.CN, NodeConstants.EGO); + regProps.put(NodeConstants.CN, NodeConstants.EGO_REPOSITORY); regProps.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE); Repository egoRepository = new EgoRepository(deployedRepository, false); bc.registerService(Repository.class, egoRepository, regProps); + registerRepositoryServlets(NodeConstants.EGO_REPOSITORY, egoRepository); // Keyring only if Argeo extensions are available if (argeoDataModelExtensionsAvailable) { @@ -317,7 +336,7 @@ public class CmsDeployment implements NodeDeployment { BundleWiring wiring = bundle.adapt(BundleWiring.class); if (wiring == null) continue bundles; - if (NodeConstants.NODE.equals(cn))// process all data models + if (NodeConstants.NODE_REPOSITORY.equals(cn))// process all data models processWiring(cn, adminSession, wiring, processed, false); else { List capabilities = wiring.getCapabilities(CMS_DATA_MODEL_NAMESPACE); @@ -395,7 +414,7 @@ public class CmsDeployment implements NodeDeployment { boolean publishLocalRepo; if (isStandalone && name.equals(cn))// includes the node itself publishLocalRepo = true; - else if (!isStandalone && cn.equals(NodeConstants.NODE)) + else if (!isStandalone && cn.equals(NodeConstants.NODE_REPOSITORY)) publishLocalRepo = true; else publishLocalRepo = false; @@ -417,6 +436,9 @@ public class CmsDeployment implements NodeDeployment { classes = new String[] { Repository.class.getName(), LocalRepository.class.getName() }; } bc.registerService(classes, localRepository, properties); + + // TODO make it configurable + registerRepositoryServlets(dataModelName, localRepository); if (log.isTraceEnabled()) log.trace("Published data model " + dataModelName); } @@ -430,6 +452,54 @@ public class CmsDeployment implements NodeDeployment { return availableSince != null; } + protected void registerRepositoryServlets(String alias, Repository repository) { + registerRemotingServlet(alias, repository); + registerWebdavServlet(alias, repository); + } + + protected void registerWebdavServlet(String alias, Repository repository) { + CmsWebDavServlet webdavServlet = new CmsWebDavServlet(alias, repository); + Hashtable ip = new Hashtable<>(); + ip.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + CmsWebDavServlet.INIT_PARAM_RESOURCE_CONFIG, webDavConfig); + ip.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + CmsWebDavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, + "/" + alias); + + ip.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/" + alias + "/*"); + ip.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, + "(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH + "=" + NodeConstants.PATH_DATA + ")"); + bc.registerService(Servlet.class, webdavServlet, ip); + } + + protected void registerRemotingServlet(String alias, Repository repository) { + CmsRemotingServlet remotingServlet = new CmsRemotingServlet(alias, repository); + Hashtable ip = new Hashtable<>(); + ip.put(NodeConstants.CN, alias); + // Properties ip = new Properties(); + ip.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + CmsRemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, + "/" + alias); + ip.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + CmsRemotingServlet.INIT_PARAM_AUTHENTICATE_HEADER, + "Negotiate"); + + // Looks like a bug in Jackrabbit remoting init + Path tmpDir; + try { + tmpDir = Files.createTempDirectory("remoting_" + alias); + } catch (IOException e) { + throw new CmsException("Cannot create temp directory for remoting servlet", e); + } + ip.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + CmsRemotingServlet.INIT_PARAM_HOME, tmpDir.toString()); + ip.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + CmsRemotingServlet.INIT_PARAM_TMP_DIRECTORY, + "remoting_" + alias); + ip.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + CmsRemotingServlet.INIT_PARAM_PROTECTED_HANDLERS_CONFIG, + HttpUtils.DEFAULT_PROTECTED_HANDLERS); + ip.put(HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX + CmsRemotingServlet.INIT_PARAM_CREATE_ABSOLUTE_URI, "false"); + + ip.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/" + alias + "/*"); + ip.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, + "(" + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH + "=" + NodeConstants.PATH_JCR + ")"); + bc.registerService(Servlet.class, remotingServlet, ip); + } + private class RepositoryContextStc extends ServiceTracker { public RepositoryContextStc() { @@ -441,10 +511,11 @@ public class CmsDeployment implements NodeDeployment { RepositoryContext repoContext = bc.getService(reference); String cn = (String) reference.getProperty(NodeConstants.CN); if (cn != null) { - if (cn.equals(NodeConstants.NODE)) { + if (cn.equals(NodeConstants.NODE_REPOSITORY)) { prepareNodeRepository(repoContext.getRepository()); // TODO separate home repository prepareHomeRepository(repoContext.getRepository()); + registerRepositoryServlets(cn, repoContext.getRepository()); nodeAvailable = true; checkReadiness(); } else {