CCM NG: Next part of DatabaseThemeProvider
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5342 8810af33-2d31-482b-a856-94f89814c4df
Former-commit-id: 386a7763b3
pull/2/head
parent
c6ead1f081
commit
0e6874575b
|
|
@ -92,14 +92,16 @@ public interface ThemeProvider extends Serializable {
|
|||
* should throw an NullPointerException if {@code null} is
|
||||
* provided as path.
|
||||
*
|
||||
* @return A list of all files in the provided directory. If there is 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, the
|
||||
* data about the file itself.
|
||||
* @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
|
||||
* of a file and not a directory the list should have one element,
|
||||
* the data about the file itself.
|
||||
*
|
||||
* @throws IllegalArgumentException If {@code theme} is an empty string,
|
||||
* if there is no theme with the name provided by {@code theme} or
|
||||
* if there is no file/directory with the provided path in the theme.
|
||||
* @throws IllegalArgumentException If {@code theme} is an empty string, if
|
||||
* there is no theme with the name provided
|
||||
* by {@code theme} or if there is no
|
||||
* file/directory with the provided path in
|
||||
* the theme.
|
||||
*/
|
||||
List<ThemeFileInfo> listThemeFiles(String theme,
|
||||
ThemeVersion version,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* 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.db;
|
||||
|
||||
import org.libreccm.core.UnexpectedErrorException;
|
||||
import org.libreccm.theming.ThemeConstants;
|
||||
import org.libreccm.theming.ThemeFileInfo;
|
||||
import org.libreccm.theming.ThemeInfo;
|
||||
import org.libreccm.theming.ThemeProvider;
|
||||
import org.libreccm.theming.ThemeVersion;
|
||||
import org.libreccm.theming.manifest.ThemeManifest;
|
||||
import org.libreccm.theming.manifest.ThemeManifestUtil;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
/**
|
||||
* An implementation of {@link ThemeProvider} which serves themes from the
|
||||
* database.
|
||||
*
|
||||
* Supports all operations.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
@RequestScoped
|
||||
public class DatabaseThemeProvider implements ThemeProvider {
|
||||
|
||||
private static final long serialVersionUID = -8661840420214119753L;
|
||||
|
||||
@Inject
|
||||
private ThemeFileManager fileManager;
|
||||
|
||||
@Inject
|
||||
private ThemeFileRepository fileRepository;
|
||||
|
||||
@Inject
|
||||
private ThemeManifestUtil manifestUtil;
|
||||
|
||||
@Inject
|
||||
private ThemeManager themeManager;
|
||||
|
||||
@Inject
|
||||
private ThemeRepository themeRepository;
|
||||
|
||||
@Override
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public List<ThemeInfo> getThemes() {
|
||||
|
||||
return themeRepository
|
||||
.findAll(ThemeVersion.DRAFT)
|
||||
.stream()
|
||||
.map(this::createThemeInfo)
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ThemeInfo> getLiveThemes() {
|
||||
|
||||
return themeRepository
|
||||
.findAll(ThemeVersion.LIVE)
|
||||
.stream()
|
||||
.map(this::createThemeInfo)
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ThemeInfo> getThemeInfo(final String themeName,
|
||||
final ThemeVersion version) {
|
||||
|
||||
return themeRepository
|
||||
.findThemeByName(themeName, version)
|
||||
.map(this::createThemeInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean providesTheme(final String theme,
|
||||
final ThemeVersion version) {
|
||||
|
||||
return themeRepository
|
||||
.findThemeByName(theme, version)
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ThemeFileInfo> listThemeFiles(final String themeName,
|
||||
final ThemeVersion version,
|
||||
final String path) {
|
||||
|
||||
final Theme theme = themeRepository
|
||||
.findThemeByName(path, version)
|
||||
.orElseThrow(() -> new IllegalArgumentException(String
|
||||
.format("No Theme \"%s\" in the database.", themeName)));
|
||||
|
||||
final Optional<ThemeFile> themeFile = fileRepository
|
||||
.findByPath(theme, path, version);
|
||||
|
||||
final List<ThemeFileInfo> result = new ArrayList<>();
|
||||
if (themeFile.isPresent()) {
|
||||
if (themeFile.get() instanceof DataFile) {
|
||||
|
||||
result.add(themeFile.map(this::createThemeFileInfo).get());
|
||||
|
||||
} else if (themeFile.get() instanceof Directory) {
|
||||
|
||||
final Directory directory = (Directory) themeFile.get();
|
||||
result.addAll(directory
|
||||
.getFiles()
|
||||
.stream()
|
||||
.map(this::createThemeFileInfo)
|
||||
.collect(Collectors.toList()));
|
||||
} else {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("Unknown type \"%s\".",
|
||||
themeFile.get().getClass().getName()));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<InputStream> getThemeFileAsStream(String theme,
|
||||
ThemeVersion version,
|
||||
String path) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStreamForThemeFile(String theme, String path) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsChanges() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsDraftThemes() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishTheme(final String themeName) {
|
||||
|
||||
themeRepository
|
||||
.findThemeByName(themeName, ThemeVersion.DRAFT)
|
||||
.ifPresent(themeManager::publishTheme);
|
||||
}
|
||||
|
||||
private ThemeInfo createThemeInfo(final Theme theme) {
|
||||
|
||||
Objects.requireNonNull(theme);
|
||||
|
||||
final Optional<ThemeFile> manifestFileJson = fileRepository
|
||||
.findByNameAndParent(ThemeConstants.THEME_MANIFEST_JSON,
|
||||
theme.getRootDirectory());
|
||||
final Optional<ThemeFile> manifestFileXml = fileRepository
|
||||
.findByNameAndParent(ThemeConstants.THEME_MANIFEST_XML,
|
||||
theme.getRootDirectory());
|
||||
|
||||
final DataFile manifestFile;
|
||||
final String filename;
|
||||
if (manifestFileJson.isPresent()) {
|
||||
manifestFile = (DataFile) manifestFileJson.get();
|
||||
filename = ThemeConstants.THEME_MANIFEST_JSON;
|
||||
} else if (manifestFileXml.isPresent()) {
|
||||
manifestFile = (DataFile) manifestFileXml.get();
|
||||
filename = ThemeConstants.THEME_MANIFEST_XML;
|
||||
} else {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("No manifest file found for theme \"%s\".",
|
||||
theme.getName()));
|
||||
}
|
||||
|
||||
try (final InputStream inputStream = new ByteArrayInputStream(
|
||||
manifestFile.getData())) {
|
||||
final ThemeManifest manifest = manifestUtil
|
||||
.loadManifest(inputStream, filename);
|
||||
final ThemeInfo themeInfo = new ThemeInfo();
|
||||
themeInfo.setManifest(manifest);
|
||||
themeInfo.setProvider(getClass());
|
||||
themeInfo.setVersion(theme.getVersion());
|
||||
|
||||
return themeInfo;
|
||||
} catch (IOException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private ThemeFileInfo createThemeFileInfo(final ThemeFile file) {
|
||||
|
||||
final ThemeFileInfo fileInfo = new ThemeFileInfo();
|
||||
|
||||
fileInfo.setName(file.getName());
|
||||
fileInfo.setWritable(true);
|
||||
|
||||
if (file instanceof DataFile) {
|
||||
|
||||
final DataFile dataFile = (DataFile) file;
|
||||
|
||||
fileInfo.setDirectory(false);
|
||||
fileInfo.setMimeType(dataFile.getType());
|
||||
fileInfo.setSize(dataFile.getSize());
|
||||
|
||||
}
|
||||
|
||||
if (file instanceof Directory) {
|
||||
fileInfo.setDirectory(true);
|
||||
}
|
||||
|
||||
return fileInfo;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -23,7 +23,6 @@ import org.libreccm.core.CoreConstants;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.OneToMany;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
package org.libreccm.theming.db;
|
||||
|
||||
import org.libreccm.core.CoreConstants;
|
||||
import org.libreccm.theming.ThemeVersion;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
|
@ -43,6 +44,9 @@ import javax.persistence.Table;
|
|||
@Entity
|
||||
@Table(name = "THEMES", schema = CoreConstants.DB_SCHEMA)
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "Theme.findAllForVersion",
|
||||
query = "SELECT t FROM Theme t WHERE t.version = :version")
|
||||
,
|
||||
@NamedQuery(name = "Theme.findByUuid",
|
||||
query = "SELECT t FROM Theme t "
|
||||
+ "WHERE t.uuid = :uuid "
|
||||
|
|
@ -50,8 +54,8 @@ import javax.persistence.Table;
|
|||
,
|
||||
@NamedQuery(name = "Theme.findByName",
|
||||
query = "SELECT t FROM Theme t "
|
||||
+ "WHERE t.name = :name "
|
||||
+ "AND t.version = :version")
|
||||
+ "WHERE t.name = :name "
|
||||
+ "AND t.version = :version")
|
||||
})
|
||||
public class Theme implements Serializable {
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
package org.libreccm.theming.db;
|
||||
|
||||
import org.libreccm.core.CoreConstants;
|
||||
import org.libreccm.theming.ThemeVersion;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
|
@ -88,6 +89,10 @@ public class ThemeFile implements Serializable {
|
|||
@NotNull
|
||||
private String path;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "THEME_ID")
|
||||
private Theme theme;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "PARENT_DIRECTORY_ID")
|
||||
private Directory parent;
|
||||
|
|
@ -132,6 +137,14 @@ public class ThemeFile implements Serializable {
|
|||
this.version = version;
|
||||
}
|
||||
|
||||
public Theme getTheme() {
|
||||
return theme;
|
||||
}
|
||||
|
||||
protected void setTheme(final Theme theme) {
|
||||
this.theme = theme;
|
||||
}
|
||||
|
||||
public Directory getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
|
@ -147,6 +160,7 @@ public class ThemeFile implements Serializable {
|
|||
hash = 37 * hash + Objects.hashCode(name);
|
||||
hash = 37 * hash + Objects.hashCode(path);
|
||||
hash = 37 * hash + Objects.hashCode(uuid);
|
||||
hash = 37 * hash + Objects.hashCode(theme);
|
||||
hash = 37 * hash + Objects.hashCode(parent);
|
||||
return hash;
|
||||
}
|
||||
|
|
@ -178,6 +192,10 @@ public class ThemeFile implements Serializable {
|
|||
if (!Objects.equals(uuid, other.getUuid())) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(theme, other.getTheme())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Objects.equals(parent, other.getParent());
|
||||
}
|
||||
|
||||
|
|
@ -195,13 +213,17 @@ public class ThemeFile implements Serializable {
|
|||
+ "fileId = %d, "
|
||||
+ "name = \"%s\", "
|
||||
+ "path = \"%s\", "
|
||||
+ "uuid = \"%s\"%s"
|
||||
+ "uuid = \"%s\", "
|
||||
+ "theme = \"%s\", "
|
||||
+ "parent = \"%s\"%s"
|
||||
+ " }",
|
||||
super.toString(),
|
||||
fileId,
|
||||
name,
|
||||
path,
|
||||
uuid,
|
||||
Objects.toString(theme),
|
||||
Objects.toString(parent),
|
||||
data);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,10 +19,15 @@
|
|||
package org.libreccm.theming.db;
|
||||
|
||||
import org.libreccm.security.RequiresPrivilege;
|
||||
import org.libreccm.theming.ThemeVersion;
|
||||
import org.libreccm.theming.ThemingPrivileges;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
/**
|
||||
* Provides methods for managing the files of the theme stored in the database.
|
||||
|
|
@ -35,32 +40,93 @@ public class ThemeFileManager {
|
|||
@Inject
|
||||
private ThemeFileRepository fileRepository;
|
||||
|
||||
@Inject
|
||||
private ThemeRepository themeRepository;
|
||||
|
||||
/**
|
||||
* Creates a new {@link DataFile}.
|
||||
* Creates a new, empty {@link DataFile}.
|
||||
*
|
||||
* @param parent The directory in which the {@link DataFile} is created.
|
||||
* @param theme The {@link Theme} to which the file belongs.
|
||||
* @param parent The {@link Directory} in which the {@link DataFile} is
|
||||
* created.
|
||||
* @param name The name of the new {@link DataFile}.
|
||||
*
|
||||
* @return The new {@link DataFile}.
|
||||
*/
|
||||
@RequiresPrivilege(ThemingPrivileges.EDIT_THEME)
|
||||
public DataFile createDataFile(final Directory parent,
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public DataFile createDataFile(final Theme theme,
|
||||
final Directory parent,
|
||||
final String name) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Objects.requireNonNull(parent);
|
||||
Objects.requireNonNull(name);
|
||||
|
||||
if (name.matches("\\s*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"The name of file can't be empty.");
|
||||
}
|
||||
|
||||
final Date now = new Date();
|
||||
final String path = String.join("/", parent.getPath(), name);
|
||||
|
||||
final DataFile dataFile = new DataFile();
|
||||
dataFile.setCreationDate(now);
|
||||
dataFile.setLastModified(now);
|
||||
dataFile.setName(name);
|
||||
dataFile.setParent(parent);
|
||||
dataFile.setPath(path);
|
||||
dataFile.setTheme(theme);
|
||||
dataFile.setVersion(ThemeVersion.DRAFT);
|
||||
|
||||
parent.addFile(dataFile);
|
||||
|
||||
fileRepository.save(dataFile);
|
||||
fileRepository.save(parent);
|
||||
themeRepository.save(theme);
|
||||
|
||||
return dataFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Directory}.
|
||||
*
|
||||
* @param theme The {@link Theme} to which the file belongs.
|
||||
* @param parent The parent directory of the new {@link Directory}.
|
||||
* @param name The name of the new {@link Directory}
|
||||
*
|
||||
* @return The new {@link Directory}.
|
||||
*/
|
||||
@RequiresPrivilege(ThemingPrivileges.EDIT_THEME)
|
||||
public Directory createDirectory(final Directory parent,
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public Directory createDirectory(final Theme theme,
|
||||
final Directory parent,
|
||||
final String name) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Objects.requireNonNull(parent);
|
||||
Objects.requireNonNull(name);
|
||||
|
||||
if (name.matches("\\s*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"The name of file can't be empty.");
|
||||
}
|
||||
|
||||
final String path = String.join("/", parent.getPath(), name);
|
||||
|
||||
final Directory directory = new Directory();
|
||||
directory.setName(name);
|
||||
directory.setParent(parent);
|
||||
directory.setPath(path);
|
||||
directory.setTheme(theme);
|
||||
directory.setVersion(ThemeVersion.DRAFT);
|
||||
|
||||
parent.addFile(directory);
|
||||
|
||||
fileRepository.save(directory);
|
||||
fileRepository.save(parent);
|
||||
themeRepository.save(theme);
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -70,8 +136,33 @@ public class ThemeFileManager {
|
|||
* @param file The {@link ThemeFile} to delete.
|
||||
*/
|
||||
@RequiresPrivilege(ThemingPrivileges.EDIT_THEME)
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public void delete(final ThemeFile file) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Objects.requireNonNull(file);
|
||||
|
||||
if (file instanceof DataFile) {
|
||||
final Directory parent = file.getParent();
|
||||
parent.removeFile(file);
|
||||
fileRepository.delete(file);
|
||||
fileRepository.save(parent);
|
||||
} else if (file instanceof Directory) {
|
||||
final Directory directory = (Directory) file;
|
||||
if (directory.getFiles().isEmpty()) {
|
||||
final Directory parent = file.getParent();
|
||||
parent.removeFile(file);
|
||||
fileRepository.delete(file);
|
||||
fileRepository.save(parent);
|
||||
} else {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("File \"%s\" is a directory and not empty.",
|
||||
directory.getPath()));
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("Don't know how handle file type \"%s\".",
|
||||
file.getClass().getName()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -84,8 +175,28 @@ public class ThemeFileManager {
|
|||
* @param file The {@link ThemeFile} to delete.
|
||||
*/
|
||||
@RequiresPrivilege(ThemingPrivileges.EDIT_THEME)
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public void deleteRecursive(final ThemeFile file) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Objects.requireNonNull(file);
|
||||
|
||||
if (file instanceof DataFile) {
|
||||
delete(file);
|
||||
} else if (file instanceof Directory) {
|
||||
|
||||
final Directory directory = (Directory) file;
|
||||
directory
|
||||
.getFiles()
|
||||
.forEach(subFile -> deleteRecursive(subFile));
|
||||
final Directory parent = file.getParent();
|
||||
parent.removeFile(file);
|
||||
fileRepository.delete(file);
|
||||
fileRepository.save(parent);
|
||||
} else {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("Don't know how handle file type \"%s\".",
|
||||
file.getClass().getName()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -98,8 +209,13 @@ public class ThemeFileManager {
|
|||
* @return The newly created copy.
|
||||
*/
|
||||
@RequiresPrivilege(ThemingPrivileges.EDIT_THEME)
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public ThemeFile copy(final ThemeFile file, final Directory target) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Objects.requireNonNull(file);
|
||||
Objects.requireNonNull(target);
|
||||
|
||||
return copy(file, target, file.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -112,10 +228,73 @@ public class ThemeFileManager {
|
|||
* @return The copy.
|
||||
*/
|
||||
@RequiresPrivilege(ThemingPrivileges.EDIT_THEME)
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public ThemeFile copy(final ThemeFile file,
|
||||
final Directory target,
|
||||
final String nameOfCopy) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Objects.requireNonNull(file);
|
||||
Objects.requireNonNull(target);
|
||||
Objects.requireNonNull(nameOfCopy);
|
||||
|
||||
if (nameOfCopy.matches("\\s*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"The name of the copy can't be empty.");
|
||||
}
|
||||
|
||||
target
|
||||
.getFiles()
|
||||
.stream()
|
||||
.filter(subFile -> subFile.getName().equals(nameOfCopy))
|
||||
.findAny()
|
||||
.ifPresent(subFile -> {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("The target directory \"%s\"already contains a "
|
||||
+ "file with name \"%s\".",
|
||||
target.getPath(),
|
||||
nameOfCopy));
|
||||
});
|
||||
|
||||
if (file instanceof DataFile) {
|
||||
|
||||
final DataFile source = (DataFile) file;
|
||||
final DataFile copy = new DataFile();
|
||||
final Date now = new Date();
|
||||
copy.setCreationDate(now);
|
||||
copy.setData(source.getData());
|
||||
copy.setLastModified(now);
|
||||
copy.setName(nameOfCopy);
|
||||
copy.setParent(target);
|
||||
copy.setPath(String.join("/", target.getPath(), copy.getName()));
|
||||
copy.setSize(source.getSize());
|
||||
copy.setTheme(source.getTheme());
|
||||
copy.setType(source.getType());
|
||||
copy.setVersion(source.getVersion());
|
||||
|
||||
fileRepository.save(copy);
|
||||
fileRepository.save(target);
|
||||
themeRepository.save(copy.getTheme());
|
||||
|
||||
return copy;
|
||||
} else if (file instanceof Directory) {
|
||||
|
||||
final Directory source = (Directory) file;
|
||||
final Directory copy = new Directory();
|
||||
copy.setName(nameOfCopy);
|
||||
copy.setParent(target);
|
||||
copy.setPath(String.join("/", target.getPath(), copy.getName()));
|
||||
copy.setTheme(source.getTheme());
|
||||
copy.setVersion(source.getVersion());
|
||||
|
||||
fileRepository.save(copy);
|
||||
fileRepository.save(target);
|
||||
|
||||
return copy;
|
||||
} else {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("Don't know how handle file type \"%s\".",
|
||||
file.getClass().getName()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -128,9 +307,14 @@ public class ThemeFileManager {
|
|||
* @return The copy.
|
||||
*/
|
||||
@RequiresPrivilege(ThemingPrivileges.EDIT_THEME)
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public ThemeFile copyRecursive(final ThemeFile file,
|
||||
final Directory target) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Objects.requireNonNull(file);
|
||||
Objects.requireNonNull(target);
|
||||
|
||||
return copyRecursive(file, target, file.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -144,10 +328,32 @@ public class ThemeFileManager {
|
|||
* @return The copy.
|
||||
*/
|
||||
@RequiresPrivilege(ThemingPrivileges.EDIT_THEME)
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public ThemeFile copyRecursive(final ThemeFile file,
|
||||
final Directory target,
|
||||
final String nameOfCopy) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Objects.requireNonNull(file);
|
||||
Objects.requireNonNull(target);
|
||||
Objects.requireNonNull(nameOfCopy);
|
||||
|
||||
if (nameOfCopy.matches("\\s*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"The name of a file can't be empty.");
|
||||
}
|
||||
|
||||
final ThemeFile copy = copy(file, target, nameOfCopy);
|
||||
|
||||
if (file instanceof Directory) {
|
||||
final Directory source = (Directory) file;
|
||||
final Directory copiedDirectory = (Directory) copy;
|
||||
|
||||
source
|
||||
.getFiles()
|
||||
.forEach(subFile -> copyRecursive(subFile, copiedDirectory));
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -161,7 +367,11 @@ public class ThemeFileManager {
|
|||
@RequiresPrivilege(ThemingPrivileges.EDIT_THEME)
|
||||
public ThemeFile move(final ThemeFile file,
|
||||
final Directory target) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Objects.requireNonNull(file);
|
||||
Objects.requireNonNull(target);
|
||||
|
||||
return move(file, target, file.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -177,7 +387,42 @@ public class ThemeFileManager {
|
|||
public ThemeFile move(final ThemeFile file,
|
||||
final Directory target,
|
||||
final String newName) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Objects.requireNonNull(file);
|
||||
Objects.requireNonNull(target);
|
||||
Objects.requireNonNull(newName);
|
||||
|
||||
if (newName.matches("\\s*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"The name of a file can't be empty.");
|
||||
}
|
||||
|
||||
target
|
||||
.getFiles()
|
||||
.stream()
|
||||
.filter(subFile -> subFile.getName().equals(newName))
|
||||
.findAny()
|
||||
.ifPresent(subFile -> {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("The target directory \"%s\"already contains a "
|
||||
+ "file with name \"%s\".",
|
||||
target.getPath(),
|
||||
newName));
|
||||
});
|
||||
|
||||
final Directory oldParent = file.getParent();
|
||||
|
||||
file.setName(newName);
|
||||
oldParent.removeFile(file);
|
||||
target.addFile(file);
|
||||
file.setParent(target);
|
||||
|
||||
fileRepository.save(file);
|
||||
fileRepository.save(oldParent);
|
||||
fileRepository.save(target);
|
||||
|
||||
return file;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,17 @@
|
|||
package org.libreccm.theming.db;
|
||||
|
||||
import org.libreccm.core.AbstractEntityRepository;
|
||||
import org.libreccm.core.UnexpectedErrorException;
|
||||
import org.libreccm.theming.ThemeVersion;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.persistence.NoResultException;
|
||||
|
|
@ -55,6 +64,33 @@ public class ThemeFileRepository extends AbstractEntityRepository<Long, ThemeFil
|
|||
return entity.getFileId() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initNewEntity(final ThemeFile themeFile) {
|
||||
if (themeFile.getUuid() == null || themeFile.getUuid().isEmpty()) {
|
||||
themeFile.setUuid(UUID.randomUUID().toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(final ThemeFile file) {
|
||||
|
||||
if (file instanceof DataFile) {
|
||||
final DataFile dataFile = (DataFile) file;
|
||||
dataFile.setLastModified(new Date());
|
||||
try (final InputStream inputStream = new BufferedInputStream(
|
||||
new ByteArrayInputStream(dataFile.getData()))) {
|
||||
|
||||
final String mimeType = URLConnection
|
||||
.guessContentTypeFromStream(inputStream);
|
||||
dataFile.setType(mimeType);
|
||||
} catch (IOException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
super.save(file);
|
||||
}
|
||||
|
||||
public Optional<ThemeFile> findByUuid(final String uuid,
|
||||
final ThemeVersion version) {
|
||||
|
||||
|
|
@ -70,7 +106,8 @@ public class ThemeFileRepository extends AbstractEntityRepository<Long, ThemeFil
|
|||
}
|
||||
}
|
||||
|
||||
public Optional<ThemeFile> findByPath(final String path,
|
||||
public Optional<ThemeFile> findByPath(final Theme theme,
|
||||
final String path,
|
||||
final ThemeVersion version) {
|
||||
|
||||
final TypedQuery<ThemeFile> query = getEntityManager()
|
||||
|
|
|
|||
|
|
@ -19,11 +19,18 @@
|
|||
package org.libreccm.theming.db;
|
||||
|
||||
import org.libreccm.security.RequiresPrivilege;
|
||||
import org.libreccm.theming.ThemeConstants;
|
||||
import org.libreccm.theming.ThemeVersion;
|
||||
import org.libreccm.theming.ThemingPrivileges;
|
||||
import org.libreccm.theming.manifest.ThemeManifest;
|
||||
import org.libreccm.theming.manifest.ThemeManifestUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
/**
|
||||
* Provides methods for managing themes stored in the database.
|
||||
|
|
@ -33,9 +40,15 @@ import javax.inject.Inject;
|
|||
@RequestScoped
|
||||
public class ThemeManager {
|
||||
|
||||
@Inject
|
||||
private ThemeManifestUtil manifestUtil;
|
||||
|
||||
@Inject
|
||||
private ThemeRepository themeRepository;
|
||||
|
||||
@Inject
|
||||
private ThemeFileRepository themeFileRepository;
|
||||
|
||||
/**
|
||||
* Creates a new theme, including the root directory and a theme manifest
|
||||
* file.
|
||||
|
|
@ -47,8 +60,44 @@ public class ThemeManager {
|
|||
* @return The new theme.
|
||||
*/
|
||||
@RequiresPrivilege(ThemingPrivileges.ADMINISTER_THEMES)
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public Theme createTheme(final String name) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Objects.requireNonNull(name);
|
||||
|
||||
if (name.matches("\\s*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"The name of a theme can't be empty.");
|
||||
}
|
||||
|
||||
final Theme theme = new Theme();
|
||||
theme.setName(name);
|
||||
theme.setVersion(ThemeVersion.DRAFT);
|
||||
|
||||
final Directory root = new Directory();
|
||||
root.setName(name);
|
||||
root.setPath("/");
|
||||
root.setTheme(theme);
|
||||
|
||||
final ThemeManifest manifest = new ThemeManifest();
|
||||
manifest.setName(name);
|
||||
|
||||
final DataFile manifestFile = new DataFile();
|
||||
manifestFile.setName(ThemeConstants.THEME_MANIFEST_JSON);
|
||||
manifestFile.setPath(String.format("/%s",
|
||||
ThemeConstants.THEME_MANIFEST_JSON));
|
||||
manifestFile.setTheme(theme);
|
||||
|
||||
final String manifestData = manifestUtil
|
||||
.serializeManifest(manifest, ThemeConstants.THEME_MANIFEST_JSON);
|
||||
manifestFile.setData(manifestData.getBytes());
|
||||
root.addFile(manifestFile);
|
||||
|
||||
themeRepository.save(theme);
|
||||
themeFileRepository.save(root);
|
||||
themeFileRepository.save(manifestFile);
|
||||
|
||||
return theme;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -57,8 +106,71 @@ public class ThemeManager {
|
|||
* @param theme The theme to delete.
|
||||
*/
|
||||
@RequiresPrivilege(ThemingPrivileges.ADMINISTER_THEMES)
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public void deleteTheme(final Theme theme) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Objects.requireNonNull(theme);
|
||||
|
||||
if (isLive(theme)) {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("The theme \"%s\" is live and can't be deleted.",
|
||||
theme.getName()));
|
||||
}
|
||||
|
||||
themeRepository.delete(theme);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a theme has a live version.
|
||||
*
|
||||
* @param theme The theme.
|
||||
*
|
||||
* @return {@code true} if there is a live version of the provided theme,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public boolean isLive(final Theme theme) {
|
||||
|
||||
Objects.requireNonNull(theme);
|
||||
|
||||
return themeRepository
|
||||
.findThemeByUuid(theme.getUuid(), ThemeVersion.LIVE)
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public Theme getDraftTheme(final Theme theme) {
|
||||
|
||||
Objects.requireNonNull(theme);
|
||||
|
||||
if (theme.getVersion() == ThemeVersion.DRAFT) {
|
||||
return theme;
|
||||
} else {
|
||||
return themeRepository
|
||||
.findThemeByUuid(theme.getUuid(), ThemeVersion.DRAFT)
|
||||
.orElseThrow(() -> new IllegalArgumentException(String
|
||||
.format("No draft theme with UUID \"%s\" in the database.",
|
||||
theme.getUuid())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the live version of a theme.
|
||||
*
|
||||
* @param theme The theme.
|
||||
*
|
||||
* @return An {@link Optional} containing the live version of the provided
|
||||
* theme or an empty {@link Optional} if the theme has no live
|
||||
* version.
|
||||
*/
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public Optional<Theme> getLiveTheme(final Theme theme) {
|
||||
|
||||
Objects.requireNonNull(theme);
|
||||
|
||||
return themeRepository
|
||||
.findThemeByUuid(theme.getUuid(), ThemeVersion.LIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -71,18 +183,149 @@ public class ThemeManager {
|
|||
*
|
||||
*/
|
||||
@RequiresPrivilege(ThemingPrivileges.ADMINISTER_THEMES)
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public void publishTheme(final Theme theme) {
|
||||
|
||||
Objects.requireNonNull(theme);
|
||||
|
||||
final Theme draftTheme;
|
||||
if (theme.getVersion() == ThemeVersion.DRAFT) {
|
||||
draftTheme = theme;
|
||||
} else {
|
||||
draftTheme = getDraftTheme(theme);
|
||||
}
|
||||
|
||||
if (isLive(draftTheme)) {
|
||||
unpublishTheme(draftTheme);
|
||||
}
|
||||
|
||||
final Theme liveTheme = new Theme();
|
||||
liveTheme.setName(draftTheme.getName());
|
||||
liveTheme.setUuid(draftTheme.getUuid());
|
||||
liveTheme.setVersion(ThemeVersion.LIVE);
|
||||
|
||||
final Directory liveRoot = new Directory();
|
||||
liveRoot.setName(draftTheme.getRootDirectory().getName());
|
||||
liveRoot.setPath(draftTheme.getRootDirectory().getPath());
|
||||
liveRoot.setUuid(draftTheme.getRootDirectory().getUuid());
|
||||
liveRoot.setTheme(theme);
|
||||
liveRoot.setVersion(ThemeVersion.LIVE);
|
||||
|
||||
themeRepository.save(liveTheme);
|
||||
themeFileRepository.save(liveRoot);
|
||||
|
||||
draftTheme
|
||||
.getRootDirectory()
|
||||
.getFiles()
|
||||
.forEach(file -> publishFile(liveTheme, liveRoot, file));
|
||||
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private void publishFile(final Theme liveTheme,
|
||||
final Directory liveParent,
|
||||
final ThemeFile draftFile) {
|
||||
|
||||
Objects.requireNonNull(liveParent);
|
||||
Objects.requireNonNull(draftFile);
|
||||
|
||||
if (liveParent.getVersion() != ThemeVersion.LIVE) {
|
||||
throw new IllegalArgumentException("Parent directory is not live.");
|
||||
}
|
||||
|
||||
if (draftFile.getVersion() != ThemeVersion.DRAFT) {
|
||||
throw new IllegalArgumentException("File to publish is not draft.");
|
||||
}
|
||||
|
||||
if (draftFile instanceof Directory) {
|
||||
|
||||
final Directory draftDirectory = (Directory) draftFile;
|
||||
|
||||
final Directory liveDirectory = new Directory();
|
||||
liveDirectory.setName(draftDirectory.getName());
|
||||
liveDirectory.setPath(draftDirectory.getPath());
|
||||
liveDirectory.setParent(liveParent);
|
||||
liveDirectory.setUuid(draftDirectory.getUuid());
|
||||
liveDirectory.setVersion(ThemeVersion.LIVE);
|
||||
liveDirectory.setTheme(liveTheme);
|
||||
|
||||
themeFileRepository.save(liveDirectory);
|
||||
|
||||
draftDirectory
|
||||
.getFiles()
|
||||
.forEach(file -> publishFile(liveTheme, liveDirectory, file));
|
||||
|
||||
} else if (draftFile instanceof DataFile) {
|
||||
|
||||
final DataFile draftDataFile = (DataFile) draftFile;
|
||||
|
||||
final DataFile liveDataFile = new DataFile();
|
||||
liveDataFile.setCreationDate(draftDataFile.getCreationDate());
|
||||
liveDataFile.setData(draftDataFile.getData());
|
||||
liveDataFile.setLastModified(draftDataFile.getLastModified());
|
||||
liveDataFile.setName(draftDataFile.getName());
|
||||
liveDataFile.setParent(liveParent);
|
||||
liveDataFile.setPath(draftDataFile.getPath());
|
||||
liveDataFile.setSize(draftDataFile.getSize());
|
||||
liveDataFile.setType(draftDataFile.getType());
|
||||
liveDataFile.setUuid(draftDataFile.getUuid());
|
||||
liveDataFile.setTheme(liveTheme);
|
||||
liveDataFile.setVersion(ThemeVersion.LIVE);
|
||||
|
||||
themeFileRepository.save(liveDataFile);
|
||||
} else {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("Don't know how handle file type \"%s\".",
|
||||
draftFile.getClass().getName()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpublishes a theme by deleting the live version of the theme.
|
||||
* Unpublishes a theme by deleting the live version of the theme. If the
|
||||
* theme is not published the method will return without doing anything.
|
||||
*
|
||||
* @param theme The theme to unpublish.
|
||||
*/
|
||||
@RequiresPrivilege(ThemingPrivileges.ADMINISTER_THEMES)
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public void unpublishTheme(final Theme theme) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
Objects.requireNonNull(theme);
|
||||
|
||||
if (!isLive(theme)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Theme liveTheme = getLiveTheme(theme).get();
|
||||
final Directory liveRoot = liveTheme.getRootDirectory();
|
||||
|
||||
liveRoot
|
||||
.getFiles()
|
||||
.forEach(file -> unpublishFile(file));
|
||||
}
|
||||
|
||||
private void unpublishFile(final ThemeFile themeFile) {
|
||||
|
||||
Objects.requireNonNull(themeFile);
|
||||
if (themeFile.getVersion() != ThemeVersion.LIVE) {
|
||||
throw new IllegalArgumentException(
|
||||
"Only live files can be unpublished.");
|
||||
}
|
||||
|
||||
if (themeFile instanceof DataFile) {
|
||||
themeFileRepository.delete(themeFile);
|
||||
} else if (themeFile instanceof Directory) {
|
||||
final Directory directory = (Directory) themeFile;
|
||||
directory
|
||||
.getFiles()
|
||||
.forEach(file -> unpublishFile(file));
|
||||
themeFileRepository.delete(themeFile);
|
||||
} else {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("Don't know how handle file type \"%s\".",
|
||||
themeFile.getClass().getName()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,13 @@
|
|||
package org.libreccm.theming.db;
|
||||
|
||||
import org.libreccm.core.AbstractEntityRepository;
|
||||
import org.libreccm.security.RequiresPrivilege;
|
||||
import org.libreccm.theming.ThemeVersion;
|
||||
import org.libreccm.theming.ThemingPrivileges;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.persistence.NoResultException;
|
||||
|
|
@ -57,8 +62,25 @@ public class ThemeRepository extends AbstractEntityRepository<Long, Theme> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void initNewEntity(final Theme theme) {
|
||||
if (theme.getUuid() == null || theme.getUuid().isEmpty()) {
|
||||
theme.setUuid(UUID.randomUUID().toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@RequiresPrivilege(ThemingPrivileges.ADMINISTER_THEMES)
|
||||
public void save(final Theme theme) {
|
||||
super.save(theme);;
|
||||
super.save(theme);
|
||||
}
|
||||
|
||||
public List<Theme> findAll(final ThemeVersion version) {
|
||||
|
||||
final TypedQuery<Theme> query = getEntityManager()
|
||||
.createNamedQuery("Theme.findAllForVersion", Theme.class);
|
||||
query.setParameter("version", version);
|
||||
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* 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.db;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
public enum ThemeVersion {
|
||||
|
||||
DRAFT,
|
||||
LIVE
|
||||
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@ import java.io.InputStream;
|
|||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.Serializable;
|
||||
import java.io.StringWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
|
|
@ -60,7 +61,6 @@ public class ThemeManifestUtil implements Serializable {
|
|||
public ThemeManifest loadManifest(final Path path) {
|
||||
|
||||
// final String pathStr = path.toString().toLowerCase(Locale.ROOT);
|
||||
|
||||
final BufferedReader reader;
|
||||
try {
|
||||
reader = Files.newBufferedReader(path, Charset.forName("UTF-8"));
|
||||
|
|
@ -130,7 +130,38 @@ public class ThemeManifestUtil implements Serializable {
|
|||
// return manifest;
|
||||
}
|
||||
|
||||
private ThemeManifest parseManifest(final Reader reader, final String path) {
|
||||
public String serializeManifest(final ThemeManifest manifest,
|
||||
final String format) {
|
||||
|
||||
final ObjectMapper mapper;
|
||||
|
||||
switch (format) {
|
||||
case THEME_MANIFEST_JSON:
|
||||
mapper = new ObjectMapper();
|
||||
break;
|
||||
case THEME_MANIFEST_XML:
|
||||
final JacksonXmlModule xmlModule = new JacksonXmlModule();
|
||||
mapper = new XmlMapper(xmlModule);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
"Unsupported format for ThemeManifest");
|
||||
}
|
||||
|
||||
mapper.registerModule(new JaxbAnnotationModule());
|
||||
|
||||
final StringWriter writer = new StringWriter();
|
||||
try {
|
||||
mapper.writeValue(writer, manifest);
|
||||
} catch (IOException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
private ThemeManifest parseManifest(final Reader reader,
|
||||
final String path) {
|
||||
|
||||
final String pathStr = path.toLowerCase(Locale.ROOT);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue