CcM NG: First part for ThemeManager UI

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5691 8810af33-2d31-482b-a856-94f89814c4df

Former-commit-id: 4297bbc4cc
pull/2/head
jensp 2018-09-13 18:15:56 +00:00
parent e1a37f7bdb
commit 69d3f449e2
10 changed files with 470 additions and 53 deletions

View File

@ -434,14 +434,6 @@ public class NIOFileSystemAdapter implements FileSystemAdapter {
throw new InsufficientPermissionsException(path); throw new InsufficientPermissionsException(path);
} }
try {
if (Files.isDirectory(nioPath) && Files.list(nioPath).count() > 0) {
throw new DirectoryNotEmptyException(path);
}
} catch (IOException ex) {
throw new FileAccessException(path, ex);
}
if (recursively && Files.isDirectory(nioPath)) { if (recursively && Files.isDirectory(nioPath)) {
final List<String> files; final List<String> files;
try { try {
@ -455,7 +447,11 @@ public class NIOFileSystemAdapter implements FileSystemAdapter {
for (final String file : files) { for (final String file : files) {
deleteFile(file, recursively); deleteFile(file, recursively);
} }
deleteFile(path);
} else { } else {
deleteFile(path); deleteFile(path);
} }
} }

View File

@ -22,15 +22,20 @@ import org.libreccm.core.UnexpectedErrorException;
import org.libreccm.files.CcmFiles; import org.libreccm.files.CcmFiles;
import org.libreccm.files.DirectoryNotEmptyException; import org.libreccm.files.DirectoryNotEmptyException;
import org.libreccm.files.FileAccessException; import org.libreccm.files.FileAccessException;
import org.libreccm.files.FileAlreadyExistsException;
import org.libreccm.files.FileDoesNotExistException; import org.libreccm.files.FileDoesNotExistException;
import org.libreccm.files.InsufficientPermissionsException; import org.libreccm.files.InsufficientPermissionsException;
import org.libreccm.theming.manifest.ThemeManifest; import org.libreccm.theming.manifest.ThemeManifest;
import org.libreccm.theming.manifest.ThemeManifestUtil; import org.libreccm.theming.manifest.ThemeManifestUtil;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -84,8 +89,8 @@ public class FileSystemThemeProvider implements ThemeProvider {
.collect(Collectors.toList()); .collect(Collectors.toList());
} catch (FileAccessException } catch (FileAccessException
| FileDoesNotExistException | FileDoesNotExistException
| InsufficientPermissionsException ex) { | InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex); throw new UnexpectedErrorException(ex);
} }
@ -96,7 +101,7 @@ public class FileSystemThemeProvider implements ThemeProvider {
try { try {
if (!ccmFiles.isDirectory(BASE_PATH) if (!ccmFiles.isDirectory(BASE_PATH)
|| !ccmFiles.isDirectory(DRAFT_THEMES_PATH)) { || !ccmFiles.isDirectory(LIVE_THEMES_PATH)) {
return Collections.emptyList(); return Collections.emptyList();
} }
@ -109,8 +114,8 @@ public class FileSystemThemeProvider implements ThemeProvider {
.map(info -> info.get()) .map(info -> info.get())
.collect(Collectors.toList()); .collect(Collectors.toList());
} catch (FileAccessException } catch (FileAccessException
| FileDoesNotExistException | FileDoesNotExistException
| InsufficientPermissionsException ex) { | InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex); throw new UnexpectedErrorException(ex);
} }
@ -137,6 +142,86 @@ public class FileSystemThemeProvider implements ThemeProvider {
} }
} }
@Override
public ThemeInfo createTheme(final String themeName) {
Objects.requireNonNull(themeName);
if (themeName.isEmpty() || themeName.matches("\\s*")) {
throw new IllegalArgumentException(
"The name of a theme can't be empty.");
}
try {
ccmFiles.createDirectory(String.format(DRAFT_THEMES_PATH + "/%s",
themeName));
} catch (FileAccessException
| FileAlreadyExistsException
| InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex);
}
final ThemeManifest manifest = new ThemeManifest();
manifest.setName(themeName);
final OutputStream outputStream;
try {
outputStream = ccmFiles.createOutputStream(
String.format(DRAFT_THEMES_PATH + "/%s/"
+ ThemeConstants.THEME_MANIFEST_JSON,
themeName));
} catch (FileAccessException
| InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex);
}
try(final OutputStreamWriter writer = new OutputStreamWriter(
outputStream, StandardCharsets.UTF_8)) {
writer
.append(manifestUtil
.serializeManifest(manifest,
ThemeConstants.THEME_MANIFEST_JSON));
writer.flush();
} catch (IOException ex) {
throw new UnexpectedErrorException(ex);
}
return getThemeInfo(themeName, ThemeVersion.DRAFT).get();
}
@Override
public void deleteTheme(final String themeName) {
Objects.requireNonNull(themeName);
if (themeName.isEmpty() || themeName.matches("\\s*")) {
throw new IllegalArgumentException(
"The name of a theme can't be empty.");
}
final Optional<ThemeInfo> liveTheme = getLiveThemes()
.stream()
.filter(theme -> theme.getName().equals(themeName))
.findAny();
if (liveTheme.isPresent()) {
throw new IllegalArgumentException(String
.format("The theme \"%s\" is live and can't be deleted.",
themeName));
}
try {
ccmFiles.deleteFile(String.format(DRAFT_THEMES_PATH + "/%s",
themeName),
true);
} catch (FileAccessException
| FileDoesNotExistException
| DirectoryNotEmptyException
| InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex);
}
}
@Override @Override
public List<ThemeFileInfo> listThemeFiles(final String theme, public List<ThemeFileInfo> listThemeFiles(final String theme,
final ThemeVersion version, final ThemeVersion version,
@ -154,8 +239,8 @@ public class FileSystemThemeProvider implements ThemeProvider {
.collect(Collectors.toList()); .collect(Collectors.toList());
} catch (FileAccessException } catch (FileAccessException
| FileDoesNotExistException | FileDoesNotExistException
| InsufficientPermissionsException ex) { | InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex); throw new UnexpectedErrorException(ex);
} }
@ -166,7 +251,7 @@ public class FileSystemThemeProvider implements ThemeProvider {
final String theme, final ThemeVersion version, final String path) { final String theme, final ThemeVersion version, final String path) {
final String themePath = createThemePath(theme, version); final String themePath = createThemePath(theme, version);
final String filePath = String.join(theme, path, "/"); final String filePath = String.join(themePath, path, "/");
try { try {
if (ccmFiles.existsFile(path)) { if (ccmFiles.existsFile(path)) {
@ -175,8 +260,8 @@ public class FileSystemThemeProvider implements ThemeProvider {
return Optional.of(ccmFiles.createInputStream(filePath)); return Optional.of(ccmFiles.createInputStream(filePath));
} }
} catch (FileAccessException } catch (FileAccessException
| FileDoesNotExistException | FileDoesNotExistException
| InsufficientPermissionsException ex) { | InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex); throw new UnexpectedErrorException(ex);
} }
@ -194,7 +279,7 @@ public class FileSystemThemeProvider implements ThemeProvider {
return ccmFiles.createOutputStream(filePath); return ccmFiles.createOutputStream(filePath);
} catch (FileAccessException } catch (FileAccessException
| InsufficientPermissionsException ex) { | InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex); throw new UnexpectedErrorException(ex);
} }
@ -209,9 +294,9 @@ public class FileSystemThemeProvider implements ThemeProvider {
try { try {
ccmFiles.deleteFile(filePath, true); ccmFiles.deleteFile(filePath, true);
} catch (FileAccessException } catch (FileAccessException
| FileDoesNotExistException | FileDoesNotExistException
| DirectoryNotEmptyException | DirectoryNotEmptyException
| InsufficientPermissionsException ex) { | InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex); throw new UnexpectedErrorException(ex);
} }
@ -242,14 +327,14 @@ public class FileSystemThemeProvider implements ThemeProvider {
if (ccmFiles.existsFile(liveThemePath)) { if (ccmFiles.existsFile(liveThemePath)) {
ccmFiles.deleteFile(liveThemePath, true); ccmFiles.deleteFile(liveThemePath, true);
} }
ccmFiles.moveFile(liveThemePathTmp, liveThemePath); ccmFiles.moveFile(liveThemePathTmp, liveThemePath);
} catch (DirectoryNotEmptyException } catch (DirectoryNotEmptyException
| FileAccessException | FileAccessException
| FileDoesNotExistException | FileDoesNotExistException
| InsufficientPermissionsException ex) { | InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(); throw new UnexpectedErrorException();
} }
} }
private String createThemePath(final String theme, private String createThemePath(final String theme,
@ -258,9 +343,9 @@ public class FileSystemThemeProvider implements ThemeProvider {
switch (version) { switch (version) {
case DRAFT: case DRAFT:
return String.format(DRAFT_THEMES_PATH, theme); return String.format(DRAFT_THEMES_PATH + "/%s", theme);
case LIVE: case LIVE:
return String.format(LIVE_THEMES_PATH, theme); return String.format(LIVE_THEMES_PATH + "/%s", theme);
default: default:
throw new IllegalArgumentException(String throw new IllegalArgumentException(String
.format("Illegal argument for ThemeVersion \"%s\".", .format("Illegal argument for ThemeVersion \"%s\".",
@ -286,8 +371,8 @@ public class FileSystemThemeProvider implements ThemeProvider {
return Optional.empty(); return Optional.empty();
} }
} catch (FileAccessException } catch (FileAccessException
| FileDoesNotExistException | FileDoesNotExistException
| InsufficientPermissionsException ex) { | InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex); throw new UnexpectedErrorException(ex);
} }
@ -310,8 +395,8 @@ public class FileSystemThemeProvider implements ThemeProvider {
return fileInfo; return fileInfo;
} catch (FileAccessException } catch (FileAccessException
| FileDoesNotExistException | FileDoesNotExistException
| InsufficientPermissionsException ex) { | InsufficientPermissionsException ex) {
throw new UnexpectedErrorException(ex); throw new UnexpectedErrorException(ex);
} }

View File

@ -254,6 +254,22 @@ public class StaticThemeProvider implements ThemeProvider {
return manifestJsonUrl != null || manifestXmlUrl != null; return manifestJsonUrl != null || manifestXmlUrl != null;
} }
@Override
public ThemeInfo createTheme(final String theme) {
throw new UnsupportedOperationException(String.format(
"The ThemeProvider %s does support the creation of new themes.",
getClass().getName()));
}
@Override
public void deleteTheme(final String theme) {
throw new UnsupportedOperationException(String.format(
"The ThemeProvider %s does support the deltion of themes.",
getClass().getName()));
}
@Override @Override
public List<ThemeFileInfo> listThemeFiles(final String theme, public List<ThemeFileInfo> listThemeFiles(final String theme,
final ThemeVersion version, final ThemeVersion version,

View File

@ -79,6 +79,36 @@ public interface ThemeProvider extends Serializable {
*/ */
boolean providesTheme(String theme, ThemeVersion version); boolean providesTheme(String theme, ThemeVersion version);
/**
* Creates a new theme.
*
* The theme should be empty besides the manifest file. If a theme with the
* provided name already exists implementations should throw an
* {@link IllegalArgumentException}.
*
* {@code ThemeProvider} implementations which do not support the the
* creation of new themes the implementation of the method should throw a
* {@link UnsupportedOperationException}.
*
* @param themeName The name of the new theme.
*
* @return The {@link ThemeInfo} about the new theme.
*/
ThemeInfo createTheme(String themeName);
/**
* Deletes a theme and all its content.
*
* If the is live implementations should throw an exception.
*
* {@code ThemeProvider} implementations which do not support the the
* deletion of themes the implementation of the method should throw a
* {@link UnsupportedOperationException}.
*
* @param themeName The theme to delete.
*/
void deleteTheme(String themeName);
/** /**
* List all files in a theme at the specified path. * List all files in a theme at the specified path.
* *
@ -154,7 +184,7 @@ public interface ThemeProvider extends Serializable {
OutputStream getOutputStreamForThemeFile(String theme, String path); OutputStream getOutputStreamForThemeFile(String theme, String path);
void deleteThemeFile(String theme, String path); void deleteThemeFile(String theme, String path);
/** /**
* Determines if the implementation supports changes to the files of the * Determines if the implementation supports changes to the files of the
* themes. * themes.

View File

@ -184,9 +184,9 @@ public class Themes implements Serializable {
return Optional.empty(); return Optional.empty();
} else { } else {
final Optional<ThemeInfo> masterTheme = getTheme( final Optional<ThemeInfo> masterTheme = getTheme(
theme.getManifest().getMasterTheme(), theme.getManifest().getMasterTheme(),
theme.getVersion()); theme.getVersion());
if (masterTheme.isPresent()) { if (masterTheme.isPresent()) {
return getFileFromTheme(masterTheme.get(), path); return getFileFromTheme(masterTheme.get(), path);
} else { } else {
@ -194,21 +194,22 @@ public class Themes implements Serializable {
} }
} }
} }
/** /**
* List all files in a theme at the specified path * List all files in a theme at the specified path
* *
* @param theme The theme from which the file is retrieved. * @param theme The theme from which the file is retrieved.
* @param path The path of the file relative to the root directory of the * @param path The path of the file relative to the root directory of the
* theme. * theme.
*
* @return A list of all files in the provided directory. If there is no * @return A list of all files in the provided directory. If there is no
* such path in the theme the list is empty. If the path is the path * such path in the theme the list is empty. If the path is the path
* of a file and not a directory the list should have one element, * of a file and not a directory the list should have one element,
* the data about the file itself. * the data about the file itself.
*/ */
public List<ThemeFileInfo> listThemesFiles(final ThemeInfo theme, public List<ThemeFileInfo> listThemeFiles(final ThemeInfo theme,
final String path) { final String path) {
final Instance<? extends ThemeProvider> forTheme = providers.select( final Instance<? extends ThemeProvider> forTheme = providers.select(
theme.getProvider()); theme.getProvider());
@ -221,17 +222,17 @@ public class Themes implements Serializable {
} }
final ThemeProvider provider = forTheme.get(); final ThemeProvider provider = forTheme.get();
return provider.listThemeFiles(theme.getName(), return provider.listThemeFiles(theme.getName(),
theme.getVersion(), theme.getVersion(),
path); path);
} }
public void deleteThemeFile(final ThemeInfo theme, public void deleteThemeFile(final ThemeInfo theme,
final String path) { final String path) {
final Instance<? extends ThemeProvider> forTheme = providers.select( final Instance<? extends ThemeProvider> forTheme = providers
theme.getProvider()); .select(theme.getProvider());
if (forTheme.isUnsatisfied()) { if (forTheme.isUnsatisfied()) {
LOGGER.error("ThemeProvider \"{}\" not found.", LOGGER.error("ThemeProvider \"{}\" not found.",
theme.getProvider().getName()); theme.getProvider().getName());
@ -242,7 +243,7 @@ public class Themes implements Serializable {
final ThemeProvider provider = forTheme.get(); final ThemeProvider provider = forTheme.get();
provider.deleteThemeFile(theme.getName(), path); provider.deleteThemeFile(theme.getName(), path);
} }
} }

View File

@ -112,6 +112,39 @@ public class DatabaseThemeProvider implements ThemeProvider {
.isPresent(); .isPresent();
} }
@Override
public ThemeInfo createTheme(final String themeName) {
Objects.requireNonNull(themeName);
if (themeName.isEmpty() || themeName.matches("\\s*")) {
throw new IllegalArgumentException(
"The name of a theme can't be empty.");
}
final Theme theme = themeManager.createTheme(themeName);
return createThemeInfo(theme);
}
@Override
public void deleteTheme(final String themeName) {
Objects.requireNonNull(themeName);
if (themeName.isEmpty() || themeName.matches("\\s*")) {
throw new IllegalArgumentException(
"The name of a theme can't be empty.");
}
final Theme theme = themeRepository
.findThemeByName(themeName, ThemeVersion.DRAFT)
.orElseThrow(() -> new IllegalArgumentException(String.format(
"No theme with name \"%s\" is managed by this provider.",
themeName)));
themeManager.deleteTheme(theme);
}
@Override @Override
public List<ThemeFileInfo> listThemeFiles(final String themeName, public List<ThemeFileInfo> listThemeFiles(final String themeName,
final ThemeVersion version, final ThemeVersion version,
@ -247,7 +280,7 @@ public class DatabaseThemeProvider implements ThemeProvider {
@Override @Override
public void deleteThemeFile(final String themeName, final String path) { public void deleteThemeFile(final String themeName, final String path) {
Objects.requireNonNull(themeName); Objects.requireNonNull(themeName);
Objects.requireNonNull(path); Objects.requireNonNull(path);
@ -267,10 +300,10 @@ public class DatabaseThemeProvider implements ThemeProvider {
final ThemeFile file = fileRepository final ThemeFile file = fileRepository
.findByPath(theme, path, ThemeVersion.DRAFT) .findByPath(theme, path, ThemeVersion.DRAFT)
.orElse(createDataFile(theme, path)); .orElse(createDataFile(theme, path));
if (file instanceof DataFile) { if (file instanceof DataFile) {
fileManager.delete(file); fileManager.delete(file);
} else if(file instanceof Directory) { } else if (file instanceof Directory) {
fileManager.deleteRecursive(file); fileManager.deleteRecursive(file);
} }
} }

View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2018 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.theming.manager;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
/**
* JAX-RS application for managing themes.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@ApplicationPath("/thememanager")
public class ThemeManager extends Application {
@Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> classes = new HashSet<>();
classes.add(Themes.class);
return classes;
}
}

View File

@ -0,0 +1,210 @@
/*
* Copyright (C) 2018 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.theming.manager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.libreccm.theming.ThemeInfo;
import org.libreccm.theming.ThemeProvider;
import org.libreccm.theming.ThemeVersion;
import java.io.Serializable;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonWriter;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
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.*;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Path("/")
public class Themes implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = LogManager.getLogger(Themes.class);
@Inject
@Any
private Instance<ThemeProvider> providers;
@Inject
private Themes themes;
@GET
@Path("/providers")
@Produces(MediaType.APPLICATION_JSON)
public String getThemeProviders() {
final List<ThemeProvider> providersList = new ArrayList<>();
providers
.forEach(provider -> providersList.add(provider));
final JsonArrayBuilder jsonArrayBuilder = Json.createArrayBuilder();
providersList
.stream()
.filter(provider -> provider.supportsChanges()
&& provider.supportsDraftThemes())
.map(this::getProviderName)
.forEach(jsonArrayBuilder::add);
final StringWriter writer = new StringWriter();
final JsonWriter jsonWriter = Json.createWriter(writer);
jsonWriter.writeArray(jsonArrayBuilder.build());
return writer.toString();
}
@GET
@Path("/themes")
@Produces(MediaType.APPLICATION_JSON)
public List<ThemeInfo> getAvailableThemes() {
final List<ThemeInfo> availableThemes = new ArrayList<>();
for (final ThemeProvider provider : providers) {
if (provider.supportsChanges() && provider.supportsDraftThemes()) {
availableThemes.addAll(provider.getThemes());
}
}
return availableThemes;
}
@GET
@Path("/themes/{theme}")
@Produces(MediaType.APPLICATION_JSON)
public ThemeInfo getTheme(@PathParam("theme") final String themeName) {
for (final ThemeProvider provider : providers) {
if (provider.providesTheme(themeName, ThemeVersion.DRAFT)) {
return provider
.getThemeInfo(themeName, ThemeVersion.DRAFT)
.orElseThrow(() -> new WebApplicationException(
Response.Status.NOT_FOUND));
}
}
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
@PUT
@Path("/themes/{theme}")
@Produces(MediaType.APPLICATION_JSON)
@SuppressWarnings("unchecked")
public ThemeInfo createTheme(
@PathParam("theme") final String themeName,
@QueryParam("provider") final String providerName) {
Objects.requireNonNull(themeName);
Objects.requireNonNull(providerName);
if (themeName.isEmpty() || themeName.matches("\\s*")) {
throw new WebApplicationException("No name for new theme provided.",
Response.Status.BAD_REQUEST);
}
if (providerName.isEmpty() || providerName.matches("\\s*")) {
throw new WebApplicationException(
"No provider for new theme provided.",
Response.Status.BAD_REQUEST);
}
final Class<ThemeProvider> providerClass;
try {
providerClass = (Class<ThemeProvider>) Class.forName(providerName);
} catch (ClassNotFoundException ex) {
throw new WebApplicationException(
String.format("No provider with name \"%s\" available.",
providerName),
Response.Status.INTERNAL_SERVER_ERROR);
}
final ThemeProvider provider = providers.select(providerClass).get();
return provider.createTheme(themeName);
}
@DELETE
@Path("/themes/{theme}")
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();
if (provider.isPresent()) {
provider.get().deleteTheme(themeName);
} else {
throw new WebApplicationException(Response.Status.NOT_FOUND);
}
}
private String getProviderName(final ThemeProvider provider) {
if (provider
.getClass()
.getCanonicalName()
.toLowerCase()
.contains("$proxy")) {
final String name = provider.getClass().getCanonicalName();
return name.substring(0, name.toLowerCase().indexOf("$proxy"));
} else {
return provider.getClass().getName();
}
}
}

View File

@ -21,6 +21,7 @@ package org.libreccm.theming.manifest;
import static org.libreccm.theming.ThemeConstants.*; import static org.libreccm.theming.ThemeConstants.*;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule; import com.fasterxml.jackson.dataformat.xml.JacksonXmlModule;
import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule; import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
@ -149,6 +150,7 @@ public class ThemeManifestUtil implements Serializable {
} }
mapper.registerModule(new JaxbAnnotationModule()); mapper.registerModule(new JaxbAnnotationModule());
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
final StringWriter writer = new StringWriter(); final StringWriter writer = new StringWriter();
try { try {

View File

@ -202,7 +202,7 @@ public class ThemeFiles {
"No theme with name \"%s\" exists.", "No theme with name \"%s\" exists.",
theme))); theme)));
final List<ThemeFileInfo> fileInfos = themes.listThemesFiles(themeInfo, final List<ThemeFileInfo> fileInfos = themes.listThemeFiles(themeInfo,
path); path);
final MultiStatus result; final MultiStatus result;
if (fileInfos.isEmpty()) { if (fileInfos.isEmpty()) {