2013-07-27 18:33:20 +02:00
|
|
|
package com.sismics.docs.rest.resource;
|
|
|
|
|
2015-11-29 19:42:49 +01:00
|
|
|
import java.io.IOException;
|
|
|
|
import java.nio.file.DirectoryStream;
|
|
|
|
import java.nio.file.Files;
|
2013-08-18 00:53:01 +02:00
|
|
|
import java.util.HashMap;
|
2013-08-17 00:36:36 +02:00
|
|
|
import java.util.List;
|
2013-08-18 00:53:01 +02:00
|
|
|
import java.util.Map;
|
2013-08-17 00:36:36 +02:00
|
|
|
import java.util.ResourceBundle;
|
|
|
|
|
2015-09-07 21:51:13 +02:00
|
|
|
import javax.json.Json;
|
|
|
|
import javax.json.JsonArrayBuilder;
|
|
|
|
import javax.json.JsonObjectBuilder;
|
2013-08-17 00:36:36 +02:00
|
|
|
import javax.ws.rs.GET;
|
|
|
|
import javax.ws.rs.POST;
|
|
|
|
import javax.ws.rs.Path;
|
|
|
|
import javax.ws.rs.QueryParam;
|
|
|
|
import javax.ws.rs.core.Response;
|
|
|
|
|
|
|
|
import org.apache.commons.lang.StringUtils;
|
|
|
|
import org.apache.log4j.Appender;
|
|
|
|
import org.apache.log4j.Logger;
|
|
|
|
|
2013-08-18 00:53:01 +02:00
|
|
|
import com.sismics.docs.core.dao.jpa.FileDao;
|
2015-11-29 23:14:33 +01:00
|
|
|
import com.sismics.docs.core.dao.jpa.UserDao;
|
2013-08-17 14:16:55 +02:00
|
|
|
import com.sismics.docs.core.model.context.AppContext;
|
2013-08-18 00:53:01 +02:00
|
|
|
import com.sismics.docs.core.model.jpa.File;
|
2015-11-29 23:14:33 +01:00
|
|
|
import com.sismics.docs.core.model.jpa.User;
|
2013-07-27 18:33:20 +02:00
|
|
|
import com.sismics.docs.core.util.ConfigUtil;
|
2013-08-18 00:53:01 +02:00
|
|
|
import com.sismics.docs.core.util.DirectoryUtil;
|
2013-07-27 18:33:20 +02:00
|
|
|
import com.sismics.docs.core.util.jpa.PaginatedList;
|
|
|
|
import com.sismics.docs.core.util.jpa.PaginatedLists;
|
|
|
|
import com.sismics.docs.rest.constant.BaseFunction;
|
|
|
|
import com.sismics.rest.exception.ForbiddenClientException;
|
|
|
|
import com.sismics.rest.exception.ServerException;
|
|
|
|
import com.sismics.util.log4j.LogCriteria;
|
|
|
|
import com.sismics.util.log4j.LogEntry;
|
|
|
|
import com.sismics.util.log4j.MemoryAppender;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* General app REST resource.
|
|
|
|
*
|
|
|
|
* @author jtremeaux
|
|
|
|
*/
|
|
|
|
@Path("/app")
|
|
|
|
public class AppResource extends BaseResource {
|
|
|
|
/**
|
|
|
|
* Return the information about the application.
|
|
|
|
*
|
|
|
|
* @return Response
|
|
|
|
*/
|
|
|
|
@GET
|
2015-09-07 21:51:13 +02:00
|
|
|
public Response info() {
|
2013-08-01 13:36:15 +02:00
|
|
|
if (!authenticate()) {
|
|
|
|
throw new ForbiddenClientException();
|
|
|
|
}
|
|
|
|
|
2013-07-27 18:33:20 +02:00
|
|
|
ResourceBundle configBundle = ConfigUtil.getConfigBundle();
|
|
|
|
String currentVersion = configBundle.getString("api.current_version");
|
|
|
|
String minVersion = configBundle.getString("api.min_version");
|
|
|
|
|
2015-09-07 21:51:13 +02:00
|
|
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
|
|
|
.add("current_version", currentVersion.replace("-SNAPSHOT", ""))
|
|
|
|
.add("min_version", minVersion)
|
|
|
|
.add("total_memory", Runtime.getRuntime().totalMemory())
|
|
|
|
.add("free_memory", Runtime.getRuntime().freeMemory());
|
2013-08-01 13:36:15 +02:00
|
|
|
|
2015-09-07 21:51:13 +02:00
|
|
|
return Response.ok().entity(response.build()).build();
|
2013-07-27 18:33:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve the application logs.
|
|
|
|
*
|
|
|
|
* @param level Filter on logging level
|
|
|
|
* @param tag Filter on logger name / tag
|
|
|
|
* @param message Filter on message
|
|
|
|
* @param limit Page limit
|
|
|
|
* @param offset Page offset
|
2013-08-13 20:20:28 +02:00
|
|
|
* @return Response
|
2013-07-27 18:33:20 +02:00
|
|
|
*/
|
|
|
|
@GET
|
|
|
|
@Path("log")
|
|
|
|
public Response log(
|
|
|
|
@QueryParam("level") String level,
|
|
|
|
@QueryParam("tag") String tag,
|
|
|
|
@QueryParam("message") String message,
|
|
|
|
@QueryParam("limit") Integer limit,
|
2015-09-07 21:51:13 +02:00
|
|
|
@QueryParam("offset") Integer offset) {
|
2013-07-27 18:33:20 +02:00
|
|
|
if (!authenticate()) {
|
|
|
|
throw new ForbiddenClientException();
|
|
|
|
}
|
2013-08-22 17:41:47 +02:00
|
|
|
// TODO Change level by minLevel (returns all logs above)
|
2013-07-27 18:33:20 +02:00
|
|
|
|
|
|
|
// Get the memory appender
|
|
|
|
Logger logger = Logger.getRootLogger();
|
|
|
|
Appender appender = logger.getAppender("MEMORY");
|
|
|
|
if (appender == null || !(appender instanceof MemoryAppender)) {
|
|
|
|
throw new ServerException("ServerError", "MEMORY appender not configured");
|
|
|
|
}
|
|
|
|
MemoryAppender memoryAppender = (MemoryAppender) appender;
|
|
|
|
|
|
|
|
// Find the logs
|
|
|
|
LogCriteria logCriteria = new LogCriteria();
|
|
|
|
logCriteria.setLevel(StringUtils.stripToNull(level));
|
|
|
|
logCriteria.setTag(StringUtils.stripToNull(tag));
|
|
|
|
logCriteria.setMessage(StringUtils.stripToNull(message));
|
|
|
|
|
|
|
|
PaginatedList<LogEntry> paginatedList = PaginatedLists.create(limit, offset);
|
|
|
|
memoryAppender.find(logCriteria, paginatedList);
|
2015-09-07 21:51:13 +02:00
|
|
|
JsonArrayBuilder logs = Json.createArrayBuilder();
|
2013-07-27 18:33:20 +02:00
|
|
|
for (LogEntry logEntry : paginatedList.getResultList()) {
|
2015-09-07 21:51:13 +02:00
|
|
|
logs.add(Json.createObjectBuilder()
|
|
|
|
.add("date", logEntry.getTimestamp())
|
|
|
|
.add("level", logEntry.getLevel())
|
|
|
|
.add("tag", logEntry.getTag())
|
|
|
|
.add("message", logEntry.getMessage()));
|
2013-07-27 18:33:20 +02:00
|
|
|
}
|
|
|
|
|
2015-09-07 21:51:13 +02:00
|
|
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
|
|
|
.add("total", paginatedList.getResultCount())
|
|
|
|
.add("logs", logs);
|
|
|
|
|
|
|
|
return Response.ok().entity(response.build()).build();
|
2013-07-27 18:33:20 +02:00
|
|
|
}
|
2013-08-17 00:36:36 +02:00
|
|
|
|
2013-08-17 14:16:55 +02:00
|
|
|
/**
|
|
|
|
* Destroy and rebuild Lucene index.
|
|
|
|
*
|
|
|
|
* @return Response
|
|
|
|
*/
|
|
|
|
@POST
|
|
|
|
@Path("batch/reindex")
|
2015-09-07 21:51:13 +02:00
|
|
|
public Response batchReindex() {
|
2013-08-17 14:16:55 +02:00
|
|
|
if (!authenticate()) {
|
|
|
|
throw new ForbiddenClientException();
|
|
|
|
}
|
|
|
|
checkBaseFunction(BaseFunction.ADMIN);
|
|
|
|
|
|
|
|
try {
|
|
|
|
AppContext.getInstance().getIndexingService().rebuildIndex();
|
|
|
|
} catch (Exception e) {
|
|
|
|
throw new ServerException("IndexingError", "Error rebuilding index", e);
|
|
|
|
}
|
2013-08-18 00:53:01 +02:00
|
|
|
|
2015-09-07 21:51:13 +02:00
|
|
|
// Always return OK
|
|
|
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
|
|
|
.add("status", "ok");
|
|
|
|
return Response.ok().entity(response.build()).build();
|
2013-08-18 00:53:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-08-20 21:51:07 +02:00
|
|
|
* Clean storage.
|
2013-08-18 00:53:01 +02:00
|
|
|
*
|
|
|
|
* @return Response
|
|
|
|
*/
|
|
|
|
@POST
|
|
|
|
@Path("batch/clean_storage")
|
2015-09-07 21:51:13 +02:00
|
|
|
public Response batchCleanStorage() {
|
2013-08-18 00:53:01 +02:00
|
|
|
if (!authenticate()) {
|
|
|
|
throw new ForbiddenClientException();
|
|
|
|
}
|
|
|
|
checkBaseFunction(BaseFunction.ADMIN);
|
|
|
|
|
|
|
|
// Get all files
|
|
|
|
FileDao fileDao = new FileDao();
|
|
|
|
List<File> fileList = fileDao.findAll();
|
|
|
|
Map<String, File> fileMap = new HashMap<>();
|
|
|
|
for (File file : fileList) {
|
|
|
|
fileMap.put(file.getId(), file);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if each stored file is valid
|
2015-11-29 19:42:49 +01:00
|
|
|
try (DirectoryStream<java.nio.file.Path> storedFileList = Files.newDirectoryStream(DirectoryUtil.getStorageDirectory())) {
|
|
|
|
for (java.nio.file.Path storedFile : storedFileList) {
|
|
|
|
String fileName = storedFile.getFileName().toString();
|
|
|
|
String[] fileNameArray = fileName.split("_");
|
|
|
|
if (!fileMap.containsKey(fileNameArray[0])) {
|
|
|
|
Files.delete(storedFile);
|
|
|
|
}
|
2013-08-18 00:53:01 +02:00
|
|
|
}
|
2015-11-29 19:42:49 +01:00
|
|
|
} catch (IOException e) {
|
|
|
|
throw new ServerException("FileError", "Error deleting orphan files", e);
|
2013-08-18 00:53:01 +02:00
|
|
|
}
|
|
|
|
|
2015-09-07 21:51:13 +02:00
|
|
|
// Always return OK
|
|
|
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
|
|
|
.add("status", "ok");
|
|
|
|
return Response.ok().entity(response.build()).build();
|
2013-08-17 14:16:55 +02:00
|
|
|
}
|
2015-11-29 23:14:33 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Recompute the quota for each user.
|
|
|
|
*
|
|
|
|
* @return Response
|
|
|
|
*/
|
|
|
|
@POST
|
|
|
|
@Path("batch/recompute_quota")
|
|
|
|
public Response batchRecomputeQuota() {
|
|
|
|
if (!authenticate()) {
|
|
|
|
throw new ForbiddenClientException();
|
|
|
|
}
|
|
|
|
checkBaseFunction(BaseFunction.ADMIN);
|
|
|
|
|
|
|
|
// Get all files
|
|
|
|
FileDao fileDao = new FileDao();
|
|
|
|
List<File> fileList = fileDao.findAll();
|
|
|
|
|
|
|
|
// Count each file for the corresponding user quota
|
|
|
|
UserDao userDao = new UserDao();
|
|
|
|
Map<String, User> userMap = new HashMap<>();
|
|
|
|
for (File file : fileList) {
|
|
|
|
java.nio.file.Path storedFile = DirectoryUtil.getStorageDirectory().resolve(file.getId());
|
|
|
|
User user = null;
|
|
|
|
if (userMap.containsKey(file.getUserId())) {
|
|
|
|
user = userMap.get(file.getUserId());
|
|
|
|
} else {
|
|
|
|
user = userDao.getById(file.getUserId());
|
|
|
|
user.setStorageCurrent(0l);
|
|
|
|
userMap.put(user.getId(), user);
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
user.setStorageCurrent(user.getStorageCurrent() + Files.size(storedFile));
|
|
|
|
} catch (IOException e) {
|
|
|
|
throw new ServerException("MissingFile", "File does not exist", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save all users
|
|
|
|
for (User user : userMap.values()) {
|
2015-11-30 00:28:51 +01:00
|
|
|
if (user.getDeleteDate() == null) {
|
|
|
|
userDao.update(user);
|
|
|
|
}
|
2015-11-29 23:14:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Always return OK
|
|
|
|
JsonObjectBuilder response = Json.createObjectBuilder()
|
|
|
|
.add("status", "ok");
|
|
|
|
return Response.ok().entity(response.build()).build();
|
|
|
|
}
|
2013-07-27 18:33:20 +02:00
|
|
|
}
|