JcrSession.java
/*
* The coLAB project
* Copyright (C) 2021-2023 AlbaSim, MEI, HEIG-VD, HES-SO
*
* Licensed under the MIT License
*/
package ch.colabproject.colab.api.persistence.jcr;
import ch.colabproject.colab.api.model.project.Project;
import ch.colabproject.colab.generator.model.exceptions.HttpErrorMessage;
import ch.colabproject.colab.generator.model.exceptions.MessageI18nKey;
import java.io.InputStream;
import java.io.Serializable;
import javax.jcr.Binary;
import javax.jcr.Credentials;
import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author maxence
*/
public class JcrSession implements Serializable {
private static final long serialVersionUID = 1L;
/**
* logger
*/
private static final Logger logger = LoggerFactory.getLogger(JcrSession.class);
/**
* Default credentials
*/
private static final Credentials credentials = new SimpleCredentials(
"admin",
"admin".toCharArray());
/** Global workspace name */
private static final String GLOBAL_WORKSPACE = "global_workspace";
/**
* The session itself
*/
private Session session;
/**
* Session workspace
*/
private final String workspace;
/**
* Session workspace path
*/
private final String workspacePath;
/**
* Open a JCR session to the repository
*
* @param repository the repository to log in
* @param project project
*
* @throws javax.jcr.RepositoryException in case of JCR issue
*/
public JcrSession(Repository repository, Project project) throws RepositoryException {
logger.trace("Create JCR Session for {}", project == null ? GLOBAL_WORKSPACE : project);
// TODO create user if not present in
// TODO long term :
this.session = repository.login(credentials);
if (project != null) {
this.workspace = "project_" + project.getId();
} else {
this.workspace = GLOBAL_WORKSPACE;
}
this.workspacePath = "/" + this.workspace;
// make sure root node exists
if (!session.nodeExists(workspacePath)) {
session.getNode("/").addNode(workspace);
}
}
/**
* Get the workspace root node
*
* @return workspace root
*/
public Node getWorkspaceRoot() {
try {
return session.getNode(workspacePath);
} catch (RepositoryException ex) {
// silent
logger.warn("getWorkspaceRoot failed with ", ex);
return null;
}
}
/**
* Get full relativePath of given relativePath.
*
* @param relativePath relativePath path relative to the workspace root. May starts with a / or
* not
*
* @return absolute relativePath (i.e. <code>workspacePath</code>/<code>relativePath</code>)
*/
private String getFullPath(String relativePath) {
if (relativePath.charAt(0) == '/') {
return this.workspacePath + relativePath;
} else {
return this.workspacePath + '/' + relativePath;
}
}
/**
* Does a node exist ?
*
* @param relativePath relativePath path relative to the workspace root. May starts with a / or
* not
*
* @return the node or null if it does not exist
*/
public boolean nodeExists(String relativePath) {
try {
return session.nodeExists(getFullPath(relativePath));
} catch (RepositoryException ex) {
// TODO: silent or not ?
logger.warn("nodeExists({}) failed with ", relativePath, ex);
return false;
}
}
/**
* Get a node
*
* @param relativePath relativePath relative to the workspace root. May starts with a / or not
*
* @return the node or null if it does not exist
*/
public Node getNode(String relativePath) {
try {
return session.getNode(getFullPath(relativePath));
} catch (RepositoryException ex) {
// silent
logger.warn("getNode: node does not exist ", ex);
return null;
}
}
/**
* @param relativePath relative path from workspace root
*/
public void removeNode(String relativePath) {
try {
session.removeItem(getFullPath(relativePath));
} catch (RepositoryException ex) {
logger.warn("removeNode: node could not be removed", ex);
}
}
/**
* Get JCR session
*
* @return the session
*/
public Session getSession() {
return session;
}
/**
* make sure to flush all pending operations
*
* @throws javax.jcr.RepositoryException something went wrong
*/
public void prepareForCommit() throws RepositoryException {
if (this.session != null && this.session.isLive()) {
session.getRootNode();
} else {
logger.warn(
"PrepareForCommit failed: session does not exists or has already been closed ");
// TODO throw something else, but what ?
throw HttpErrorMessage.dataError(MessageI18nKey.DATA_INTEGRITY_FAILURE);
}
}
/**
* creates a new binary object to be stored
*
* @param content content to be stored in the binary
*
* @return The created binary
*
* @throws RepositoryException JCR issue
*/
public Binary createBinary(InputStream content) throws RepositoryException {
return this.session.getValueFactory().createBinary(content);
}
/**
* Save and close
*/
public void saveAndClose() {
try {
session.save();
} catch (RepositoryException ex) {
logger.error(
"Error occured while saving changes despite prepareForCommit did not throw anything !",
ex);
/* no-op */
}
session.logout();
this.session = null;
}
/**
* Close the session without saving any changes
*/
public void rollback() {
logger.trace("Rollback session");
if (session != null && session.isLive()) {
session.logout();
}
this.session = null;
}
}