<!-- <artifactId>org.osgi.service.component.annotations</artifactId> -->
<!-- </dependency> -->
- <!-- Jackson JSON processor -->
- <dependency>
- <groupId>org.argeo.tp.jackson</groupId>
- <artifactId>com.fasterxml.jackson.core.jackson-core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.jackson</groupId>
- <artifactId>com.fasterxml.jackson.core.jackson-databind</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.jackson</groupId>
- <artifactId>com.fasterxml.jackson.core.jackson-annotations</artifactId>
- </dependency>
<dependency>
<groupId>org.argeo.tp.bouncycastle</groupId>
<groupId>org.argeo.tp.apache.commons</groupId>
<artifactId>org.apache.commons.httpclient</artifactId>
</dependency>
- <dependency>
- <groupId>org.argeo.tp.apache.commons</groupId>
- <artifactId>org.apache.commons.vfs</artifactId>
- </dependency>
<dependency>
<groupId>org.argeo.tp.apache.commons</groupId>
<artifactId>org.apache.commons.net</artifactId>
<artifactId>org.eclipse.equinox.metatype</artifactId>
</dependency>
- <!-- SSH -->
- <dependency>
- <groupId>org.argeo.tp.apache</groupId>
- <artifactId>org.apache.mina.core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.apache</groupId>
- <artifactId>org.apache.tomcat.jni</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.apache</groupId>
- <artifactId>org.apache.sshd.core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.apache</groupId>
- <artifactId>org.apache.sshd.common</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.apache</groupId>
- <artifactId>org.apache.sshd.sftp</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.apache</groupId>
- <artifactId>org.apache.sshd.scp</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.apache</groupId>
- <artifactId>org.apache.sshd.cli</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.apache</groupId>
- <artifactId>org.apache.sshd.putty</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.misc</groupId>
- <artifactId>net.i2p.crypto.eddsa</artifactId>
- </dependency>
-
<!-- Console -->
<dependency>
<groupId>org.argeo.tp.apache.felix</groupId>
<artifactId>org.argeo.maintenance</artifactId>
<version>2.1.89-SNAPSHOT</version>
</dependency>
-<!-- <dependency> -->
-<!-- <groupId>org.argeo.commons</groupId> -->
-<!-- <artifactId>org.argeo.ext.jackrabbit</artifactId> -->
-<!-- <version>2.1.89-SNAPSHOT</version> -->
-<!-- </dependency> -->
- <dependency>
- <groupId>org.argeo.commons</groupId>
- <artifactId>org.argeo.ext.equinox.jetty</artifactId>
- <version>2.1.89-SNAPSHOT</version>
- </dependency>
<!-- CMS Dependencies -->
<!-- <dependency> -->
<artifactId>org.eclipse.jetty.xml</artifactId>
</dependency>
- <!-- HTTP2 -->
- <dependency>
- <groupId>org.argeo.tp.jetty</groupId>
- <artifactId>org.eclipse.jetty.alpn.api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.jetty</groupId>
- <artifactId>org.eclipse.jetty.alpn.client</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.jetty</groupId>
- <artifactId>org.eclipse.jetty.alpn.server</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.jetty</groupId>
- <artifactId>org.eclipse.jetty.http2.common</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.jetty</groupId>
- <artifactId>org.eclipse.jetty.http2.client</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.jetty</groupId>
- <artifactId>org.eclipse.jetty.http2.client.http</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.jetty</groupId>
- <artifactId>org.eclipse.jetty.http2.server</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.jetty</groupId>
- <artifactId>org.eclipse.jetty.http2.hpack</artifactId>
- </dependency>
- <!-- Async -->
- <dependency>
- <groupId>org.argeo.tp.javax</groupId>
- <artifactId>javax.websocket</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.jetty</groupId>
- <artifactId>org.eclipse.jetty.websocket.api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.jetty</groupId>
- <artifactId>org.eclipse.jetty.websocket.common</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.jetty</groupId>
- <artifactId>org.eclipse.jetty.websocket.client</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.jetty</groupId>
- <artifactId>org.eclipse.jetty.websocket.server</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.jetty</groupId>
- <artifactId>org.eclipse.jetty.websocket.servlet</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.jetty</groupId>
- <artifactId>org.eclipse.jetty.websocket.javax.websocket</artifactId>
- </dependency>
- <dependency>
- <groupId>org.argeo.tp.jetty</groupId>
- <artifactId>org.eclipse.jetty.websocket.javax.websocket.server</artifactId>
- </dependency>
</dependencies>
<profiles>
+++ /dev/null
-package org.argeo.cms.integration;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-/** Serialisable wrapper of a {@link Throwable}. */
-public class CmsExceptionsChain {
- public final static Log log = LogFactory.getLog(CmsExceptionsChain.class);
-
- private List<SystemException> exceptions = new ArrayList<>();
-
- public CmsExceptionsChain() {
- super();
- }
-
- public CmsExceptionsChain(Throwable exception) {
- writeException(exception);
- if (log.isDebugEnabled())
- log.error("Exception chain", exception);
- }
-
- public String toJsonString(ObjectMapper objectMapper) {
- try {
- return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(this);
- } catch (JsonProcessingException e) {
- throw new IllegalStateException("Cannot write system exceptions " + toString(), e);
- }
- }
-
- public void writeAsJson(ObjectMapper objectMapper, Writer writer) {
- try {
- JsonGenerator jg = objectMapper.writerWithDefaultPrettyPrinter().getFactory().createGenerator(writer);
- jg.writeObject(this);
- } catch (IOException e) {
- throw new IllegalStateException("Cannot write system exceptions " + toString(), e);
- }
- }
-
- public void writeAsJson(ObjectMapper objectMapper, HttpServletResponse resp) {
- try {
- resp.setContentType("application/json");
- resp.setStatus(500);
- writeAsJson(objectMapper, resp.getWriter());
- } catch (IOException e) {
- throw new IllegalStateException("Cannot write system exceptions " + toString(), e);
- }
- }
-
- /** recursive */
- protected void writeException(Throwable exception) {
- SystemException systemException = new SystemException(exception);
- exceptions.add(systemException);
- Throwable cause = exception.getCause();
- if (cause != null)
- writeException(cause);
- }
-
- public List<SystemException> getExceptions() {
- return exceptions;
- }
-
- public void setExceptions(List<SystemException> exceptions) {
- this.exceptions = exceptions;
- }
-
- /** An exception in the chain. */
- public static class SystemException {
- private String type;
- private String message;
- private List<String> stackTrace;
-
- public SystemException() {
- }
-
- public SystemException(Throwable exception) {
- this.type = exception.getClass().getName();
- this.message = exception.getMessage();
- this.stackTrace = new ArrayList<>();
- StackTraceElement[] elems = exception.getStackTrace();
- for (int i = 0; i < elems.length; i++)
- stackTrace.add("at " + elems[i].toString());
- }
-
- public String getType() {
- return type;
- }
-
- public void setType(String type) {
- this.type = type;
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-
- public List<String> getStackTrace() {
- return stackTrace;
- }
-
- public void setStackTrace(List<String> stackTrace) {
- this.stackTrace = stackTrace;
- }
-
- @Override
- public String toString() {
- return "System exception: " + type + ", " + message + ", " + stackTrace;
- }
-
- }
-
- @Override
- public String toString() {
- return exceptions.toString();
- }
-
-// public static void main(String[] args) throws Exception {
-// try {
-// try {
-// try {
-// testDeeper();
-// } catch (Exception e) {
-// throw new Exception("Less deep exception", e);
-// }
-// } catch (Exception e) {
-// throw new RuntimeException("Top exception", e);
-// }
-// } catch (Exception e) {
-// CmsExceptionsChain vjeSystemErrors = new CmsExceptionsChain(e);
-// ObjectMapper objectMapper = new ObjectMapper();
-// System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(vjeSystemErrors));
-// System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(e));
-// e.printStackTrace();
-// }
-// }
-//
-// static void testDeeper() throws Exception {
-// throw new IllegalStateException("Deep exception");
-// }
-
-}
+++ /dev/null
-package org.argeo.cms.integration;
-
-import java.io.IOException;
-import java.util.Locale;
-import java.util.Set;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.argeo.api.NodeConstants;
-import org.argeo.cms.auth.CmsSessionId;
-import org.argeo.cms.auth.HttpRequestCallback;
-import org.argeo.cms.auth.HttpRequestCallbackHandler;
-import org.osgi.service.useradmin.Authorization;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-/** Externally authenticate an http session. */
-public class CmsLoginServlet extends HttpServlet {
- public final static String PARAM_USERNAME = "username";
- public final static String PARAM_PASSWORD = "password";
-
- private static final long serialVersionUID = 2478080654328751539L;
- private ObjectMapper objectMapper = new ObjectMapper();
-
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doPost(request, response);
- }
-
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- LoginContext lc = null;
- String username = request.getParameter(PARAM_USERNAME);
- String password = request.getParameter(PARAM_PASSWORD);
- try {
- lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request, response) {
- public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
- for (Callback callback : callbacks) {
- if (callback instanceof NameCallback && username != null)
- ((NameCallback) callback).setName(username);
- else if (callback instanceof PasswordCallback && password != null)
- ((PasswordCallback) callback).setPassword(password.toCharArray());
- else if (callback instanceof HttpRequestCallback) {
- ((HttpRequestCallback) callback).setRequest(request);
- ((HttpRequestCallback) callback).setResponse(response);
- }
- }
- }
- });
- lc.login();
-
- Subject subject = lc.getSubject();
- CmsSessionId cmsSessionId = extractFrom(subject.getPrivateCredentials(CmsSessionId.class));
- if (cmsSessionId == null) {
- response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
- return;
- }
- Authorization authorization = extractFrom(subject.getPrivateCredentials(Authorization.class));
- Locale locale = extractFrom(subject.getPublicCredentials(Locale.class));
-
- CmsSessionDescriptor cmsSessionDescriptor = new CmsSessionDescriptor(authorization.getName(),
- cmsSessionId.getUuid().toString(), authorization.getRoles(), authorization.toString(),
- locale != null ? locale.toString() : null);
-
- response.setContentType("application/json");
- JsonGenerator jg = objectMapper.getFactory().createGenerator(response.getWriter());
- jg.writeObject(cmsSessionDescriptor);
-
- String redirectTo = redirectTo(request);
- if (redirectTo != null)
- response.sendRedirect(redirectTo);
- } catch (LoginException e) {
- response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
- return;
- }
- }
-
- protected <T> T extractFrom(Set<T> creds) {
- if (creds.size() > 0)
- return creds.iterator().next();
- else
- return null;
- }
-
- /**
- * To be overridden in order to return a richer {@link CmsSessionDescriptor} to
- * be serialized.
- */
- protected CmsSessionDescriptor enrichJson(CmsSessionDescriptor cmsSessionDescriptor) {
- return cmsSessionDescriptor;
- }
-
- protected String redirectTo(HttpServletRequest request) {
- return null;
- }
-}
+++ /dev/null
-package org.argeo.cms.integration;
-
-import java.io.IOException;
-import java.util.Set;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.argeo.api.NodeConstants;
-import org.argeo.cms.auth.CmsSessionId;
-import org.argeo.cms.auth.CurrentUser;
-import org.argeo.cms.auth.HttpRequestCallback;
-import org.argeo.cms.auth.HttpRequestCallbackHandler;
-
-/** Externally authenticate an http session. */
-public class CmsLogoutServlet extends HttpServlet {
- private static final long serialVersionUID = 2478080654328751539L;
-
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doPost(request, response);
- }
-
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- LoginContext lc = null;
- try {
- lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request, response) {
- public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
- for (Callback callback : callbacks) {
- if (callback instanceof HttpRequestCallback) {
- ((HttpRequestCallback) callback).setRequest(request);
- ((HttpRequestCallback) callback).setResponse(response);
- }
- }
- }
- });
- lc.login();
-
- Subject subject = lc.getSubject();
- CmsSessionId cmsSessionId = extractFrom(subject.getPrivateCredentials(CmsSessionId.class));
- if (cmsSessionId != null) {// logged in
- CurrentUser.logoutCmsSession(subject);
- }
-
- } catch (LoginException e) {
- // ignore
- }
-
- String redirectTo = redirectTo(request);
- if (redirectTo != null)
- response.sendRedirect(redirectTo);
- }
-
- protected <T> T extractFrom(Set<T> creds) {
- if (creds.size() > 0)
- return creds.iterator().next();
- else
- return null;
- }
-
- protected String redirectTo(HttpServletRequest request) {
- return null;
- }
-}
+++ /dev/null
-package org.argeo.cms.integration;
-
-import static org.argeo.api.NodeConstants.LOGIN_CONTEXT_USER;
-
-import java.io.IOException;
-import java.security.AccessControlContext;
-import java.security.PrivilegedAction;
-import java.util.Map;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.argeo.cms.auth.HttpRequestCallbackHandler;
-import org.argeo.cms.servlet.ServletAuthUtils;
-import org.osgi.service.http.context.ServletContextHelper;
-
-/** Manages security access to servlets. */
-public class CmsPrivateServletContext extends ServletContextHelper {
- public final static String LOGIN_PAGE = "argeo.cms.integration.loginPage";
- public final static String LOGIN_SERVLET = "argeo.cms.integration.loginServlet";
- private String loginPage;
- private String loginServlet;
-
- public void init(Map<String, String> properties) {
- loginPage = properties.get(LOGIN_PAGE);
- loginServlet = properties.get(LOGIN_SERVLET);
- }
-
- /**
- * Add the {@link AccessControlContext} as a request attribute, or redirect to
- * the login page.
- */
- @Override
- public boolean handleSecurity(final HttpServletRequest request, HttpServletResponse response) throws IOException {
- LoginContext lc = null;
-
- String pathInfo = request.getPathInfo();
- String servletPath = request.getServletPath();
- if ((pathInfo != null && (servletPath + pathInfo).equals(loginPage)) || servletPath.contentEquals(loginServlet))
- return true;
- try {
- lc = new LoginContext(LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request, response));
- lc.login();
- } catch (LoginException e) {
- lc = processUnauthorized(request, response);
- if (lc == null)
- return false;
- }
- Subject.doAs(lc.getSubject(), new PrivilegedAction<Void>() {
-
- @Override
- public Void run() {
- // TODO also set login context in order to log out ?
- ServletAuthUtils.configureRequestSecurity(request);
- return null;
- }
-
- });
-
- return true;
- }
-
- @Override
- public void finishSecurity(HttpServletRequest request, HttpServletResponse response) {
- ServletAuthUtils.clearRequestSecurity(request);
- }
-
- protected LoginContext processUnauthorized(HttpServletRequest request, HttpServletResponse response) {
- try {
- response.sendRedirect(loginPage);
- } catch (IOException e) {
- throw new RuntimeException("Cannot redirect to login page", e);
- }
- return null;
- }
-}
+++ /dev/null
-package org.argeo.cms.integration;
-
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Set;
-import java.util.TreeSet;
-
-import org.argeo.cms.auth.CmsSession;
-import org.osgi.service.useradmin.Authorization;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-
-/** A serializable descriptor of an internal {@link CmsSession}. */
-@JsonIgnoreProperties(ignoreUnknown = true)
-public class CmsSessionDescriptor implements Serializable, Authorization {
- private static final long serialVersionUID = 8592162323372641462L;
-
- private String name;
- private String cmsSessionId;
- private String displayName;
- private String locale;
- private Set<String> roles;
-
- public CmsSessionDescriptor() {
- }
-
- public CmsSessionDescriptor(String name, String cmsSessionId, String[] roles, String displayName, String locale) {
- this.name = name;
- this.displayName = displayName;
- this.cmsSessionId = cmsSessionId;
- this.locale = locale;
- this.roles = Collections.unmodifiableSortedSet(new TreeSet<>(Arrays.asList(roles)));
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getDisplayName() {
- return displayName;
- }
-
- public void setDisplayName(String displayName) {
- this.displayName = displayName;
- }
-
- public String getCmsSessionId() {
- return cmsSessionId;
- }
-
- public void setCmsSessionId(String cmsSessionId) {
- this.cmsSessionId = cmsSessionId;
- }
-
- public Boolean isAnonymous() {
- return name == null;
- }
-
- public String getLocale() {
- return locale;
- }
-
- public void setLocale(String locale) {
- this.locale = locale;
- }
-
- @Override
- public boolean hasRole(String name) {
- return roles.contains(name);
- }
-
- @Override
- public String[] getRoles() {
- return roles.toArray(new String[roles.size()]);
- }
-
- public void setRoles(String[] roles) {
- this.roles = Collections.unmodifiableSortedSet(new TreeSet<>(Arrays.asList(roles)));
- }
-
- @Override
- public int hashCode() {
- return cmsSessionId != null ? cmsSessionId.hashCode() : super.hashCode();
- }
-
- @Override
- public String toString() {
- return displayName != null ? displayName : name != null ? name : super.toString();
- }
-
-}
+++ /dev/null
-package org.argeo.cms.integration;
-
-import java.io.IOException;
-import java.time.ZonedDateTime;
-import java.util.Set;
-import java.util.UUID;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.argeo.api.NodeConstants;
-import org.argeo.cms.CmsUserManager;
-import org.argeo.cms.auth.HttpRequestCallback;
-import org.argeo.cms.auth.HttpRequestCallbackHandler;
-import org.argeo.naming.NamingUtils;
-import org.osgi.service.useradmin.Authorization;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-/** Provides access to tokens. */
-public class CmsTokenServlet extends HttpServlet {
- private static final long serialVersionUID = 302918711430864140L;
-
- public final static String PARAM_EXPIRY_DATE = "expiryDate";
- public final static String PARAM_TOKEN = "token";
-
- private final static int DEFAULT_HOURS = 24;
-
- private CmsUserManager userManager;
- private ObjectMapper objectMapper = new ObjectMapper();
-
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- LoginContext lc = null;
- try {
- lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request, response) {
- public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
- for (Callback callback : callbacks) {
- if (callback instanceof HttpRequestCallback) {
- ((HttpRequestCallback) callback).setRequest(request);
- ((HttpRequestCallback) callback).setResponse(response);
- }
- }
- }
- });
- lc.login();
- } catch (LoginException e) {
- // ignore
- }
-
- try {
- Subject subject = lc.getSubject();
- Authorization authorization = extractFrom(subject.getPrivateCredentials(Authorization.class));
- String token = UUID.randomUUID().toString();
- String expiryDateStr = request.getParameter(PARAM_EXPIRY_DATE);
- ZonedDateTime expiryDate;
- if (expiryDateStr != null) {
- expiryDate = NamingUtils.ldapDateToZonedDateTime(expiryDateStr);
- } else {
- expiryDate = ZonedDateTime.now().plusHours(DEFAULT_HOURS);
- expiryDateStr = NamingUtils.instantToLdapDate(expiryDate);
- }
- userManager.addAuthToken(authorization.getName(), token, expiryDate);
-
- TokenDescriptor tokenDescriptor = new TokenDescriptor();
- tokenDescriptor.setUsername(authorization.getName());
- tokenDescriptor.setToken(token);
- tokenDescriptor.setExpiryDate(expiryDateStr);
-// tokenDescriptor.setRoles(Collections.unmodifiableSortedSet(new TreeSet<>(Arrays.asList(roles))));
-
- response.setContentType("application/json");
- JsonGenerator jg = objectMapper.getFactory().createGenerator(response.getWriter());
- jg.writeObject(tokenDescriptor);
- } catch (Exception e) {
- new CmsExceptionsChain(e).writeAsJson(objectMapper, response);
- }
- }
-
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- // temporarily wrap POST for ease of testing
- doPost(req, resp);
- }
-
- @Override
- protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- try {
- String token = req.getParameter(PARAM_TOKEN);
- userManager.expireAuthToken(token);
- } catch (Exception e) {
- new CmsExceptionsChain(e).writeAsJson(objectMapper, resp);
- }
- }
-
- protected <T> T extractFrom(Set<T> creds) {
- if (creds.size() > 0)
- return creds.iterator().next();
- else
- return null;
- }
-
- public void setUserManager(CmsUserManager userManager) {
- this.userManager = userManager;
- }
-}
+++ /dev/null
-package org.argeo.cms.integration;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
-import java.security.AccessControlContext;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
-import javax.jcr.PropertyIterator;
-import javax.jcr.PropertyType;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.Value;
-import javax.jcr.nodetype.NodeType;
-import javax.security.auth.Subject;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.jackrabbit.api.JackrabbitNode;
-import org.apache.jackrabbit.api.JackrabbitValue;
-import org.argeo.jcr.JcrUtils;
-import org.osgi.service.http.context.ServletContextHelper;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-/** Access a JCR repository via web services. */
-public class JcrReadServlet extends HttpServlet {
- private static final long serialVersionUID = 6536175260540484539L;
- private final static Log log = LogFactory.getLog(JcrReadServlet.class);
-
- protected final static String ACCEPT_HTTP_HEADER = "Accept";
- protected final static String CONTENT_DISPOSITION_HTTP_HEADER = "Content-Disposition";
-
- protected final static String OCTET_STREAM_CONTENT_TYPE = "application/octet-stream";
- protected final static String XML_CONTENT_TYPE = "application/xml";
- protected final static String JSON_CONTENT_TYPE = "application/json";
-
- private final static String PARAM_VERBOSE = "verbose";
- private final static String PARAM_DEPTH = "depth";
-
- protected final static String JCR_NODES = "jcr:nodes";
- // cf. javax.jcr.Property
- protected final static String JCR_PATH = "path";
- protected final static String JCR_NAME = "name";
-
- protected final static String _JCR = "_jcr";
- protected final static String JCR_PREFIX = "jcr:";
- protected final static String REP_PREFIX = "rep:";
-
- private Repository repository;
- private Integer maxDepth = 8;
-
- private ObjectMapper objectMapper = new ObjectMapper();
-
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- if (log.isTraceEnabled())
- log.trace("Data service: " + req.getPathInfo());
-
- String dataWorkspace = getWorkspace(req);
- String jcrPath = getJcrPath(req);
-
- boolean verbose = req.getParameter(PARAM_VERBOSE) != null && !req.getParameter(PARAM_VERBOSE).equals("false");
- int depth = 1;
- if (req.getParameter(PARAM_DEPTH) != null) {
- depth = Integer.parseInt(req.getParameter(PARAM_DEPTH));
- if (depth > maxDepth)
- throw new RuntimeException("Depth " + depth + " is higher than maximum " + maxDepth);
- }
-
- Session session = null;
- try {
- // authentication
- session = openJcrSession(req, resp, getRepository(), dataWorkspace);
- if (!session.itemExists(jcrPath))
- throw new RuntimeException("JCR node " + jcrPath + " does not exist");
- Node node = session.getNode(jcrPath);
-
- List<String> acceptHeader = readAcceptHeader(req);
- if (!acceptHeader.isEmpty() && node.isNodeType(NodeType.NT_FILE)) {
- resp.setContentType(OCTET_STREAM_CONTENT_TYPE);
- resp.addHeader(CONTENT_DISPOSITION_HTTP_HEADER, "attachment; filename='" + node.getName() + "'");
- IOUtils.copy(JcrUtils.getFileAsStream(node), resp.getOutputStream());
- resp.flushBuffer();
- } else {
- if (!acceptHeader.isEmpty() && acceptHeader.get(0).equals(XML_CONTENT_TYPE)) {
- // TODO Use req.startAsync(); ?
- resp.setContentType(XML_CONTENT_TYPE);
- session.exportSystemView(node.getPath(), resp.getOutputStream(), false, depth <= 1);
- return;
- }
- if (!acceptHeader.isEmpty() && !acceptHeader.contains(JSON_CONTENT_TYPE)) {
- if (log.isTraceEnabled())
- log.warn("Content type " + acceptHeader + " in Accept header is not supported. Supported: "
- + JSON_CONTENT_TYPE + " (default), " + XML_CONTENT_TYPE);
- }
- resp.setContentType(JSON_CONTENT_TYPE);
- JsonGenerator jsonGenerator = getObjectMapper().getFactory().createGenerator(resp.getWriter());
- jsonGenerator.writeStartObject();
- writeNodeChildren(node, jsonGenerator, depth, verbose);
- writeNodeProperties(node, jsonGenerator, verbose);
- jsonGenerator.writeEndObject();
- jsonGenerator.flush();
- }
- } catch (Exception e) {
- new CmsExceptionsChain(e).writeAsJson(getObjectMapper(), resp);
- } finally {
- JcrUtils.logoutQuietly(session);
- }
- }
-
- protected Session openJcrSession(HttpServletRequest req, HttpServletResponse resp, Repository repository,
- String workspace) throws RepositoryException {
- AccessControlContext acc = (AccessControlContext) req.getAttribute(ServletContextHelper.REMOTE_USER);
- Subject subject = Subject.getSubject(acc);
- try {
- return Subject.doAs(subject, new PrivilegedExceptionAction<Session>() {
-
- @Override
- public Session run() throws RepositoryException {
- return repository.login(workspace);
- }
-
- });
- } catch (PrivilegedActionException e) {
- if (e.getException() instanceof RepositoryException)
- throw (RepositoryException) e.getException();
- else
- throw new RuntimeException(e.getException());
- }
-// return workspace != null ? repository.login(workspace) : repository.login();
- }
-
- protected String getWorkspace(HttpServletRequest req) {
- String path = req.getPathInfo();
- try {
- path = URLDecoder.decode(path, StandardCharsets.UTF_8.name());
- } catch (UnsupportedEncodingException e) {
- throw new IllegalArgumentException(e);
- }
- String[] pathTokens = path.split("/");
- return pathTokens[1];
- }
-
- protected String getJcrPath(HttpServletRequest req) {
- String path = req.getPathInfo();
- try {
- path = URLDecoder.decode(path, StandardCharsets.UTF_8.name());
- } catch (UnsupportedEncodingException e) {
- throw new IllegalArgumentException(e);
- }
- String[] pathTokens = path.split("/");
- String domain = pathTokens[1];
- String jcrPath = path.substring(domain.length() + 1);
- return jcrPath;
- }
-
- protected List<String> readAcceptHeader(HttpServletRequest req) {
- List<String> lst = new ArrayList<>();
- String acceptHeader = req.getHeader(ACCEPT_HTTP_HEADER);
- if (acceptHeader == null)
- return lst;
-// Enumeration<String> acceptHeader = req.getHeaders(ACCEPT_HTTP_HEADER);
-// while (acceptHeader.hasMoreElements()) {
- String[] arr = acceptHeader.split("\\.");
- for (int i = 0; i < arr.length; i++) {
- String str = arr[i].trim();
- if (!"".equals(str))
- lst.add(str);
- }
-// }
- return lst;
- }
-
- protected void writeNodeProperties(Node node, JsonGenerator jsonGenerator, boolean verbose)
- throws RepositoryException, IOException {
- String jcrPath = node.getPath();
- Map<String, Map<String, Property>> namespaces = new TreeMap<>();
-
- PropertyIterator pit = node.getProperties();
- properties: while (pit.hasNext()) {
- Property property = pit.nextProperty();
-
- final String propertyName = property.getName();
- int columnIndex = propertyName.indexOf(':');
- if (columnIndex > 0) {
- // mark prefix with a '_' before the name of the object, according to JSON
- // conventions to indicate a special value
- String prefix = "_" + propertyName.substring(0, columnIndex);
- String unqualifiedName = propertyName.substring(columnIndex + 1);
- if (!namespaces.containsKey(prefix))
- namespaces.put(prefix, new LinkedHashMap<String, Property>());
- Map<String, Property> map = namespaces.get(prefix);
- assert !map.containsKey(unqualifiedName);
- map.put(unqualifiedName, property);
- continue properties;
- }
-
- if (property.getType() == PropertyType.BINARY) {
- if (!(node instanceof JackrabbitNode)) {
- continue properties;// skip
- }
- }
-
- writeProperty(propertyName, property, jsonGenerator);
- }
-
- for (String prefix : namespaces.keySet()) {
- Map<String, Property> map = namespaces.get(prefix);
- jsonGenerator.writeFieldName(prefix);
- jsonGenerator.writeStartObject();
- if (_JCR.equals(prefix)) {
- jsonGenerator.writeStringField(JCR_NAME, node.getName());
- jsonGenerator.writeStringField(JCR_PATH, jcrPath);
- }
- properties: for (String unqualifiedName : map.keySet()) {
- Property property = map.get(unqualifiedName);
- if (property.getType() == PropertyType.BINARY) {
- if (!(node instanceof JackrabbitNode)) {
- continue properties;// skip
- }
- }
- writeProperty(unqualifiedName, property, jsonGenerator);
- }
- jsonGenerator.writeEndObject();
- }
- }
-
- protected void writeProperty(String fieldName, Property property, JsonGenerator jsonGenerator)
- throws RepositoryException, IOException {
- if (!property.isMultiple()) {
- jsonGenerator.writeFieldName(fieldName);
- writePropertyValue(property.getType(), property.getValue(), jsonGenerator);
- } else {
- jsonGenerator.writeFieldName(fieldName);
- jsonGenerator.writeStartArray();
- Value[] values = property.getValues();
- for (Value value : values) {
- writePropertyValue(property.getType(), value, jsonGenerator);
- }
- jsonGenerator.writeEndArray();
- }
- }
-
- protected void writePropertyValue(int type, Value value, JsonGenerator jsonGenerator)
- throws RepositoryException, IOException {
- if (type == PropertyType.DOUBLE)
- jsonGenerator.writeNumber(value.getDouble());
- else if (type == PropertyType.LONG)
- jsonGenerator.writeNumber(value.getLong());
- else if (type == PropertyType.BINARY) {
- if (value instanceof JackrabbitValue) {
- String contentIdentity = ((JackrabbitValue) value).getContentIdentity();
- jsonGenerator.writeString("SHA256:" + contentIdentity);
- } else {
- // TODO write Base64 ?
- jsonGenerator.writeNull();
- }
- } else
- jsonGenerator.writeString(value.getString());
- }
-
- protected void writeNodeChildren(Node node, JsonGenerator jsonGenerator, int depth, boolean verbose)
- throws RepositoryException, IOException {
- if (!node.hasNodes())
- return;
- if (depth <= 0)
- return;
- NodeIterator nit;
-
- nit = node.getNodes();
- children: while (nit.hasNext()) {
- Node child = nit.nextNode();
- if (!verbose && child.getName().startsWith(REP_PREFIX)) {
- continue children;// skip Jackrabbit auth metadata
- }
-
- jsonGenerator.writeFieldName(child.getName());
- jsonGenerator.writeStartObject();
- writeNodeChildren(child, jsonGenerator, depth - 1, verbose);
- writeNodeProperties(child, jsonGenerator, verbose);
- jsonGenerator.writeEndObject();
- }
- }
-
- public void setRepository(Repository repository) {
- this.repository = repository;
- }
-
- public void setMaxDepth(Integer maxDepth) {
- this.maxDepth = maxDepth;
- }
-
- protected Repository getRepository() {
- return repository;
- }
-
- protected ObjectMapper getObjectMapper() {
- return objectMapper;
- }
-
-}
+++ /dev/null
-package org.argeo.cms.integration;
-
-import java.io.IOException;
-
-import javax.jcr.ImportUUIDBehavior;
-import javax.jcr.Node;
-import javax.jcr.Session;
-import javax.jcr.nodetype.NodeType;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.jcr.JcrUtils;
-
-/** Access a JCR repository via web services. */
-public class JcrWriteServlet extends JcrReadServlet {
- private static final long serialVersionUID = 17272653843085492L;
- private final static Log log = LogFactory.getLog(JcrWriteServlet.class);
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- if (log.isDebugEnabled())
- log.debug("Data service POST: " + req.getPathInfo());
-
- String dataWorkspace = getWorkspace(req);
- String jcrPath = getJcrPath(req);
-
- Session session = null;
- try {
- // authentication
- session = openJcrSession(req, resp, getRepository(), dataWorkspace);
-
- if (req.getContentType() != null && req.getContentType().equals(XML_CONTENT_TYPE)) {
-// resp.setContentType(XML_CONTENT_TYPE);
- session.getWorkspace().importXML(jcrPath, req.getInputStream(),
- ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
- return;
- }
-
- if (!session.itemExists(jcrPath)) {
- String parentPath = FilenameUtils.getFullPathNoEndSeparator(jcrPath);
- String fileName = FilenameUtils.getName(jcrPath);
- Node folderNode = JcrUtils.mkfolders(session, parentPath);
- byte[] bytes = IOUtils.toByteArray(req.getInputStream());
- JcrUtils.copyBytesAsFile(folderNode, fileName, bytes);
- } else {
- Node node = session.getNode(jcrPath);
- if (!node.isNodeType(NodeType.NT_FILE))
- throw new IllegalArgumentException("Node " + jcrPath + " exists but is not a file");
- byte[] bytes = IOUtils.toByteArray(req.getInputStream());
- JcrUtils.copyBytesAsFile(node.getParent(), node.getName(), bytes);
- }
- session.save();
- } catch (Exception e) {
- new CmsExceptionsChain(e).writeAsJson(getObjectMapper(), resp);
- } finally {
- JcrUtils.logoutQuietly(session);
- }
- }
-
- @Override
- protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- if (log.isDebugEnabled())
- log.debug("Data service DELETE: " + req.getPathInfo());
-
- String dataWorkspace = getWorkspace(req);
- String jcrPath = getJcrPath(req);
-
- Session session = null;
- try {
- // authentication
- session = openJcrSession(req, resp, getRepository(), dataWorkspace);
- if (!session.itemExists(jcrPath)) {
- // ignore
- return;
- } else {
- Node node = session.getNode(jcrPath);
- node.remove();
- }
- session.save();
- } catch (Exception e) {
- new CmsExceptionsChain(e).writeAsJson(getObjectMapper(), resp);
- } finally {
- JcrUtils.logoutQuietly(session);
- }
- }
-
-}
+++ /dev/null
-package org.argeo.cms.integration;
-
-import java.io.Serializable;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-
-/** A serializable descriptor of a token. */
-@JsonIgnoreProperties(ignoreUnknown = true)
-public class TokenDescriptor implements Serializable {
- private static final long serialVersionUID = -6607393871416803324L;
-
- private String token;
- private String username;
- private String expiryDate;
-// private Set<String> roles;
-
- public String getToken() {
- return token;
- }
-
- public void setToken(String token) {
- this.token = token;
- }
-
- public String getUsername() {
- return username;
- }
-
- public void setUsername(String username) {
- this.username = username;
- }
-
-// public Set<String> getRoles() {
-// return roles;
-// }
-//
-// public void setRoles(Set<String> roles) {
-// this.roles = roles;
-// }
-
- public String getExpiryDate() {
- return expiryDate;
- }
-
- public void setExpiryDate(String expiryDate) {
- this.expiryDate = expiryDate;
- }
-
-}
+++ /dev/null
-package org.argeo.cms.integration;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.xml.transform.Result;
-import javax.xml.transform.Source;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.TransformerFactoryConfigurationError;
-import javax.xml.transform.stream.StreamResult;
-import javax.xml.transform.stream.StreamSource;
-
-public class XslTemplate {
- private Transformer transformer;
-
- public XslTemplate(InputStream in, String systemId) {
- this(loadTransformer(in, systemId));
- }
-
- public XslTemplate(Transformer transformer) {
- this.transformer = transformer;
- }
-
- private static Transformer loadTransformer(InputStream in, String systemId) {
- try {
- TransformerFactory tFactory = TransformerFactory.newInstance();
- StreamSource stylesource = new StreamSource(in, systemId);
- return tFactory.newTransformer(stylesource);
- } catch (TransformerConfigurationException | TransformerFactoryConfigurationError e) {
- throw new IllegalArgumentException("Cannot initialise stylesheet with systemId " + systemId, e);
- }
- }
-
- public synchronized void apply(Node node, OutputStream out) {
- // TODO use a pool of Transformer instead of synchronized
- try (ByteArrayOutputStream xml = new ByteArrayOutputStream()) {
- node.getSession().exportDocumentView(node.getPath(), xml, true, false);
- try (ByteArrayInputStream xmlIn = new ByteArrayInputStream(xml.toByteArray())) {
- Source source = new StreamSource(xmlIn);
- Result results = new StreamResult(out);
- transformer.transform(source, results);
- }
- } catch (IOException | RepositoryException | TransformerException e) {
- throw new RuntimeException("Cannot process XSL template on " + node, e);
- }
- }
-}
+++ /dev/null
-/** Argeo CMS integration (JSON, web services). */
-package org.argeo.cms.integration;
\ No newline at end of file
import javax.naming.directory.BasicAttributes;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
-import javax.websocket.server.ServerEndpointConfig;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.argeo.api.NodeConstants;
import org.argeo.cms.CmsException;
-import org.argeo.cms.internal.http.InternalHttpConstants;
-import org.argeo.cms.websocket.CmsWebSocketConfigurator;
import org.argeo.naming.AttributesDictionary;
import org.argeo.naming.LdifParser;
import org.argeo.naming.LdifWriter;
// activator of the Equinox Jetty bundle.
Dictionary<String, Object> webServerConfig = InitUtils
.getHttpServerConfig(getProps(KernelConstants.JETTY_FACTORY_PID, NodeConstants.DEFAULT));
- if (!webServerConfig.isEmpty()) {
- webServerConfig.put("customizer.class", KernelConstants.CMS_JETTY_CUSTOMIZER_CLASS);
-
- // TODO centralise with Jetty extender
- Object webSocketEnabled = webServerConfig.get(InternalHttpConstants.WEBSOCKET_ENABLED);
- if (webSocketEnabled != null && webSocketEnabled.toString().equals("true")) {
- bc.registerService(ServerEndpointConfig.Configurator.class, new CmsWebSocketConfigurator(), null);
- webServerConfig.put(InternalHttpConstants.WEBSOCKET_ENABLED, "true");
- }
- }
+// if (!webServerConfig.isEmpty()) {
+// webServerConfig.put("customizer.class", KernelConstants.CMS_JETTY_CUSTOMIZER_CLASS);
+//
+// // TODO centralise with Jetty extender
+// Object webSocketEnabled = webServerConfig.get(InternalHttpConstants.WEBSOCKET_ENABLED);
+// if (webSocketEnabled != null && webSocketEnabled.toString().equals("true")) {
+// bc.registerService(ServerEndpointConfig.Configurator.class, new CmsWebSocketConfigurator(), null);
+// webServerConfig.put(InternalHttpConstants.WEBSOCKET_ENABLED, "true");
+// }
+// }
int tryCount = 60;
try {
+++ /dev/null
-package org.argeo.cms.websocket;
-
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.List;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-import javax.servlet.http.HttpSession;
-import javax.websocket.Extension;
-import javax.websocket.HandshakeResponse;
-import javax.websocket.server.HandshakeRequest;
-import javax.websocket.server.ServerEndpointConfig;
-import javax.websocket.server.ServerEndpointConfig.Configurator;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.api.NodeConstants;
-import org.argeo.cms.auth.HttpRequestCallbackHandler;
-import org.osgi.service.http.context.ServletContextHelper;
-
-/** Customises the initialisation of a new web socket. */
-public class CmsWebSocketConfigurator extends Configurator {
- public final static String WEBSOCKET_SUBJECT = "org.argeo.cms.websocket.subject";
-
- private final static Log log = LogFactory.getLog(CmsWebSocketConfigurator.class);
- final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
-
- @Override
- public boolean checkOrigin(String originHeaderValue) {
- return true;
- }
-
- @Override
- public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException {
- try {
- return endpointClass.getDeclaredConstructor().newInstance();
- } catch (Exception e) {
- throw new IllegalArgumentException("Cannot get endpoint instance", e);
- }
- }
-
- @Override
- public List<Extension> getNegotiatedExtensions(List<Extension> installed, List<Extension> requested) {
- return requested;
- }
-
- @Override
- public String getNegotiatedSubprotocol(List<String> supported, List<String> requested) {
- if ((requested == null) || (requested.size() == 0))
- return "";
- if ((supported == null) || (supported.isEmpty()))
- return "";
- for (String possible : requested) {
- if (possible == null)
- continue;
- if (supported.contains(possible))
- return possible;
- }
- return "";
- }
-
- @Override
- public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
- HttpSession httpSession = (HttpSession) request.getHttpSession();
- if (log.isDebugEnabled() && httpSession != null)
- log.debug("Web socket HTTP session id: " + httpSession.getId());
-
- if (httpSession == null) {
- rejectResponse(response, null);
- }
- try {
- LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER,
- new HttpRequestCallbackHandler(httpSession));
- lc.login();
- if (log.isDebugEnabled())
- log.debug("Web socket logged-in as " + lc.getSubject());
- Subject.doAs(lc.getSubject(), new PrivilegedAction<Void>() {
-
- @Override
- public Void run() {
- sec.getUserProperties().put(ServletContextHelper.REMOTE_USER, AccessController.getContext());
- return null;
- }
-
- });
- } catch (Exception e) {
- rejectResponse(response, e);
- }
- }
-
- /**
- * Behaviour when the web socket could not be authenticated. Throws an
- * {@link IllegalStateException} by default.
- *
- * @param e can be null
- */
- protected void rejectResponse(HandshakeResponse response, Exception e) {
- // violent implementation, as suggested in
- // https://stackoverflow.com/questions/21763829/jsr-356-how-to-abort-a-websocket-connection-during-the-handshake
-// throw new IllegalStateException("Web socket cannot be authenticated");
- }
-}
+++ /dev/null
-/** Argeo CMS websocket integration. */
-package org.argeo.cms.websocket;
\ No newline at end of file
-Import-Package: com.fasterxml.jackson.annotation;resolution:=optional,\
- com.fasterxml.jackson.core;resolution:=optional,\
- com.fasterxml.jackson.databind;resolution:=optional,\
- org.apache.jackrabbit.api;resolution:=optional,\
- org.apache.jackrabbit.commons;resolution:=optional,\
- *;resolution:=optional
\ No newline at end of file
+Import-Package:\
+org.apache.jackrabbit.api,\
+org.apache.jackrabbit.commons,\
+*
\ No newline at end of file
output.. = bin/
bin.includes = META-INF/,\
.
-additional.bundles = org.apache.sshd.common,\
- org.apache.jackrabbit.data,\
+additional.bundles = org.apache.jackrabbit.data,\
org.slf4j.log4j12,\
org.slf4j.api,\
- org.apache.sshd.core,\
bcprov,\
- org.apache.tomcat.jni,\
org.junit,\
org.hamcrest
+++ /dev/null
-package org.argeo.json;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.Test;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-public class JacksonTest {
-
- @Test
- public void testSimpleObjectMapping() throws JsonProcessingException {
- ObjectMapper om = new ObjectMapper();
- Map<String, Integer> map = new HashMap<>();
- map.put("one", 1);
- map.put("two", 2);
- String s = om.writeValueAsString(map);
- System.out.println(s);
- }
-}
import java.util.concurrent.Callable;
import org.argeo.jackrabbit.fs.DavexFsProvider;
-import org.argeo.ssh.Sftp;
import org.argeo.sync.SyncResult;
/** Synchronises two paths. */
} else if (uri.getScheme().equals("davex")) {
FileSystemProvider fsProvider = new DavexFsProvider();
path = fsProvider.getPath(uri);
- } else if (uri.getScheme().equals("sftp")) {
- Sftp sftp = new Sftp(uri);
- path = sftp.getBasePath();
+// } else if (uri.getScheme().equals("sftp")) {
+// Sftp sftp = new Sftp(uri);
+// path = sftp.getBasePath();
} else
throw new IllegalArgumentException("URI scheme not supported for " + uri);
return path;
+++ /dev/null
-package org.argeo.cli.fs;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Map;
-import java.util.Scanner;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.sshd.agent.SshAgent;
-import org.apache.sshd.agent.SshAgentFactory;
-import org.apache.sshd.agent.local.LocalAgentFactory;
-import org.apache.sshd.agent.unix.UnixAgentFactory;
-import org.apache.sshd.client.SshClient;
-import org.apache.sshd.client.future.ConnectFuture;
-import org.apache.sshd.client.session.ClientSession;
-import org.apache.sshd.client.subsystem.sftp.fs.SftpFileSystem;
-import org.apache.sshd.client.subsystem.sftp.fs.SftpFileSystemProvider;
-
-public class SshSync {
- private final static Log log = LogFactory.getLog(SshSync.class);
-
- public static void main(String[] args) {
-
- try (SshClient client = SshClient.setUpDefaultClient()) {
- client.start();
- boolean osAgent = true;
- SshAgentFactory agentFactory = osAgent ? new UnixAgentFactory() : new LocalAgentFactory();
- // SshAgentFactory agentFactory = new LocalAgentFactory();
- client.setAgentFactory(agentFactory);
- SshAgent sshAgent = agentFactory.createClient(client);
-
- String login = System.getProperty("user.name");
- String host = "localhost";
- int port = 22;
-
- if (!osAgent) {
- String keyPath = "/home/" + login + "/.ssh/id_rsa";
- System.out.print(keyPath + ": ");
- Scanner s = new Scanner(System.in);
- String password = s.next();
-// KeyPair keyPair = ClientIdentityLoader.DEFAULT.loadClientIdentity(keyPath,
-// FilePasswordProvider.of(password));
-// sshAgent.addIdentity(keyPair, "NO COMMENT");
- }
-
-// List<? extends Map.Entry<PublicKey, String>> identities = sshAgent.getIdentities();
-// for (Map.Entry<PublicKey, String> entry : identities) {
-// System.out.println(entry.getValue() + " : " + entry.getKey());
-// }
-
- ConnectFuture connectFuture = client.connect(login, host, port);
- connectFuture.await();
- ClientSession session = connectFuture.getSession();
-
- try {
-
-// session.addPasswordIdentity(new String(password));
- session.auth().verify(1000l);
-
- SftpFileSystemProvider fsProvider = new SftpFileSystemProvider(client);
-
- SftpFileSystem fs = fsProvider.newFileSystem(session);
- Path testPath = fs.getPath("/home/" + login + "/tmp");
- Files.list(testPath).forEach(System.out::println);
- test(testPath);
-
- } finally {
- client.stop();
- }
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- static void test(Path testBase) {
- try {
- Path testPath = testBase.resolve("ssh-test.txt");
- Files.createFile(testPath);
- log.debug("Created file " + testPath);
- Files.delete(testPath);
- log.debug("Deleted " + testPath);
- String txt = "TEST\nTEST2\n";
- byte[] arr = txt.getBytes();
- Files.write(testPath, arr);
- log.debug("Wrote " + testPath);
- byte[] read = Files.readAllBytes(testPath);
- log.debug("Read " + testPath);
- Path testDir = testBase.resolve("testDir");
- log.debug("Resolved " + testDir);
- // Copy
- Files.createDirectory(testDir);
- log.debug("Created directory " + testDir);
- Path subsubdir = Files.createDirectories(testDir.resolve("subdir/subsubdir"));
- log.debug("Created sub directories " + subsubdir);
- Path copiedFile = testDir.resolve("copiedFile.txt");
- log.debug("Resolved " + copiedFile);
- Path relativeCopiedFile = testDir.relativize(copiedFile);
- log.debug("Relative copied file " + relativeCopiedFile);
- try (OutputStream out = Files.newOutputStream(copiedFile);
- InputStream in = Files.newInputStream(testPath)) {
- IOUtils.copy(in, out);
- }
- log.debug("Copied " + testPath + " to " + copiedFile);
- Files.delete(testPath);
- log.debug("Deleted " + testPath);
- byte[] copiedRead = Files.readAllBytes(copiedFile);
- log.debug("Read " + copiedFile);
- // Browse directories
- DirectoryStream<Path> files = Files.newDirectoryStream(testDir);
- int fileCount = 0;
- Path listedFile = null;
- for (Path file : files) {
- fileCount++;
- if (!Files.isDirectory(file))
- listedFile = file;
- }
- log.debug("Listed " + testDir);
- // Generic attributes
- Map<String, Object> attrs = Files.readAttributes(copiedFile, "*");
- log.debug("Read attributes of " + copiedFile + ": " + attrs.keySet());
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- }
-
-}
+++ /dev/null
-package org.argeo.ssh;
-
-import java.io.Console;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Scanner;
-import java.util.Set;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.sshd.client.SshClient;
-import org.apache.sshd.client.channel.ClientChannel;
-import org.apache.sshd.client.channel.ClientChannelEvent;
-import org.apache.sshd.client.future.ConnectFuture;
-import org.apache.sshd.client.session.ClientSession;
-import org.apache.sshd.client.subsystem.sftp.fs.SftpFileSystemProvider;
-import org.apache.sshd.common.util.io.NoCloseInputStream;
-import org.apache.sshd.common.util.io.NoCloseOutputStream;
-
-@SuppressWarnings("restriction")
-abstract class AbstractSsh {
- private final static Log log = LogFactory.getLog(AbstractSsh.class);
-
- private static SshClient sshClient;
- private static SftpFileSystemProvider sftpFileSystemProvider;
-
- private boolean passwordSet = false;
- private ClientSession session;
-
- private SshKeyPair sshKeyPair;
-
- synchronized SshClient getSshClient() {
- if (sshClient == null) {
- long begin = System.currentTimeMillis();
- sshClient = SshClient.setUpDefaultClient();
- sshClient.start();
- long duration = System.currentTimeMillis() - begin;
- if (log.isDebugEnabled())
- log.debug("SSH client started in " + duration + " ms");
- Runtime.getRuntime().addShutdownHook(new Thread(() -> sshClient.stop(), "Stop SSH client"));
- }
- return sshClient;
- }
-
- synchronized SftpFileSystemProvider getSftpFileSystemProvider() {
- if (sftpFileSystemProvider == null) {
- sftpFileSystemProvider = new SftpFileSystemProvider(sshClient);
- }
- return sftpFileSystemProvider;
- }
-
- void authenticate() {
- try {
- if (sshKeyPair != null) {
- session.addPublicKeyIdentity(sshKeyPair.asKeyPair());
- } else {
-
- if (!passwordSet) {
- String password;
- Console console = System.console();
- if (console == null) {// IDE
- System.out.print("Password: ");
- try (Scanner s = new Scanner(System.in)) {
- password = s.next();
- }
- } else {
- console.printf("Password: ");
- char[] pwd = console.readPassword();
- password = new String(pwd);
- Arrays.fill(pwd, ' ');
- }
- session.addPasswordIdentity(password);
- passwordSet = true;
- }
- }
- session.auth().verify(1000l);
- } catch (IOException e) {
- throw new IllegalStateException(e);
- }
- }
-
- void addPassword(String password) {
- session.addPasswordIdentity(password);
- }
-
- void loadKey(String password) {
- loadKey(password, System.getProperty("user.home") + "/.ssh/id_rsa");
- }
-
- void loadKey(String password, String keyPath) {
-// try {
-// KeyPair keyPair = ClientIdentityLoader.DEFAULT.loadClientIdentity(keyPath,
-// FilePasswordProvider.of(password));
-// session.addPublicKeyIdentity(keyPair);
-// } catch (IOException | GeneralSecurityException e) {
-// throw new IllegalStateException(e);
-// }
- }
-
- void openSession(URI uri) {
- openSession(uri.getUserInfo(), uri.getHost(), uri.getPort() > 0 ? uri.getPort() : null);
- }
-
- void openSession(String login, String host, Integer port) {
- if (session != null)
- throw new IllegalStateException("Session is already open");
-
- if (host == null)
- host = "localhost";
- if (port == null)
- port = 22;
- if (login == null)
- login = System.getProperty("user.name");
- String password = null;
- int sepIndex = login.indexOf(':');
- if (sepIndex > 0)
- if (sepIndex + 1 < login.length()) {
- password = login.substring(sepIndex + 1);
- login = login.substring(0, sepIndex);
- } else {
- throw new IllegalArgumentException("Illegal authority: " + login);
- }
- try {
- ConnectFuture connectFuture = getSshClient().connect(login, host, port);
- connectFuture.await();
- ClientSession session = connectFuture.getSession();
- if (password != null) {
- session.addPasswordIdentity(password);
- passwordSet = true;
- }
- this.session = session;
- } catch (IOException e) {
- throw new IllegalStateException("Cannot connect to " + host + ":" + port);
- }
- }
-
- void closeSession() {
- if (session == null)
- throw new IllegalStateException("No session is open");
- try {
- session.close();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- session = null;
- }
- }
-
- ClientSession getSession() {
- return session;
- }
-
- public void setSshKeyPair(SshKeyPair sshKeyPair) {
- this.sshKeyPair = sshKeyPair;
- }
-
- public static void openShell(ClientSession session) {
- try (ClientChannel channel = session.createChannel(ClientChannel.CHANNEL_SHELL)) {
- channel.setIn(new NoCloseInputStream(System.in));
- channel.setOut(new NoCloseOutputStream(System.out));
- channel.setErr(new NoCloseOutputStream(System.err));
- channel.open();
-
- Set<ClientChannelEvent> events = new HashSet<>();
- events.add(ClientChannelEvent.CLOSED);
- channel.waitFor(events, 0);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } finally {
- session.close(false);
- }
- }
-
- static URI toUri(String username, String host, int port) {
- try {
- if (username == null)
- username = "root";
- return new URI("ssh://" + username + "@" + host + ":" + port);
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException("Cannot generate SSH URI to " + host + ":" + port + " for " + username,
- e);
- }
- }
-
-}
+++ /dev/null
-package org.argeo.ssh;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import org.apache.sshd.server.SshServer;
-import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
-import org.apache.sshd.server.scp.ScpCommandFactory;
-import org.apache.sshd.server.shell.ProcessShellFactory;
-import org.argeo.util.OS;
-
-/** A simple SSH server with some defaults. Supports SCP. */
-@SuppressWarnings("restriction")
-public class BasicSshServer {
- private Integer port;
- private Path hostKeyPath;
-
- private SshServer sshd = null;
-
- public BasicSshServer(Integer port, Path hostKeyPath) {
- this.port = port;
- this.hostKeyPath = hostKeyPath;
- }
-
- public void init() {
- try {
- sshd = SshServer.setUpDefaultServer();
- sshd.setPort(port);
- if (hostKeyPath == null)
- throw new IllegalStateException("An SSH server key must be set");
- sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(hostKeyPath));
- // sshd.setShellFactory(new ProcessShellFactory(new String[] { "/bin/sh", "-i",
- // "-l" }));
- String[] shellCommand = OS.LOCAL.getDefaultShellCommand();
- sshd.setShellFactory(new ProcessShellFactory(shellCommand));
- sshd.setCommandFactory(new ScpCommandFactory());
- sshd.start();
- } catch (Exception e) {
- throw new RuntimeException("Cannot start SSH server on port " + port, e);
- }
- }
-
- public void destroy() {
- try {
- sshd.stop();
- } catch (IOException e) {
- throw new RuntimeException("Cannot stop SSH server on port " + port, e);
- }
- }
-
- public Integer getPort() {
- return port;
- }
-
- public void setPort(Integer port) {
- this.port = port;
- }
-
- public Path getHostKeyPath() {
- return hostKeyPath;
- }
-
- public void setHostKeyPath(Path hostKeyPath) {
- this.hostKeyPath = hostKeyPath;
- }
-
- public static void main(String[] args) {
- int port = 2222;
- Path hostKeyPath = Paths.get("hostkey.ser");
- try {
- if (args.length > 0)
- port = Integer.parseInt(args[0]);
- if (args.length > 1)
- hostKeyPath = Paths.get(args[1]);
- } catch (Exception e1) {
- printUsage();
- }
-
- BasicSshServer sshServer = new BasicSshServer(port, hostKeyPath);
- sshServer.init();
- Runtime.getRuntime().addShutdownHook(new Thread("Shutdown SSH server") {
-
- @Override
- public void run() {
- sshServer.destroy();
- }
- });
- try {
- synchronized (sshServer) {
- sshServer.wait();
- }
- } catch (InterruptedException e) {
- sshServer.destroy();
- }
-
- }
-
- public static void printUsage() {
- System.out.println("java " + BasicSshServer.class.getName() + " [port] [server key path]");
- }
-
-}
+++ /dev/null
-package org.argeo.ssh;
-
-import java.io.IOException;
-import java.net.URI;
-import java.nio.file.FileSystem;
-import java.nio.file.Path;
-
-import org.apache.sshd.client.subsystem.sftp.fs.SftpFileSystem;
-
-/** Create an SFTP {@link FileSystem}. */
-public class Sftp extends AbstractSsh {
- private URI uri;
-
- private SftpFileSystem fileSystem;
-
- public Sftp(String username, String host, int port) {
- this(AbstractSsh.toUri(username, host, port));
- }
-
- public Sftp(URI uri) {
- this.uri = uri;
- openSession(uri);
- }
-
- public FileSystem getFileSystem() {
- if (fileSystem == null) {
- try {
- authenticate();
- fileSystem = getSftpFileSystemProvider().newFileSystem(getSession());
- } catch (IOException e) {
- throw new IllegalStateException(e);
- }
- }
- return fileSystem;
- }
-
- public Path getBasePath() {
- String p = uri.getPath() != null ? uri.getPath() : "/";
- return getFileSystem().getPath(p);
- }
-
-}
+++ /dev/null
-package org.argeo.ssh;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.DefaultParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-
-/** Create an SSH shell. */
-public class Ssh extends AbstractSsh {
- private final URI uri;
-
- public Ssh(String username, String host, int port) {
- this(AbstractSsh.toUri(username, host, port));
- }
-
- public Ssh(URI uri) {
- this.uri = uri;
- openSession(uri);
- }
-
- public static void main(String[] args) {
- Options options = getOptions();
- CommandLineParser parser = new DefaultParser();
- try {
- CommandLine line = parser.parse(options, args);
- List<String> remaining = line.getArgList();
- if (remaining.size() == 0) {
- System.err.println("There must be at least one argument");
- printHelp(options);
- System.exit(1);
- }
- URI uri = new URI("ssh://" + remaining.get(0));
- List<String> command = new ArrayList<>();
- if (remaining.size() > 1) {
- for (int i = 1; i < remaining.size(); i++) {
- command.add(remaining.get(i));
- }
- }
-
- // auth
- Ssh ssh = new Ssh(uri);
- ssh.authenticate();
-
- if (command.size() == 0) {// shell
- AbstractSsh.openShell(ssh.getSession());
- } else {// execute command
-
- }
- ssh.closeSession();
- } catch (Exception exp) {
- exp.printStackTrace();
- printHelp(options);
- System.exit(1);
- } finally {
-
- }
- }
-
- public URI getUri() {
- return uri;
- }
-
- public static Options getOptions() {
- Options options = new Options();
-// options.addOption("p", true, "port");
- options.addOption(Option.builder("p").hasArg().argName("port").desc("port of the SSH server").build());
-
- return options;
- }
-
- public static void printHelp(Options options) {
- HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp("ssh [username@]hostname", options, true);
- }
-}
+++ /dev/null
-package org.argeo.ssh;
-
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.GeneralSecurityException;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.interfaces.RSAPrivateCrtKey;
-import java.security.spec.RSAPublicKeySpec;
-
-import org.apache.sshd.common.config.keys.KeyUtils;
-import org.apache.sshd.common.config.keys.PublicKeyEntry;
-import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
-import org.bouncycastle.openssl.PEMKeyPair;
-import org.bouncycastle.openssl.PEMParser;
-import org.bouncycastle.openssl.PKCS8Generator;
-import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
-import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
-import org.bouncycastle.openssl.jcajce.JcaPKCS8Generator;
-import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
-import org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder;
-import org.bouncycastle.operator.InputDecryptorProvider;
-import org.bouncycastle.operator.OutputEncryptor;
-import org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
-
-@SuppressWarnings("restriction")
-public class SshKeyPair {
- public final static String RSA_KEY_TYPE = "ssh-rsa";
-
- private PublicKey publicKey;
- private PrivateKey privateKey;
- private KeyPair keyPair;
-
- public SshKeyPair(KeyPair keyPair) {
- super();
- this.publicKey = keyPair.getPublic();
- this.privateKey = keyPair.getPrivate();
- this.keyPair = keyPair;
- }
-
- public SshKeyPair(PublicKey publicKey, PrivateKey privateKey) {
- super();
- this.publicKey = publicKey;
- this.privateKey = privateKey;
- this.keyPair = new KeyPair(publicKey, privateKey);
- }
-
- public KeyPair asKeyPair() {
- return keyPair;
- }
-
- public String getPublicKeyAsOpenSshString() {
- return PublicKeyEntry.toString(publicKey);
- }
-
- public String getPrivateKeyAsPemString(char[] password) {
- try {
- Object obj;
-
- if (password != null) {
- JceOpenSSLPKCS8EncryptorBuilder encryptorBuilder = new JceOpenSSLPKCS8EncryptorBuilder(
- PKCS8Generator.PBE_SHA1_3DES);
- encryptorBuilder.setPasssword(password);
- OutputEncryptor oe = encryptorBuilder.build();
- JcaPKCS8Generator gen = new JcaPKCS8Generator(privateKey, oe);
- obj = gen.generate();
- } else {
- obj = privateKey;
- }
-
- StringWriter sw = new StringWriter();
- JcaPEMWriter pemWrt = new JcaPEMWriter(sw);
- pemWrt.writeObject(obj);
- pemWrt.close();
- return sw.toString();
- } catch (Exception e) {
- throw new RuntimeException("Cannot convert private key", e);
- }
- }
-
- public static SshKeyPair loadOrGenerate(Path privateKeyPath, int size, char[] password) {
- try {
- SshKeyPair sshKeyPair;
- if (Files.exists(privateKeyPath)) {
-// String privateKeyStr = new String(Files.readAllBytes(privateKeyPath), StandardCharsets.US_ASCII);
- sshKeyPair = load(
- new InputStreamReader(Files.newInputStream(privateKeyPath), StandardCharsets.US_ASCII),
- password);
- // TOD make sure public key is consistemt
- } else {
- sshKeyPair = generate(size);
- Files.write(privateKeyPath,
- sshKeyPair.getPrivateKeyAsPemString(password).getBytes(StandardCharsets.US_ASCII));
- Path publicKeyPath = privateKeyPath.resolveSibling(privateKeyPath.getFileName() + ".pub");
- Files.write(publicKeyPath,
- sshKeyPair.getPublicKeyAsOpenSshString().getBytes(StandardCharsets.US_ASCII));
- }
- return sshKeyPair;
- } catch (IOException e) {
- throw new RuntimeException("Cannot read or write private key " + privateKeyPath, e);
- }
- }
-
- public static SshKeyPair generate(int size) {
- return generate(RSA_KEY_TYPE, size);
- }
-
- public static SshKeyPair generate(String keyType, int size) {
- try {
- KeyPair keyPair = KeyUtils.generateKeyPair(keyType, size);
- PublicKey publicKey = keyPair.getPublic();
- PrivateKey privateKey = keyPair.getPrivate();
- return new SshKeyPair(publicKey, privateKey);
- } catch (GeneralSecurityException e) {
- throw new RuntimeException("Cannot generate SSH key", e);
- }
- }
-
- public static SshKeyPair load(Reader reader, char[] password) {
- try (PEMParser pemParser = new PEMParser(reader)) {
- Object object = pemParser.readObject();
- JcaPEMKeyConverter converter = new JcaPEMKeyConverter();// .setProvider("BC");
- KeyPair kp;
- if (object instanceof PKCS8EncryptedPrivateKeyInfo) {
- // Encrypted key - we will use provided password
- PKCS8EncryptedPrivateKeyInfo ckp = (PKCS8EncryptedPrivateKeyInfo) object;
-// PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password);
- InputDecryptorProvider inputDecryptorProvider = new JceOpenSSLPKCS8DecryptorProviderBuilder()
- .build(password);
- PrivateKeyInfo pkInfo = ckp.decryptPrivateKeyInfo(inputDecryptorProvider);
- PrivateKey privateKey = converter.getPrivateKey(pkInfo);
-
- // generate public key
- RSAPrivateCrtKey privk = (RSAPrivateCrtKey) privateKey;
- RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(privk.getModulus(),
- privk.getPublicExponent());
- KeyFactory keyFactory = KeyFactory.getInstance("RSA");
- PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
-
- kp = new KeyPair(publicKey, privateKey);
- } else {
- // Unencrypted key - no password needed
-// PKCS8EncryptedPrivateKeyInfo ukp = (PKCS8EncryptedPrivateKeyInfo) object;
- PEMKeyPair pemKp = (PEMKeyPair) object;
- kp = converter.getKeyPair(pemKp);
- }
- return new SshKeyPair(kp);
- } catch (Exception e) {
- throw new RuntimeException("Cannot load private key", e);
- }
- }
-
- public static void main(String args[]) {
- Path privateKeyPath = Paths.get(System.getProperty("user.dir") + "/id_rsa");
- SshKeyPair skp = SshKeyPair.loadOrGenerate(privateKeyPath, 1024, null);
- System.out.println("Public:\n" + skp.getPublicKeyAsOpenSshString());
- System.out.println("Private (plain):\n" + skp.getPrivateKeyAsPemString(null));
- System.out.println("Private (encrypted):\n" + skp.getPrivateKeyAsPemString("demo".toCharArray()));
-
- StringReader reader = new StringReader(skp.getPrivateKeyAsPemString(null));
- skp = SshKeyPair.load(reader, null);
- System.out.println("Public:\n" + skp.getPublicKeyAsOpenSshString());
- System.out.println("Private (plain):\n" + skp.getPrivateKeyAsPemString(null));
- System.out.println("Private (encrypted):\n" + skp.getPrivateKeyAsPemString("demo".toCharArray()));
-
- reader = new StringReader(skp.getPrivateKeyAsPemString("demo".toCharArray()));
- skp = SshKeyPair.load(reader, "demo".toCharArray());
- System.out.println("Public:\n" + skp.getPublicKeyAsOpenSshString());
- System.out.println("Private (plain):\n" + skp.getPrivateKeyAsPemString(null));
- System.out.println("Private (encrypted):\n" + skp.getPrivateKeyAsPemString("demo".toCharArray()));
- }
-
-}
+++ /dev/null
-/** SSH support. */
-package org.argeo.ssh;
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+++ /dev/null
-/bin/
-/target/
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>org.argeo.ext.equinox.jetty</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.ManifestBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.SchemaBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.pde.PluginNature</nature>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
+++ /dev/null
-/MANIFEST.MF
+++ /dev/null
-Fragment-Host: org.eclipse.equinox.http.jetty
-
-Import-Package: org.eclipse.jetty.websocket.jsr356,\
-org.eclipse.jetty.websocket.api,\
-org.eclipse.jetty.websocket.common,\
-org.osgi.service.http,\
-*
\ No newline at end of file
+++ /dev/null
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
- .
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.argeo.commons</groupId>
- <artifactId>argeo-commons</artifactId>
- <version>2.1.89-SNAPSHOT</version>
- <relativePath>..</relativePath>
- </parent>
- <artifactId>org.argeo.ext.equinox.jetty</artifactId>
- <name>Extension of Equinox Jetty Integration</name>
- <dependencies>
- <dependency>
- <groupId>org.argeo.commons</groupId>
- <artifactId>org.argeo.cms</artifactId>
- <version>2.1.89-SNAPSHOT</version>
- </dependency>
- </dependencies>
-</project>
\ No newline at end of file
+++ /dev/null
-package org.argeo.equinox.jetty;
-
-import java.util.Dictionary;
-
-import javax.servlet.ServletContext;
-import javax.websocket.DeploymentException;
-
-import org.eclipse.equinox.http.jetty.JettyCustomizer;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
-import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
-import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer.Configurator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-
-/** Customises the Jetty HTTP server. */
-public class CmsJettyCustomizer extends JettyCustomizer {
- private BundleContext bc = FrameworkUtil.getBundle(CmsJettyCustomizer.class).getBundleContext();
-
- public final static String WEBSOCKET_ENABLED = "websocket.enabled";
-
- @Override
- public Object customizeContext(Object context, Dictionary<String, ?> settings) {
- // WebSocket
- Object webSocketEnabled = settings.get(WEBSOCKET_ENABLED);
- if (webSocketEnabled != null && webSocketEnabled.toString().equals("true")) {
- ServletContextHandler servletContextHandler = (ServletContextHandler) context;
- WebSocketServerContainerInitializer.configure(servletContextHandler, new Configurator() {
-
- @Override
- public void accept(ServletContext servletContext, ServerContainer serverContainer)
- throws DeploymentException {
- bc.registerService(javax.websocket.server.ServerContainer.class, serverContainer, null);
- }
- });
- }
- return super.customizeContext(context, settings);
-
- }
-}
+++ /dev/null
-/** Equinox Jetty extensions. */
-package org.argeo.equinox.jetty;
\ No newline at end of file
output.. = bin/
bin.includes = META-INF/,\
.
-additional.bundles = org.apache.sshd.common,\
- org.slf4j.log4j12,\
- org.slf4j.api,\
- org.apache.sshd.core
+additional.bundles = org.slf4j.log4j12,\
+ org.slf4j.api
+++ /dev/null
-package org.argeo.maintenance.backup.vfs;
-
-import org.apache.commons.vfs2.FileObject;
-import org.apache.commons.vfs2.FileSystemManager;
-import org.apache.commons.vfs2.FileSystemOptions;
-import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;
-import org.argeo.maintenance.MaintenanceException;
-
-/**
- * Simplify atomic backups implementation, especially by managing VFS.
- */
-public abstract class AbstractAtomicBackup implements AtomicBackup {
- private String name;
- private String compression = "bz2";
-
- protected abstract void writeBackup(FileObject targetFo);
-
- public AbstractAtomicBackup() {
- }
-
- public AbstractAtomicBackup(String name) {
- this.name = name;
- }
-
- public void init() {
- if (name == null)
- throw new MaintenanceException("Atomic backup name must be set");
- }
-
- public void destroy() {
-
- }
-
- @Override
- public String backup(FileSystemManager fileSystemManager,
- String backupsBase, BackupContext backupContext,
- FileSystemOptions opts) {
- if (name == null)
- throw new MaintenanceException("Atomic backup name must be set");
-
- FileObject targetFo = null;
- try {
- if (backupsBase.startsWith("sftp:"))
- SftpFileSystemConfigBuilder.getInstance()
- .setStrictHostKeyChecking(opts, "no");
- if (compression == null || compression.equals("none"))
- targetFo = fileSystemManager.resolveFile(backupsBase + '/'
- + backupContext.getRelativeFolder() + '/' + name, opts);
- else if (compression.equals("bz2"))
- targetFo = fileSystemManager.resolveFile("bz2:" + backupsBase
- + '/' + backupContext.getRelativeFolder() + '/' + name
- + ".bz2" + "!" + name, opts);
- else if (compression.equals("gz"))
- targetFo = fileSystemManager.resolveFile("gz:" + backupsBase
- + '/' + backupContext.getRelativeFolder() + '/' + name
- + ".gz" + "!" + name, opts);
- else
- throw new MaintenanceException("Unsupported compression "
- + compression);
-
- writeBackup(targetFo);
-
- return targetFo.toString();
- } catch (Exception e) {
- throw new MaintenanceException("Cannot backup " + name + " to "
- + targetFo, e);
- } finally {
- BackupUtils.closeFOQuietly(targetFo);
- }
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public void setCompression(String compression) {
- this.compression = compression;
- }
-}
+++ /dev/null
-package org.argeo.maintenance.backup.vfs;
-
-import org.apache.commons.vfs2.FileSystemManager;
-import org.apache.commons.vfs2.FileSystemOptions;
-
-/** Performs the backup of a single component, typically a database dump */
-public interface AtomicBackup {
- /** Name identifiying this backup */
- public String getName();
-
- /**
- * Retrieves the data of the component in a format that allows to restore
- * the component
- *
- * @param backupContext
- * the context of this backup
- * @return the VFS URI of the generated file or directory
- */
- public String backup(FileSystemManager fileSystemManager,
- String backupsBase, BackupContext backupContext,
- FileSystemOptions opts);
-}
+++ /dev/null
-package org.argeo.maintenance.backup.vfs;
-
-import java.text.DateFormat;
-import java.util.Date;
-
-/**
- * Transient information of a given backup, centralizing common information such
- * as timestamp and location.
- */
-public interface BackupContext {
- /** Backup date */
- public Date getTimestamp();
-
- /** Formatted backup date */
- public String getTimestampAsString();
-
- /** System name */
- public String getSystemName();
-
- /** Local base */
- public String getRelativeFolder();
-
- /** Date format */
- public DateFormat getDateFormat();
-}
+++ /dev/null
-package org.argeo.maintenance.backup.vfs;
-
-import org.apache.commons.vfs2.FileSystemException;
-import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
-import org.apache.commons.vfs2.provider.bzip2.Bzip2FileProvider;
-import org.apache.commons.vfs2.provider.ftp.FtpFileProvider;
-import org.apache.commons.vfs2.provider.gzip.GzipFileProvider;
-import org.apache.commons.vfs2.provider.local.DefaultLocalFileProvider;
-import org.apache.commons.vfs2.provider.ram.RamFileProvider;
-import org.apache.commons.vfs2.provider.sftp.SftpFileProvider;
-import org.apache.commons.vfs2.provider.url.UrlFileProvider;
-import org.argeo.maintenance.MaintenanceException;
-
-/**
- * Programatically configured VFS file system manager which can be declared as a
- * bean and associated with a life cycle (methods
- * {@link DefaultFileSystemManager#init()} and
- * {@link DefaultFileSystemManager#close()}). Supports bz2, file, ram, gzip,
- * ftp, sftp
- */
-public class BackupFileSystemManager extends DefaultFileSystemManager {
-
- public BackupFileSystemManager() {
- super();
- try {
- addProvider("file", new DefaultLocalFileProvider());
- addProvider("bz2", new Bzip2FileProvider());
- addProvider("ftp", new FtpFileProvider());
- addProvider("sftp", new SftpFileProvider());
- addProvider("gzip", new GzipFileProvider());
- addProvider("ram", new RamFileProvider());
- setDefaultProvider(new UrlFileProvider());
- } catch (FileSystemException e) {
- throw new MaintenanceException("Cannot configure backup file provider", e);
- }
- }
-}
+++ /dev/null
-package org.argeo.maintenance.backup.vfs;
-
-import java.text.DateFormat;
-
-import org.apache.commons.vfs2.FileSystemManager;
-import org.apache.commons.vfs2.FileSystemOptions;
-
-/** Purges previous backups */
-public interface BackupPurge {
- /**
- * Purge the backups identified by these arguments. Although these are the
- * same fields as a {@link BackupContext} we don't pass it as argument since
- * we want to use this interface to purge remote backups as well (that is,
- * with a different base), or outside the scope of a running backup.
- */
- public void purge(FileSystemManager fileSystemManager, String base,
- String name, DateFormat dateFormat, FileSystemOptions opts);
-}
+++ /dev/null
-package org.argeo.maintenance.backup.vfs;
-
-import org.apache.commons.vfs2.FileObject;
-
-/** Backup utilities */
-public class BackupUtils {
- /** Close a file object quietly even if it is null or throws an exception. */
- public static void closeFOQuietly(FileObject fo) {
- if (fo != null) {
- try {
- fo.close();
- } catch (Exception e) {
- // silent
- }
- }
- }
-
- /** Prevents instantiation */
- private BackupUtils() {
- }
-}
+++ /dev/null
-package org.argeo.maintenance.backup.vfs;
-
-import org.apache.commons.vfs2.FileObject;
-
-/** Backups a MySQL database using mysqldump. */
-public class MySqlBackup extends OsCallBackup {
- private String mysqldumpLocation = "/usr/bin/mysqldump";
-
- private String dbUser;
- private String dbPassword;
- private String dbName;
-
- public MySqlBackup() {
- }
-
- public MySqlBackup(String dbUser, String dbPassword, String dbName) {
- this.dbUser = dbUser;
- this.dbPassword = dbPassword;
- this.dbName = dbName;
- init();
- }
-
- @Override
- public void init() {
- if (getName() == null)
- setName(dbName + ".mysql");
- super.init();
- }
-
- @Override
- public void writeBackup(FileObject targetFo) {
- if (getCommand() == null)
- setCommand(mysqldumpLocation
- + " --lock-tables --add-locks --add-drop-table"
- + " -u ${dbUser} --password=${dbPassword} --databases ${dbName}");
- getVariables().put("dbUser", dbUser);
- getVariables().put("dbPassword", dbPassword);
- getVariables().put("dbName", dbName);
-
- super.writeBackup(targetFo);
- }
-
- public void setDbUser(String dbUser) {
- this.dbUser = dbUser;
- }
-
- public void setDbPassword(String dbPassword) {
- this.dbPassword = dbPassword;
- }
-
- public void setDbName(String dbName) {
- this.dbName = dbName;
- }
-
- public void setMysqldumpLocation(String mysqldumpLocation) {
- this.mysqldumpLocation = mysqldumpLocation;
- }
-
-}
+++ /dev/null
-package org.argeo.maintenance.backup.vfs;
-
-import org.apache.commons.vfs2.FileObject;
-import org.argeo.maintenance.MaintenanceException;
-
-/** Backups an OpenLDAP server using slapcat */
-public class OpenLdapBackup extends OsCallBackup {
- private String slapcatLocation = "/usr/sbin/slapcat";
- private String slapdConfLocation = "/etc/openldap/slapd.conf";
- private String baseDn;
-
- public OpenLdapBackup() {
- super();
- }
-
- public OpenLdapBackup(String baseDn) {
- super();
- this.baseDn = baseDn;
- }
-
- @Override
- public void writeBackup(FileObject targetFo) {
- if (baseDn == null)
- throw new MaintenanceException("Base DN must be set");
-
- if (getCommand() == null)
- setCommand(slapcatLocation
- + " -f ${slapdConfLocation} -b '${baseDn}'");
- getVariables().put("slapdConfLocation", slapdConfLocation);
- getVariables().put("baseDn", baseDn);
-
- super.writeBackup(targetFo);
- }
-
- public void setSlapcatLocation(String slapcatLocation) {
- this.slapcatLocation = slapcatLocation;
- }
-
- public void setSlapdConfLocation(String slapdConfLocation) {
- this.slapdConfLocation = slapdConfLocation;
- }
-
- public void setBaseDn(String baseDn) {
- this.baseDn = baseDn;
- }
-
-}
+++ /dev/null
-package org.argeo.maintenance.backup.vfs;
-
-import java.io.ByteArrayOutputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.exec.CommandLine;
-import org.apache.commons.exec.DefaultExecutor;
-import org.apache.commons.exec.ExecuteException;
-import org.apache.commons.exec.ExecuteStreamHandler;
-import org.apache.commons.exec.Executor;
-import org.apache.commons.exec.PumpStreamHandler;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.commons.vfs2.FileContent;
-import org.apache.commons.vfs2.FileObject;
-import org.argeo.maintenance.MaintenanceException;
-
-/**
- * Runs an OS command and save its standard output as a file. Typically used for
- * MySQL or OpenLDAP dumps.
- */
-public class OsCallBackup extends AbstractAtomicBackup {
- private final static Log log = LogFactory.getLog(OsCallBackup.class);
-
- private String command;
- private Map<String, String> variables = new HashMap<String, String>();
- private Executor executor = new DefaultExecutor();
-
- private Map<String, String> environment = new HashMap<String, String>();
-
- /** Name of the sudo user, root if "", not sudo if null */
- private String sudo = null;
-
- public OsCallBackup() {
- }
-
- public OsCallBackup(String name) {
- super(name);
- }
-
- public OsCallBackup(String name, String command) {
- super(name);
- this.command = command;
- }
-
- @Override
- public void writeBackup(FileObject targetFo) {
- String commandToUse = command;
-
- // sudo
- if (sudo != null) {
- if (sudo.equals(""))
- commandToUse = "sudo " + commandToUse;
- else
- commandToUse = "sudo -u " + sudo + " " + commandToUse;
- }
-
- CommandLine commandLine = CommandLine.parse(commandToUse, variables);
- ByteArrayOutputStream errBos = new ByteArrayOutputStream();
- if (log.isTraceEnabled())
- log.trace(commandLine.toString());
-
- try {
- // stdout
- FileContent targetContent = targetFo.getContent();
- // stderr
- ExecuteStreamHandler streamHandler = new PumpStreamHandler(targetContent.getOutputStream(), errBos);
- executor.setStreamHandler(streamHandler);
- executor.execute(commandLine, environment);
- } catch (ExecuteException e) {
- byte[] err = errBos.toByteArray();
- String errStr = new String(err);
- throw new MaintenanceException("Process " + commandLine + " failed (" + e.getExitValue() + "): " + errStr, e);
- } catch (Exception e) {
- byte[] err = errBos.toByteArray();
- String errStr = new String(err);
- throw new MaintenanceException("Process " + commandLine + " failed: " + errStr, e);
- } finally {
- IOUtils.closeQuietly(errBos);
- }
- }
-
- public void setCommand(String command) {
- this.command = command;
- }
-
- protected String getCommand() {
- return command;
- }
-
- /**
- * A reference to the environment variables that will be passed to the
- * process. Empty by default.
- */
- protected Map<String, String> getEnvironment() {
- return environment;
- }
-
- protected Map<String, String> getVariables() {
- return variables;
- }
-
- public void setVariables(Map<String, String> variables) {
- this.variables = variables;
- }
-
- public void setExecutor(Executor executor) {
- this.executor = executor;
- }
-
- public void setSudo(String sudo) {
- this.sudo = sudo;
- }
-
-}
+++ /dev/null
-package org.argeo.maintenance.backup.vfs;
-
-import org.apache.commons.vfs2.FileObject;
-
-/** Backups a PostgreSQL database using pg_dump. */
-public class PostgreSqlBackup extends OsCallBackup {
- /**
- * PostgreSQL password environment variable (see
- * http://stackoverflow.com/questions
- * /2893954/how-to-pass-in-password-to-pg-dump)
- */
- protected final static String PGPASSWORD = "PGPASSWORD";
-
- private String pgDumpLocation = "/usr/bin/pg_dump";
-
- private String dbUser;
- private String dbPassword;
- private String dbName;
-
- public PostgreSqlBackup() {
- super();
- }
-
- public PostgreSqlBackup(String dbUser, String dbPassword, String dbName) {
- this.dbUser = dbUser;
- this.dbPassword = dbPassword;
- this.dbName = dbName;
- init();
- }
-
- @Override
- public void init() {
- // disable compression since pg_dump is used with -Fc option
- setCompression(null);
-
- if (getName() == null)
- setName(dbName + ".pgdump");
- super.init();
- }
-
- @Override
- public void writeBackup(FileObject targetFo) {
- if (getCommand() == null) {
- getEnvironment().put(PGPASSWORD, dbPassword);
- setCommand(pgDumpLocation + " -Fc" + " -U ${dbUser} ${dbName}");
- }
- getVariables().put("dbUser", dbUser);
- getVariables().put("dbPassword", dbPassword);
- getVariables().put("dbName", dbName);
-
- super.writeBackup(targetFo);
- }
-
- public void setDbUser(String dbUser) {
- this.dbUser = dbUser;
- }
-
- public void setDbPassword(String dbPassword) {
- this.dbPassword = dbPassword;
- }
-
- public void setDbName(String dbName) {
- this.dbName = dbName;
- }
-
- public void setPgDumpLocation(String mysqldumpLocation) {
- this.pgDumpLocation = mysqldumpLocation;
- }
-
-}
+++ /dev/null
-package org.argeo.maintenance.backup.vfs;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import org.apache.commons.vfs2.FileSystemManager;
-
-/** Simple implementation of a backup context */
-public class SimpleBackupContext implements BackupContext {
- private DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmm");
- private final Date timestamp;
- private final String name;
-
- private final FileSystemManager fileSystemManager;
-
- public SimpleBackupContext(FileSystemManager fileSystemManager,
- String backupsBase, String name) {
- this.name = name;
- this.timestamp = new Date();
- this.fileSystemManager = fileSystemManager;
- }
-
- public Date getTimestamp() {
- return timestamp;
- }
-
- public String getTimestampAsString() {
- return dateFormat.format(timestamp);
- }
-
- public String getSystemName() {
- return name;
- }
-
- public String getRelativeFolder() {
- return name + '/' + getTimestampAsString();
- }
-
- public DateFormat getDateFormat() {
- return dateFormat;
- }
-
- public FileSystemManager getFileSystemManager() {
- return fileSystemManager;
- }
-
-}
+++ /dev/null
-package org.argeo.maintenance.backup.vfs;
-
-import java.text.DateFormat;
-import java.time.Period;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.util.Date;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.commons.vfs2.FileObject;
-import org.apache.commons.vfs2.FileSystemManager;
-import org.apache.commons.vfs2.FileSystemOptions;
-import org.apache.commons.vfs2.Selectors;
-import org.argeo.maintenance.MaintenanceException;
-
-/** Simple backup purge which keeps backups only for a given number of days */
-public class SimpleBackupPurge implements BackupPurge {
- private final static Log log = LogFactory.getLog(SimpleBackupPurge.class);
-
- private Integer daysKept = 30;
-
- @Override
- public void purge(FileSystemManager fileSystemManager, String base, String name, DateFormat dateFormat,
- FileSystemOptions opts) {
- try {
- ZonedDateTime nowDt = ZonedDateTime.now();
- FileObject baseFo = fileSystemManager.resolveFile(base + '/' + name, opts);
-
- SortedMap<ZonedDateTime, FileObject> toDelete = new TreeMap<ZonedDateTime, FileObject>();
- int backupCount = 0;
-
- // make sure base dir exists
- baseFo.createFolder();
-
- // scan backups and list those which should be deleted
- for (FileObject backupFo : baseFo.getChildren()) {
- String backupName = backupFo.getName().getBaseName();
- Date backupDate = dateFormat.parse(backupName);
- backupCount++;
- ZonedDateTime backupDt = ZonedDateTime.ofInstant(backupDate.toInstant(), ZoneId.systemDefault());
- Period sinceThen = Period.between(backupDt.toLocalDate(), nowDt.toLocalDate());
- // new Period(backupDt, nowDt);
- int days = sinceThen.getDays();
- // int days = sinceThen.getMinutes();
- if (days > daysKept) {
- toDelete.put(backupDt, backupFo);
- }
- }
-
- if (toDelete.size() != 0 && toDelete.size() == backupCount) {
- // all backups would be deleted
- // but we want to keep at least one
- ZonedDateTime lastBackupDt = toDelete.firstKey();
- FileObject keptFo = toDelete.remove(lastBackupDt);
- log.warn("Backup " + keptFo + " kept although it is older than " + daysKept + " days.");
- }
-
- // delete old backups
- for (FileObject backupFo : toDelete.values()) {
- backupFo.delete(Selectors.SELECT_ALL);
- if (log.isDebugEnabled())
- log.debug("Deleted backup " + backupFo);
- }
- } catch (Exception e) {
- throw new MaintenanceException("Could not purge previous backups", e);
- }
-
- }
-
-}
+++ /dev/null
-package org.argeo.maintenance.backup.vfs;
-
-import java.io.File;
-
-import org.apache.commons.vfs2.FileObject;
-
-/** Backups a Subversion repository using svnadmin. */
-public class SvnBackup extends OsCallBackup {
- private String svnadminLocation = "/usr/bin/svnadmin";
-
- private String repoLocation;
- private String repoName;
-
- public SvnBackup() {
- }
-
- public SvnBackup(String repoLocation) {
- this.repoLocation = repoLocation;
- init();
- }
-
- @Override
- public void init() {
- // use directory as repo name
- if (repoName == null)
- repoName = new File(repoLocation).getName();
-
- if (getName() == null)
- setName(repoName + ".svndump");
- super.init();
- }
-
- @Override
- public void writeBackup(FileObject targetFo) {
- if (getCommand() == null) {
- setCommand(svnadminLocation + " dump " + " ${repoLocation}");
- }
- getVariables().put("repoLocation", repoLocation);
-
- super.writeBackup(targetFo);
- }
-
- public void setRepoLocation(String repoLocation) {
- this.repoLocation = repoLocation;
- }
-
- public void setRepoName(String repoName) {
- this.repoName = repoName;
- }
-
- public void setSvnadminLocation(String mysqldumpLocation) {
- this.svnadminLocation = mysqldumpLocation;
- }
-
-}
+++ /dev/null
-package org.argeo.maintenance.backup.vfs;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.commons.vfs2.FileObject;
-import org.apache.commons.vfs2.FileSystemException;
-import org.apache.commons.vfs2.FileSystemManager;
-import org.apache.commons.vfs2.FileSystemOptions;
-import org.apache.commons.vfs2.Selectors;
-import org.apache.commons.vfs2.UserAuthenticator;
-import org.apache.commons.vfs2.impl.DefaultFileSystemConfigBuilder;
-import org.argeo.maintenance.MaintenanceException;
-import org.argeo.util.LangUtils;
-
-/**
- * Combines multiple backups and transfer them to a remote location. Purges
- * remote and local data based on certain criteria.
- */
-public class SystemBackup implements Runnable {
- private final static Log log = LogFactory.getLog(SystemBackup.class);
-
- private FileSystemManager fileSystemManager;
- private UserAuthenticator userAuthenticator = null;
-
- private String backupsBase;
- private String systemName;
-
- private List<AtomicBackup> atomicBackups = new ArrayList<AtomicBackup>();
- private BackupPurge backupPurge = new SimpleBackupPurge();
-
- private Map<String, UserAuthenticator> remoteBases = new HashMap<String, UserAuthenticator>();
-
- @Override
- public void run() {
- if (atomicBackups.size() == 0)
- throw new MaintenanceException("No atomic backup listed");
- List<String> failures = new ArrayList<String>();
-
- SimpleBackupContext backupContext = new SimpleBackupContext(fileSystemManager, backupsBase, systemName);
-
- // purge older backups
- FileSystemOptions opts = new FileSystemOptions();
- try {
- DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, userAuthenticator);
- } catch (FileSystemException e) {
- throw new MaintenanceException("Cannot create authentication", e);
- }
-
- try {
-
- backupPurge.purge(fileSystemManager, backupsBase, systemName, backupContext.getDateFormat(), opts);
- } catch (Exception e) {
- failures.add("Purge " + backupsBase + " failed: " + e.getMessage());
- log.error("Purge of " + backupsBase + " failed", e);
- }
-
- // perform backup
- for (AtomicBackup atomickBackup : atomicBackups) {
- try {
- String target = atomickBackup.backup(fileSystemManager, backupsBase, backupContext, opts);
- if (log.isDebugEnabled())
- log.debug("Performed backup " + target);
- } catch (Exception e) {
- String msg = "Atomic backup " + atomickBackup.getName() + " failed: "
- + LangUtils.chainCausesMessages(e);
- failures.add(msg);
- log.error(msg);
- if (log.isTraceEnabled())
- log.trace("Stacktrace of atomic backup " + atomickBackup.getName() + " failure.", e);
- }
- }
-
- // dispatch to remote
- for (String remoteBase : remoteBases.keySet()) {
- FileObject localBaseFo = null;
- FileObject remoteBaseFo = null;
- UserAuthenticator auth = remoteBases.get(remoteBase);
-
- // authentication
- FileSystemOptions remoteOpts = new FileSystemOptions();
- try {
- DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(remoteOpts, auth);
- backupPurge.purge(fileSystemManager, remoteBase, systemName, backupContext.getDateFormat(), remoteOpts);
- } catch (Exception e) {
- failures.add("Purge " + remoteBase + " failed: " + e.getMessage());
- log.error("Cannot purge " + remoteBase, e);
- }
-
- try {
- localBaseFo = fileSystemManager.resolveFile(backupsBase + '/' + backupContext.getRelativeFolder(),
- opts);
- remoteBaseFo = fileSystemManager.resolveFile(remoteBase + '/' + backupContext.getRelativeFolder(),
- remoteOpts);
- remoteBaseFo.copyFrom(localBaseFo, Selectors.SELECT_ALL);
- if (log.isDebugEnabled())
- log.debug("Copied backup to " + remoteBaseFo + " from " + localBaseFo);
- // }
- } catch (Exception e) {
- failures.add("Dispatch to " + remoteBase + " failed: " + e.getMessage());
- log.error("Cannot dispatch backups from " + backupContext.getRelativeFolder() + " to " + remoteBase, e);
- }
- BackupUtils.closeFOQuietly(localBaseFo);
- BackupUtils.closeFOQuietly(remoteBaseFo);
- }
-
- int failureCount = 0;
- if (failures.size() > 0) {
- StringBuffer buf = new StringBuffer();
- for (String failure : failures) {
- buf.append('\n').append(failureCount).append(" - ").append(failure);
- failureCount++;
- }
- throw new MaintenanceException(failureCount + " error(s) when running the backup,"
- + " check the logs and the backups as soon as possible." + buf);
- }
- }
-
- public void setFileSystemManager(FileSystemManager fileSystemManager) {
- this.fileSystemManager = fileSystemManager;
- }
-
- public void setBackupsBase(String backupsBase) {
- this.backupsBase = backupsBase;
- }
-
- public void setSystemName(String name) {
- this.systemName = name;
- }
-
- public void setAtomicBackups(List<AtomicBackup> atomicBackups) {
- this.atomicBackups = atomicBackups;
- }
-
- public void setBackupPurge(BackupPurge backupPurge) {
- this.backupPurge = backupPurge;
- }
-
- public void setUserAuthenticator(UserAuthenticator userAuthenticator) {
- this.userAuthenticator = userAuthenticator;
- }
-
- public void setRemoteBases(Map<String, UserAuthenticator> remoteBases) {
- this.remoteBases = remoteBases;
- }
-
- // public static void main(String args[]) {
- // while (true) {
- // try {
- // StandardFileSystemManager fsm = new StandardFileSystemManager();
- // fsm.init();
- //
- // SystemBackup systemBackup = new SystemBackup();
- // systemBackup.setSystemName("mySystem");
- // systemBackup
- // .setBackupsBase("/home/mbaudier/dev/src/commons/server/runtime/org.argeo.server.core/target");
- // systemBackup.setFileSystemManager(fsm);
- //
- // List<AtomicBackup> atomicBackups = new ArrayList<AtomicBackup>();
- //
- // MySqlBackup mySqlBackup = new MySqlBackup("root", "", "test");
- // atomicBackups.add(mySqlBackup);
- // PostgreSqlBackup postgreSqlBackup = new PostgreSqlBackup(
- // "argeo", "argeo", "gis_template");
- // atomicBackups.add(postgreSqlBackup);
- // SvnBackup svnBackup = new SvnBackup(
- // "/home/mbaudier/tmp/testsvnrepo");
- // atomicBackups.add(svnBackup);
- //
- // systemBackup.setAtomicBackups(atomicBackups);
- //
- // Map<String, UserAuthenticator> remoteBases = new HashMap<String,
- // UserAuthenticator>();
- // StaticUserAuthenticator userAuthenticator = new StaticUserAuthenticator(
- // null, "demo", "demo");
- // remoteBases.put("sftp://localhost/home/mbaudier/test",
- // userAuthenticator);
- // systemBackup.setRemoteBases(remoteBases);
- //
- // systemBackup.run();
- //
- // fsm.close();
- // } catch (FileSystemException e) {
- // // TODO Auto-generated catch block
- // e.printStackTrace();
- // System.exit(1);
- // }
- //
- // // wait
- // try {
- // Thread.sleep(120 * 1000);
- // } catch (InterruptedException e) {
- // e.printStackTrace();
- // }
- // }
- // }
-}
+++ /dev/null
-/** Argeo Node backup utilities based on Apache Commons VFS. */
-package org.argeo.maintenance.backup.vfs;
\ No newline at end of file
<!-- CMS E4 -->
<module>org.argeo.cms.e4</module>
<module>org.argeo.cms.e4.rap</module>
- <!-- Third Parties Extensions -->
- <!-- <module>org.argeo.ext.jackrabbit</module> -->
- <module>org.argeo.ext.equinox.jetty</module>
<!-- Distribution -->
<module>dep</module>
<module>demo</module>