CCM NG: Second part of api for theme manager app

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5692 8810af33-2d31-482b-a856-94f89814c4df
jensp 2018-09-14 18:01:57 +00:00
parent 4297bbc4cc
commit db9e9b9cfd
6 changed files with 153 additions and 42 deletions

View File

@ -44,7 +44,6 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.rmi.UnexpectedException;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -234,14 +233,16 @@ public class NIOFileSystemAdapter implements FileSystemAdapter {
final String targetPath,
boolean recursive) throws FileAccessException {
final Path nioSourcePath = Paths.get(sourcePath);
final Path nioTargetPath = Paths.get(targetPath);
final Path nioSourcePath = Paths
.get(String.join("/", dataPath, sourcePath));
final Path nioTargetPath = Paths
.get(String.join("/", dataPath, targetPath));
if (recursive) {
try {
Files.walkFileTree(
nioTargetPath,
nioSourcePath,
new FileVisitor<Path>() {
@Override
@ -262,7 +263,7 @@ public class NIOFileSystemAdapter implements FileSystemAdapter {
file,
nioTargetPath
.resolve(nioSourcePath.relativize(file)),
StandardCopyOption.ATOMIC_MOVE,
// StandardCopyOption.ATOMIC_MOVE,
StandardCopyOption.COPY_ATTRIBUTES,
StandardCopyOption.REPLACE_EXISTING,
LinkOption.NOFOLLOW_LINKS);
@ -311,7 +312,7 @@ public class NIOFileSystemAdapter implements FileSystemAdapter {
try {
Files.copy(nioSourcePath,
nioTargetPath,
StandardCopyOption.ATOMIC_MOVE,
// StandardCopyOption.ATOMIC_MOVE,
StandardCopyOption.COPY_ATTRIBUTES,
StandardCopyOption.REPLACE_EXISTING,
LinkOption.NOFOLLOW_LINKS);
@ -325,14 +326,16 @@ public class NIOFileSystemAdapter implements FileSystemAdapter {
public void move(final String sourcePath, final String targetPath)
throws FileAccessException {
final Path nioSourcePath = Paths.get(sourcePath);
final Path nioTargetPath = Paths.get(targetPath);
final Path nioSourcePath = Paths.get(
String.join("/", dataPath, sourcePath));
final Path nioTargetPath = Paths.get(
String.join("/", dataPath, targetPath));
try {
Files.move(nioSourcePath,
nioTargetPath,
StandardCopyOption.ATOMIC_MOVE,
StandardCopyOption.COPY_ATTRIBUTES,
// StandardCopyOption.COPY_ATTRIBUTES,
StandardCopyOption.REPLACE_EXISTING,
LinkOption.NOFOLLOW_LINKS);
} catch(IOException ex) {

View File

@ -54,8 +54,8 @@ public class FileSystemThemeProvider implements ThemeProvider {
private static final long serialVersionUID = 1L;
private static final String BASE_PATH = "/themes";
private static final String DRAFT_THEMES_PATH = "/themes" + "/draft";
private static final String LIVE_THEMES_PATH = "/themes" + "/live";
private static final String DRAFT_THEMES_PATH = BASE_PATH + "/draft";
private static final String LIVE_THEMES_PATH = BASE_PATH + "/live";
private static final String THEME_JSON = "%s/theme.json";
private static final String THEME_XML = "%s/theme.xml";
@ -175,7 +175,7 @@ public class FileSystemThemeProvider implements ThemeProvider {
throw new UnexpectedErrorException(ex);
}
try(final OutputStreamWriter writer = new OutputStreamWriter(
try (final OutputStreamWriter writer = new OutputStreamWriter(
outputStream, StandardCharsets.UTF_8)) {
writer
.append(manifestUtil
@ -215,9 +215,9 @@ public class FileSystemThemeProvider implements ThemeProvider {
themeName),
true);
} catch (FileAccessException
| FileDoesNotExistException
| DirectoryNotEmptyException
| InsufficientPermissionsException ex) {
| FileDoesNotExistException
| DirectoryNotEmptyException
| InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex);
}
}
@ -320,20 +320,50 @@ public class FileSystemThemeProvider implements ThemeProvider {
ThemeVersion.DRAFT);
final String liveThemePath = createThemePath(theme,
ThemeVersion.LIVE);
final String liveThemePathTmp = String.format("%_tmp", liveThemePath);
final String liveThemePathTmp = String.format("%s_tmp", liveThemePath);
try {
if (!ccmFiles.existsFile(LIVE_THEMES_PATH)) {
ccmFiles.createDirectory(LIVE_THEMES_PATH);
}
} catch (FileAccessException
| InsufficientPermissionsException
| FileAlreadyExistsException ex) {
throw new UnexpectedErrorException(ex);
}
try {
ccmFiles.createDirectory(liveThemePathTmp);
ccmFiles.copyFile(draftThemePath, liveThemePathTmp, true);
if (ccmFiles.existsFile(liveThemePath)) {
ccmFiles.deleteFile(liveThemePath, true);
}
ccmFiles.moveFile(liveThemePathTmp, liveThemePath);
} catch (DirectoryNotEmptyException
| FileAccessException
| FileAlreadyExistsException
| FileDoesNotExistException
| InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex);
}
}
@Override
public void unpublishTheme(final String theme) {
final String liveThemePath = createThemePath(theme,
ThemeVersion.LIVE);
try {
ccmFiles.deleteFile(liveThemePath, true);
} catch (DirectoryNotEmptyException
| FileAccessException
| FileDoesNotExistException
| InsufficientPermissionsException ex) {
throw new UnexpectedErrorException();
throw new UnexpectedErrorException(ex);
}
}
@ -357,15 +387,19 @@ public class FileSystemThemeProvider implements ThemeProvider {
final ThemeManifest manifest;
try {
final InputStream inputStream = ccmFiles
.createInputStream(String.format(THEME_JSON,
themePath));
if (ccmFiles.existsFile(String.format(THEME_JSON,
themePath))) {
final String jsonPath = String.format(
DRAFT_THEMES_PATH + "/" + THEME_JSON, themePath);
final String xmlPath = String.format(
DRAFT_THEMES_PATH + "/" + THEME_XML, themePath);
if (ccmFiles.existsFile(jsonPath)) {
final InputStream inputStream = ccmFiles
.createInputStream(jsonPath);
manifest = manifestUtil.loadManifest(inputStream, "theme.json");
} else if (ccmFiles.existsFile(String.format(THEME_XML,
themePath))) {
} else if (ccmFiles.existsFile(xmlPath)) {
final InputStream inputStream = ccmFiles
.createInputStream(xmlPath);
manifest = manifestUtil.loadManifest(inputStream, "theme.xml");
} else {
return Optional.empty();

View File

@ -391,6 +391,11 @@ public class StaticThemeProvider implements ThemeProvider {
//No op in this implementation.
}
@Override
public void unpublishTheme(final String theme) {
//No op in this implementation.
}
private URI getJarUri() {
LOGGER.debug("Getting URI of JAR...");

View File

@ -209,4 +209,13 @@ public interface ThemeProvider extends Serializable {
*/
void publishTheme(String theme);
/**
* Unpublishes (deletes) the live version of a theme. For
* implementations which do not support draft/live themes the implementation
* of this method should be a noop, but not throw an exception.
*
* @param theme The theme to publish.
*/
void unpublishTheme(String theme);
}

View File

@ -326,6 +326,14 @@ public class DatabaseThemeProvider implements ThemeProvider {
.ifPresent(themeManager::publishTheme);
}
@Override
public void unpublishTheme(final String themeName) {
themeRepository
.findThemeByName(themeName, ThemeVersion.LIVE)
.ifPresent(themeManager::unpublishTheme);
}
private ThemeInfo createThemeInfo(final Theme theme) {
Objects.requireNonNull(theme);

View File

@ -20,9 +20,11 @@ package org.libreccm.theming.manager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.libreccm.security.RequiresPrivilege;
import org.libreccm.theming.ThemeInfo;
import org.libreccm.theming.ThemeProvider;
import org.libreccm.theming.ThemeVersion;
import org.libreccm.theming.ThemingPrivileges;
import java.io.Serializable;
import java.io.StringWriter;
@ -40,6 +42,7 @@ import javax.json.JsonArrayBuilder;
import javax.json.JsonWriter;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@ -49,8 +52,6 @@ import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import static javassist.CtClass.*;
import static org.reflections.util.Utils.*;
/**
*
@ -74,6 +75,8 @@ public class Themes implements Serializable {
@GET
@Path("/providers")
@Produces(MediaType.APPLICATION_JSON)
//@AuthorizationRequired
@RequiresPrivilege(ThemingPrivileges.ADMINISTER_THEMES)
public String getThemeProviders() {
final List<ThemeProvider> providersList = new ArrayList<>();
@ -100,6 +103,8 @@ public class Themes implements Serializable {
@GET
@Path("/themes")
@Produces(MediaType.APPLICATION_JSON)
//@AuthorizationRequired
@RequiresPrivilege(ThemingPrivileges.ADMINISTER_THEMES)
public List<ThemeInfo> getAvailableThemes() {
final List<ThemeInfo> availableThemes = new ArrayList<>();
@ -115,6 +120,8 @@ public class Themes implements Serializable {
@GET
@Path("/themes/{theme}")
@Produces(MediaType.APPLICATION_JSON)
//@AuthorizationRequired
@RequiresPrivilege(ThemingPrivileges.EDIT_THEME)
public ThemeInfo getTheme(@PathParam("theme") final String themeName) {
for (final ThemeProvider provider : providers) {
@ -133,6 +140,8 @@ public class Themes implements Serializable {
@Path("/themes/{theme}")
@Produces(MediaType.APPLICATION_JSON)
@SuppressWarnings("unchecked")
//@AuthorizationRequired
@RequiresPrivilege(ThemingPrivileges.ADMINISTER_THEMES)
public ThemeInfo createTheme(
@PathParam("theme") final String themeName,
@QueryParam("provider") final String providerName) {
@ -167,19 +176,13 @@ public class Themes implements Serializable {
@DELETE
@Path("/themes/{theme}")
//@AuthorizationRequired
@RequiresPrivilege(ThemingPrivileges.ADMINISTER_THEMES)
public void deleteTheme(@PathParam("theme") final String themeName) {
Objects.requireNonNull(themeName);
final List<ThemeProvider> providersList = new ArrayList<>();
providers
.forEach(provider -> providersList.add(provider));
final Optional<ThemeProvider> provider = providersList
.stream()
.filter(current -> current.providesTheme(themeName,
ThemeVersion.DRAFT))
.findAny();
final Optional<ThemeProvider> provider = findProvider(themeName);
if (provider.isPresent()) {
@ -190,6 +193,42 @@ public class Themes implements Serializable {
}
}
@POST
@Path("/themes/{theme}/live")
//@AuthorizationRequired
@RequiresPrivilege(ThemingPrivileges.ADMINISTER_THEMES)
public void publishTheme(@PathParam("theme") final String themeName) {
final Optional<ThemeProvider> provider = findProvider(themeName);
if (provider.isPresent()) {
provider.get().publishTheme(themeName);
} else {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
}
@DELETE
@Path("/themes/{theme}/live")
//@AuthorizationRequired
@RequiresPrivilege(ThemingPrivileges.ADMINISTER_THEMES)
public void unPublishTheme(@PathParam("theme") final String themeName) {
final Optional<ThemeProvider> provider = findProvider(themeName);
if (provider.isPresent()) {
provider.get().unpublishTheme(themeName);
} else {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
}
private String getProviderName(final ThemeProvider provider) {
if (provider
@ -207,4 +246,17 @@ public class Themes implements Serializable {
}
private Optional<ThemeProvider> findProvider(final String forTheme) {
final List<ThemeProvider> providersList = new ArrayList<>();
providers
.forEach(provider -> providersList.add(provider));
return providersList
.stream()
.filter(current -> current.providesTheme(forTheme,
ThemeVersion.DRAFT))
.findAny();
}
}