CCM NG: Various things including a new version of the StaticThemeProvider (not finished yet)
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5093 8810af33-2d31-482b-a856-94f89814c4dfccm-docs
parent
0fc51a8faf
commit
cacf30cf12
|
|
@ -196,6 +196,12 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.reflections</groupId>
|
||||
<artifactId>reflections</artifactId>
|
||||
<version>0.9.11</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.primefaces</groupId>
|
||||
<artifactId>primefaces</artifactId>
|
||||
|
|
|
|||
|
|
@ -55,6 +55,10 @@ public class SitesTab extends LayoutPanel {
|
|||
final ActionLink addNewSite = new ActionLink(new GlobalizedMessage(
|
||||
"ui.admin.sites.add_new_site_link",
|
||||
ADMIN_BUNDLE));
|
||||
addNewSite
|
||||
.addActionListener(event -> {
|
||||
showSiteForm(event.getPageState());
|
||||
});
|
||||
|
||||
final BoxPanel right = new BoxPanel(BoxPanel.VERTICAL);
|
||||
right.add(addNewSite);
|
||||
|
|
|
|||
|
|
@ -18,82 +18,181 @@
|
|||
*/
|
||||
package org.libreccm.theming;
|
||||
|
||||
import static org.libreccm.theming.ThemeConstants.*;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.libreccm.core.UnexpectedErrorException;
|
||||
import org.libreccm.theming.manifest.ThemeManifest;
|
||||
import org.libreccm.theming.manifest.ThemeManifestUtil;
|
||||
import org.reflections.Reflections;
|
||||
import org.reflections.scanners.ResourcesScanner;
|
||||
import org.reflections.util.ClasspathHelper;
|
||||
import org.reflections.util.ConfigurationBuilder;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* A theme provider implementation which serves themes from the class path
|
||||
* ({@code /themes)}. This implementation does not support changes to the
|
||||
* theme(s) and files.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
@RequestScoped
|
||||
public class StaticThemeProvider implements ThemeProvider {
|
||||
|
||||
private static final Logger LOGGER = LogManager
|
||||
.getLogger(StaticThemeProvider.class);
|
||||
private static final long serialVersionUID = 7174370298224448067L;
|
||||
private static final Logger LOGGER = LogManager.getLogger(
|
||||
StaticThemeProvider.class);
|
||||
|
||||
/**
|
||||
* Path the the static themes.
|
||||
*/
|
||||
private static final String THEMES_DIR = "/themes";
|
||||
private static final long serialVersionUID = -8701021965452233811L;
|
||||
private static final String THEME_MANIFEST_JSON = THEMES_DIR
|
||||
+ "/%s/theme.json";
|
||||
private static final String THEME_MANIFEST_XML = THEMES_DIR
|
||||
+ "/%s/theme.xml";
|
||||
|
||||
@Inject
|
||||
private ThemeFileInfoUtil themeFileInfoUtil;
|
||||
|
||||
@Inject
|
||||
private ThemeManifestUtil themeManifests;
|
||||
private ThemeManifestUtil manifestUtil;
|
||||
|
||||
@Override
|
||||
public List<ThemeInfo> getThemes() {
|
||||
|
||||
LOGGER.debug("Retrieving info about all static themes...");
|
||||
final Reflections reflections = new Reflections(
|
||||
new ConfigurationBuilder()
|
||||
.setUrls(ClasspathHelper.forPackage("themes"))
|
||||
.setScanners(new ResourcesScanner()));
|
||||
final Set<String> resources = reflections
|
||||
.getResources(Pattern.compile("themes/.*/theme.json"));
|
||||
LOGGER.debug("Found resources:");
|
||||
for (final String resource : resources) {
|
||||
LOGGER.debug("\t{}", resource);
|
||||
}
|
||||
|
||||
try (final FileSystem jarFileSystem = FileSystems.newFileSystem(
|
||||
getJarUri(), Collections.emptyMap())) {
|
||||
final URL themesUrl = StaticThemeProvider.class.getResource(THEMES_DIR);
|
||||
|
||||
final Path themesPath = jarFileSystem.getPath(THEMES_DIR);
|
||||
if (!Files.isDirectory(themesPath)) {
|
||||
LOGGER.warn(THEMES_DIR + " is not a directory. Returning "
|
||||
+ "empty list.");
|
||||
return Collections.emptyList();
|
||||
if (themesUrl == null) {
|
||||
throw new UnexpectedErrorException(
|
||||
"Static themes directory does not"
|
||||
+ "exist in class path. Something is wrong.");
|
||||
}
|
||||
|
||||
File directory;
|
||||
try {
|
||||
directory = new File(themesUrl.toURI());
|
||||
} catch (URISyntaxException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
directory = null;
|
||||
}
|
||||
|
||||
final List<String> themeDirs = new ArrayList<>();
|
||||
if (directory != null && directory.exists()) {
|
||||
final String[] files = directory.list();
|
||||
for (final String file : files) {
|
||||
themeDirs.add(file);
|
||||
}
|
||||
} else {
|
||||
final String jarPath = themesUrl
|
||||
.getFile()
|
||||
.replaceFirst("[.]jar[!].*", ".jar")
|
||||
.replaceFirst("file:", "");
|
||||
|
||||
return Files
|
||||
.list(themesPath)
|
||||
.filter(this::isTheme)
|
||||
.map(this::generateThemeInfo)
|
||||
.collect(Collectors.toList());
|
||||
final JarFile jarFile;
|
||||
try {
|
||||
jarFile = new JarFile(jarPath);
|
||||
} catch (IOException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
final Enumeration<JarEntry> jarEntries = jarFile.entries();
|
||||
while (jarEntries.hasMoreElements()) {
|
||||
final JarEntry jarEntry = jarEntries.nextElement();
|
||||
final String jarEntryName = jarEntry.getName();
|
||||
|
||||
if (jarEntryName.startsWith("themes")
|
||||
&& jarEntryName.length() > "themes/".length()
|
||||
&& jarEntryName.endsWith("/")) {
|
||||
themeDirs.add(jarEntryName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return themeDirs
|
||||
.stream()
|
||||
.filter(dirPath -> isThemeDir(dirPath))
|
||||
.map(dirPath -> loadThemeManifest(dirPath))
|
||||
.map(manifest -> generateThemeInfo(manifest))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private boolean isThemeDir(final String dirPath) {
|
||||
|
||||
Objects.requireNonNull(dirPath);
|
||||
|
||||
final URL manifestJsonUrl = StaticThemeProvider.class.getResource(
|
||||
String.format(THEME_MANIFEST_JSON, dirPath));
|
||||
final URL manifestXmlUrl = StaticThemeProvider.class.getResource(
|
||||
String.format(THEME_MANIFEST_XML, dirPath));
|
||||
|
||||
return (manifestJsonUrl != null) || (manifestXmlUrl != null);
|
||||
}
|
||||
|
||||
private ThemeManifest loadThemeManifest(final String dirPath) {
|
||||
|
||||
Objects.requireNonNull(dirPath);
|
||||
|
||||
final URL manifestJsonUrl = StaticThemeProvider.class.getResource(
|
||||
String.format(THEME_MANIFEST_JSON, dirPath));
|
||||
final URL manifestXmlUrl = StaticThemeProvider.class.getResource(
|
||||
String.format(THEME_MANIFEST_XML, dirPath));
|
||||
|
||||
final URL manifestUrl;
|
||||
if (manifestJsonUrl != null) {
|
||||
manifestUrl = manifestJsonUrl;
|
||||
} else if (manifestXmlUrl != null) {
|
||||
manifestUrl = manifestXmlUrl;
|
||||
} else {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("Path \"%s\" does not point to a valid theme manifest.",
|
||||
dirPath));
|
||||
}
|
||||
|
||||
final ThemeManifest themeManifest;
|
||||
try (final InputStream inputStream = manifestUrl.openStream()) {
|
||||
|
||||
themeManifest = manifestUtil.loadManifest(inputStream,
|
||||
manifestUrl.toString());
|
||||
|
||||
} catch (IOException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
|
||||
return themeManifest;
|
||||
}
|
||||
|
||||
private ThemeInfo generateThemeInfo(final ThemeManifest manifest) {
|
||||
|
||||
Objects.requireNonNull(manifest);
|
||||
|
||||
final ThemeInfo info = new ThemeInfo();
|
||||
info.setManifest(manifest);
|
||||
info.setProvider(getClass());
|
||||
info.setVersion(ThemeVersion.LIVE);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -106,31 +205,13 @@ public class StaticThemeProvider implements ThemeProvider {
|
|||
final ThemeVersion version) {
|
||||
|
||||
Objects.requireNonNull(theme);
|
||||
Objects.requireNonNull(version);
|
||||
|
||||
if (theme.matches("\\s*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"The name of the theme can't be empty.");
|
||||
if (isThemeDir(theme)) {
|
||||
return Optional.of(generateThemeInfo(loadThemeManifest(theme)));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
LOGGER.debug("Trying to find static theme \"{}\"...",
|
||||
theme);
|
||||
|
||||
try (final FileSystem jarFileSystem = FileSystems
|
||||
.newFileSystem(getJarUri(), Collections.emptyMap())) {
|
||||
|
||||
final Path themePath = jarFileSystem
|
||||
.getPath(String.format(THEMES_DIR + "/%s", theme));
|
||||
|
||||
if (isTheme(themePath)) {
|
||||
return Optional.of(generateThemeInfo(themePath));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
} catch (IOException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -138,30 +219,9 @@ public class StaticThemeProvider implements ThemeProvider {
|
|||
final ThemeVersion version) {
|
||||
|
||||
Objects.requireNonNull(theme);
|
||||
Objects.requireNonNull(version);
|
||||
|
||||
if (theme.isEmpty() || theme.matches("\\s*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"The name of the theme can't be empty.");
|
||||
}
|
||||
return isThemeDir(theme);
|
||||
|
||||
LOGGER.debug("Determining if there is static theme \"{}\"...",
|
||||
theme);
|
||||
|
||||
try (final FileSystem jarFileSystem = FileSystems
|
||||
.newFileSystem(getJarUri(), Collections.emptyMap())) {
|
||||
|
||||
final Path themePath = jarFileSystem
|
||||
.getPath(String.format(THEMES_DIR + "/%s", theme));
|
||||
|
||||
LOGGER.debug("Is there a static theme \"{}\": {}",
|
||||
theme,
|
||||
isTheme(themePath));
|
||||
return isTheme(themePath);
|
||||
|
||||
} catch (IOException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -169,128 +229,19 @@ public class StaticThemeProvider implements ThemeProvider {
|
|||
final ThemeVersion version,
|
||||
final String path) {
|
||||
|
||||
Objects.requireNonNull(theme);
|
||||
Objects.requireNonNull(version);
|
||||
Objects.requireNonNull(path);
|
||||
|
||||
if (theme.isEmpty() || theme.matches("\\s*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"The name of the theme can't be empty.");
|
||||
}
|
||||
|
||||
final String pathToDir;
|
||||
if ("".equals(path)) {
|
||||
pathToDir = "/";
|
||||
} else {
|
||||
pathToDir = path;
|
||||
}
|
||||
|
||||
LOGGER.debug("Listing all files in path \"{]\" of theme \"{}\"...",
|
||||
path,
|
||||
theme);
|
||||
|
||||
final List<ThemeFileInfo> infos;
|
||||
try (final FileSystem jarFileSystem = FileSystems
|
||||
.newFileSystem(getJarUri(), Collections.emptyMap())) {
|
||||
|
||||
final Path themePath = jarFileSystem
|
||||
.getPath(String.format(THEMES_DIR + "/%s", theme));
|
||||
|
||||
if (!isTheme(themePath)) {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("Theme \"%s\" does not exist.",
|
||||
theme));
|
||||
}
|
||||
|
||||
final Path dirPath = themePath.resolve(pathToDir);
|
||||
if (Files.exists(dirPath)) {
|
||||
|
||||
if (Files.isDirectory(dirPath)) {
|
||||
|
||||
try (final Stream<Path> stream = Files.list(dirPath)) {
|
||||
infos = stream
|
||||
.map(themeFileInfoUtil::buildThemeInfo)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
} else {
|
||||
infos = new ArrayList<>();
|
||||
infos.add(themeFileInfoUtil.buildThemeInfo(dirPath));
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("No file/directory \"%s\" in theme \"%s\".",
|
||||
path,
|
||||
theme));
|
||||
}
|
||||
|
||||
} catch (IOException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
|
||||
LOGGER.debug("Files in path \"{}\" of static theme \"{}\": {}",
|
||||
pathToDir,
|
||||
theme,
|
||||
Objects.toString(infos));
|
||||
return infos;
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<InputStream> getThemeFileAsStream(final String theme,
|
||||
final ThemeVersion version,
|
||||
final String path) {
|
||||
Objects.requireNonNull(theme);
|
||||
Objects.requireNonNull(version);
|
||||
Objects.requireNonNull(path);
|
||||
|
||||
if (theme.isEmpty() || theme.matches("\\s*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"The name of the theme can't be empty.");
|
||||
}
|
||||
|
||||
if (path.isEmpty() || path.matches("\\s*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"The name of the theme can't be empty.");
|
||||
}
|
||||
|
||||
try (final FileSystem jarFileSystem = FileSystems
|
||||
.newFileSystem(getJarUri(), Collections.emptyMap())) {
|
||||
|
||||
final Path themePath = jarFileSystem
|
||||
.getPath(String.format(THEMES_DIR + "/%s", theme));
|
||||
|
||||
final Path filePath;
|
||||
if (path.charAt(0) == '/') {
|
||||
filePath = themePath.resolve(path.substring(1));
|
||||
} else {
|
||||
filePath = themePath.resolve(path);
|
||||
}
|
||||
|
||||
if (!Files.isRegularFile(filePath)) {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("The provided path \"%s\" in theme \"%s\" points "
|
||||
+ "not to a regular file.",
|
||||
path,
|
||||
theme));
|
||||
}
|
||||
|
||||
if (Files.exists(filePath)) {
|
||||
return Optional.of(Files.newInputStream(filePath));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
} catch (IOException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
|
||||
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(final String theme,
|
||||
final String path) {
|
||||
|
||||
throw new UnsupportedOperationException("Not supported by this"
|
||||
+ " implemetentation");
|
||||
public OutputStream getOutputStreamForThemeFile(String theme, String path) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -305,72 +256,7 @@ public class StaticThemeProvider implements ThemeProvider {
|
|||
|
||||
@Override
|
||||
public void publishTheme(final String theme) {
|
||||
LOGGER.info("StaticThemeProvider#publishTheme(String) called, but "
|
||||
+ "StaticThemeProvider does not support draft/live "
|
||||
+ "themes.");
|
||||
}
|
||||
|
||||
private URI getJarUri() {
|
||||
|
||||
LOGGER.debug("Getting URI of JAR...");
|
||||
|
||||
final String themesUrl = getClass().getResource(THEMES_DIR).toString();
|
||||
LOGGER.debug("Full URL of " + THEMES_DIR + " directory: {}", themesUrl);
|
||||
|
||||
final int index = themesUrl.indexOf('!');
|
||||
final String pathToJar = themesUrl.substring(0, index);
|
||||
|
||||
final URI uri = URI.create(pathToJar);
|
||||
LOGGER.debug("URI to JAR is \"%s\".", uri.toString());
|
||||
return uri;
|
||||
}
|
||||
|
||||
private boolean isTheme(final Path path) {
|
||||
|
||||
Objects.requireNonNull(path);
|
||||
|
||||
if (!Files.isDirectory(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Path manifestPathJson = path.resolve(THEME_MANIFEST_JSON);
|
||||
final Path manifestPathXml = path.resolve(THEME_MANIFEST_XML);
|
||||
|
||||
return Files.exists(manifestPathJson) || Files.exists(manifestPathXml);
|
||||
}
|
||||
|
||||
private ThemeInfo generateThemeInfo(final Path path) {
|
||||
|
||||
Objects.requireNonNull(path);
|
||||
|
||||
if (!Files.exists(path)) {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("The provided path \"%s\" does "
|
||||
+ "not exist.",
|
||||
path.toString()));
|
||||
}
|
||||
|
||||
final Path manifestPathJson = path.resolve(THEME_MANIFEST_JSON);
|
||||
final Path manifestPathXml = path.resolve(THEME_MANIFEST_XML);
|
||||
|
||||
final ThemeManifest manifest;
|
||||
if (Files.exists(manifestPathJson)) {
|
||||
manifest = themeManifests.loadManifest(manifestPathJson);
|
||||
} else if (Files.exists(manifestPathXml)) {
|
||||
manifest = themeManifests.loadManifest(manifestPathXml);
|
||||
} else {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("The provided path \"%s\" does "
|
||||
+ "contain a theme manifest file.",
|
||||
path.toString()));
|
||||
}
|
||||
|
||||
final ThemeInfo themeInfo = new ThemeInfo();
|
||||
themeInfo.setVersion(ThemeVersion.LIVE);
|
||||
themeInfo.setProvider(getClass());
|
||||
themeInfo.setManifest(manifest);
|
||||
|
||||
return themeInfo;
|
||||
//No op in this implementation.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,376 @@
|
|||
/*
|
||||
* Copyright (C) 2017 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;
|
||||
|
||||
import static org.libreccm.theming.ThemeConstants.*;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.libreccm.core.UnexpectedErrorException;
|
||||
import org.libreccm.theming.manifest.ThemeManifest;
|
||||
import org.libreccm.theming.manifest.ThemeManifestUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
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 java.util.stream.Stream;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* A theme provider implementation which serves themes from the class path
|
||||
* ({@code /themes)}. This implementation does not support changes to the
|
||||
* theme(s) and files.
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
@RequestScoped
|
||||
public class StaticThemeProvider implements ThemeProvider {
|
||||
|
||||
private static final Logger LOGGER = LogManager
|
||||
.getLogger(StaticThemeProvider.class);
|
||||
|
||||
/**
|
||||
* Path the the static themes.
|
||||
*/
|
||||
private static final String THEMES_DIR = "/themes";
|
||||
private static final long serialVersionUID = -8701021965452233811L;
|
||||
|
||||
@Inject
|
||||
private ThemeFileInfoUtil themeFileInfoUtil;
|
||||
|
||||
@Inject
|
||||
private ThemeManifestUtil themeManifests;
|
||||
|
||||
@Override
|
||||
public List<ThemeInfo> getThemes() {
|
||||
|
||||
LOGGER.debug("Retrieving info about all static themes...");
|
||||
|
||||
try (final FileSystem jarFileSystem = FileSystems.newFileSystem(
|
||||
getJarUri(), Collections.emptyMap())) {
|
||||
|
||||
final Path themesPath = jarFileSystem.getPath(THEMES_DIR);
|
||||
if (!Files.isDirectory(themesPath)) {
|
||||
LOGGER.warn(THEMES_DIR + " is not a directory. Returning "
|
||||
+ "empty list.");
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return Files
|
||||
.list(themesPath)
|
||||
.filter(this::isTheme)
|
||||
.map(this::generateThemeInfo)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
} catch (IOException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ThemeInfo> getLiveThemes() {
|
||||
return getThemes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ThemeInfo> getThemeInfo(final String theme,
|
||||
final ThemeVersion version) {
|
||||
|
||||
Objects.requireNonNull(theme);
|
||||
Objects.requireNonNull(version);
|
||||
|
||||
if (theme.matches("\\s*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"The name of the theme can't be empty.");
|
||||
}
|
||||
|
||||
LOGGER.debug("Trying to find static theme \"{}\"...",
|
||||
theme);
|
||||
|
||||
try (final FileSystem jarFileSystem = FileSystems
|
||||
.newFileSystem(getJarUri(), Collections.emptyMap())) {
|
||||
|
||||
final Path themePath = jarFileSystem
|
||||
.getPath(String.format(THEMES_DIR + "/%s", theme));
|
||||
|
||||
if (isTheme(themePath)) {
|
||||
return Optional.of(generateThemeInfo(themePath));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
} catch (IOException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean providesTheme(final String theme,
|
||||
final ThemeVersion version) {
|
||||
|
||||
Objects.requireNonNull(theme);
|
||||
Objects.requireNonNull(version);
|
||||
|
||||
if (theme.isEmpty() || theme.matches("\\s*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"The name of the theme can't be empty.");
|
||||
}
|
||||
|
||||
LOGGER.debug("Determining if there is static theme \"{}\"...",
|
||||
theme);
|
||||
|
||||
try (final FileSystem jarFileSystem = FileSystems
|
||||
.newFileSystem(getJarUri(), Collections.emptyMap())) {
|
||||
|
||||
final Path themePath = jarFileSystem
|
||||
.getPath(String.format(THEMES_DIR + "/%s", theme));
|
||||
|
||||
LOGGER.debug("Is there a static theme \"{}\": {}",
|
||||
theme,
|
||||
isTheme(themePath));
|
||||
return isTheme(themePath);
|
||||
|
||||
} catch (IOException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ThemeFileInfo> listThemeFiles(final String theme,
|
||||
final ThemeVersion version,
|
||||
final String path) {
|
||||
|
||||
Objects.requireNonNull(theme);
|
||||
Objects.requireNonNull(version);
|
||||
Objects.requireNonNull(path);
|
||||
|
||||
if (theme.isEmpty() || theme.matches("\\s*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"The name of the theme can't be empty.");
|
||||
}
|
||||
|
||||
final String pathToDir;
|
||||
if ("".equals(path)) {
|
||||
pathToDir = "/";
|
||||
} else {
|
||||
pathToDir = path;
|
||||
}
|
||||
|
||||
LOGGER.debug("Listing all files in path \"{]\" of theme \"{}\"...",
|
||||
path,
|
||||
theme);
|
||||
|
||||
final List<ThemeFileInfo> infos;
|
||||
try (final FileSystem jarFileSystem = FileSystems
|
||||
.newFileSystem(getJarUri(), Collections.emptyMap())) {
|
||||
|
||||
final Path themePath = jarFileSystem
|
||||
.getPath(String.format(THEMES_DIR + "/%s", theme));
|
||||
|
||||
if (!isTheme(themePath)) {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("Theme \"%s\" does not exist.",
|
||||
theme));
|
||||
}
|
||||
|
||||
final Path dirPath = themePath.resolve(pathToDir);
|
||||
if (Files.exists(dirPath)) {
|
||||
|
||||
if (Files.isDirectory(dirPath)) {
|
||||
|
||||
try (final Stream<Path> stream = Files.list(dirPath)) {
|
||||
infos = stream
|
||||
.map(themeFileInfoUtil::buildThemeInfo)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
} else {
|
||||
infos = new ArrayList<>();
|
||||
infos.add(themeFileInfoUtil.buildThemeInfo(dirPath));
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("No file/directory \"%s\" in theme \"%s\".",
|
||||
path,
|
||||
theme));
|
||||
}
|
||||
|
||||
} catch (IOException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
|
||||
LOGGER.debug("Files in path \"{}\" of static theme \"{}\": {}",
|
||||
pathToDir,
|
||||
theme,
|
||||
Objects.toString(infos));
|
||||
return infos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<InputStream> getThemeFileAsStream(final String theme,
|
||||
final ThemeVersion version,
|
||||
final String path) {
|
||||
Objects.requireNonNull(theme);
|
||||
Objects.requireNonNull(version);
|
||||
Objects.requireNonNull(path);
|
||||
|
||||
if (theme.isEmpty() || theme.matches("\\s*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"The name of the theme can't be empty.");
|
||||
}
|
||||
|
||||
if (path.isEmpty() || path.matches("\\s*")) {
|
||||
throw new IllegalArgumentException(
|
||||
"The name of the theme can't be empty.");
|
||||
}
|
||||
|
||||
try (final FileSystem jarFileSystem = FileSystems
|
||||
.newFileSystem(getJarUri(), Collections.emptyMap())) {
|
||||
|
||||
final Path themePath = jarFileSystem
|
||||
.getPath(String.format(THEMES_DIR + "/%s", theme));
|
||||
|
||||
final Path filePath;
|
||||
if (path.charAt(0) == '/') {
|
||||
filePath = themePath.resolve(path.substring(1));
|
||||
} else {
|
||||
filePath = themePath.resolve(path);
|
||||
}
|
||||
|
||||
if (!Files.isRegularFile(filePath)) {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("The provided path \"%s\" in theme \"%s\" points "
|
||||
+ "not to a regular file.",
|
||||
path,
|
||||
theme));
|
||||
}
|
||||
|
||||
if (Files.exists(filePath)) {
|
||||
return Optional.of(Files.newInputStream(filePath));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
} catch (IOException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStreamForThemeFile(final String theme,
|
||||
final String path) {
|
||||
|
||||
throw new UnsupportedOperationException("Not supported by this"
|
||||
+ " implemetentation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsChanges() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsDraftThemes() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishTheme(final String theme) {
|
||||
LOGGER.info("StaticThemeProvider#publishTheme(String) called, but "
|
||||
+ "StaticThemeProvider does not support draft/live "
|
||||
+ "themes.");
|
||||
}
|
||||
|
||||
private URI getJarUri() {
|
||||
|
||||
LOGGER.debug("Getting URI of JAR...");
|
||||
|
||||
final String themesUrl = getClass().getResource(THEMES_DIR).toString();
|
||||
LOGGER.debug("Full URL of " + THEMES_DIR + " directory: {}", themesUrl);
|
||||
|
||||
final int index = themesUrl.indexOf('!');
|
||||
final String pathToJar = themesUrl.substring(0, index);
|
||||
|
||||
final URI uri = URI.create(pathToJar);
|
||||
LOGGER.debug("URI to JAR is \"%s\".", uri.toString());
|
||||
return uri;
|
||||
}
|
||||
|
||||
private boolean isTheme(final Path path) {
|
||||
|
||||
Objects.requireNonNull(path);
|
||||
|
||||
if (!Files.isDirectory(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Path manifestPathJson = path.resolve(THEME_MANIFEST_JSON);
|
||||
final Path manifestPathXml = path.resolve(THEME_MANIFEST_XML);
|
||||
|
||||
return Files.exists(manifestPathJson) || Files.exists(manifestPathXml);
|
||||
}
|
||||
|
||||
private ThemeInfo generateThemeInfo(final Path path) {
|
||||
|
||||
Objects.requireNonNull(path);
|
||||
|
||||
if (!Files.exists(path)) {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("The provided path \"%s\" does "
|
||||
+ "not exist.",
|
||||
path.toString()));
|
||||
}
|
||||
|
||||
final Path manifestPathJson = path.resolve(THEME_MANIFEST_JSON);
|
||||
final Path manifestPathXml = path.resolve(THEME_MANIFEST_XML);
|
||||
|
||||
final ThemeManifest manifest;
|
||||
if (Files.exists(manifestPathJson)) {
|
||||
manifest = themeManifests.loadManifest(manifestPathJson);
|
||||
} else if (Files.exists(manifestPathXml)) {
|
||||
manifest = themeManifests.loadManifest(manifestPathXml);
|
||||
} else {
|
||||
throw new IllegalArgumentException(String
|
||||
.format("The provided path \"%s\" does "
|
||||
+ "contain a theme manifest file.",
|
||||
path.toString()));
|
||||
}
|
||||
|
||||
final ThemeInfo themeInfo = new ThemeInfo();
|
||||
themeInfo.setVersion(ThemeVersion.LIVE);
|
||||
themeInfo.setProvider(getClass());
|
||||
themeInfo.setManifest(manifest);
|
||||
|
||||
return themeInfo;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -28,7 +28,11 @@ import org.libreccm.core.UnexpectedErrorException;
|
|||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.Serializable;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
|
@ -50,11 +54,12 @@ public class ThemeManifestUtil implements Serializable {
|
|||
* Reads the manifest file at {@code path}.
|
||||
*
|
||||
* @param path The path of the manifest file.
|
||||
*
|
||||
* @return The parsed manifest file.
|
||||
*/
|
||||
public ThemeManifest loadManifest(final Path path) {
|
||||
|
||||
final String pathStr = path.toString().toLowerCase(Locale.ROOT);
|
||||
// final String pathStr = path.toString().toLowerCase(Locale.ROOT);
|
||||
|
||||
final BufferedReader reader;
|
||||
try {
|
||||
|
|
@ -63,6 +68,72 @@ public class ThemeManifestUtil implements Serializable {
|
|||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
|
||||
return parseManifest(reader, path.toString());
|
||||
|
||||
// final ObjectMapper mapper;
|
||||
// if (pathStr.endsWith(THEME_MANIFEST_JSON)) {
|
||||
// mapper = new ObjectMapper();
|
||||
// } else if (pathStr.endsWith(THEME_MANIFEST_XML)) {
|
||||
// final JacksonXmlModule xmlModule = new JacksonXmlModule();
|
||||
// mapper = new XmlMapper(xmlModule);
|
||||
// } else {
|
||||
// throw new IllegalArgumentException(String
|
||||
// .format("The provided path \"%s\" does not point to a theme "
|
||||
// + "manifest file.",
|
||||
// path.toString()));
|
||||
// }
|
||||
//
|
||||
// mapper.registerModule(new JaxbAnnotationModule());
|
||||
//
|
||||
// final ThemeManifest manifest;
|
||||
// try {
|
||||
// manifest = mapper.readValue(reader, ThemeManifest.class);
|
||||
// } catch (IOException ex) {
|
||||
// throw new UnexpectedErrorException(ex);
|
||||
// }
|
||||
// return manifest;
|
||||
}
|
||||
|
||||
public ThemeManifest loadManifest(final InputStream inputStream,
|
||||
final String fileName) {
|
||||
|
||||
final InputStreamReader reader;
|
||||
try {
|
||||
reader = new InputStreamReader(inputStream, "UTF-8");
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
throw new UnexpectedErrorException(ex);
|
||||
}
|
||||
|
||||
return parseManifest(reader, fileName);
|
||||
|
||||
// final ObjectMapper mapper;
|
||||
// if (fileName.endsWith(THEME_MANIFEST_JSON)) {
|
||||
// mapper = new ObjectMapper();
|
||||
// } else if (fileName.endsWith(THEME_MANIFEST_XML)) {
|
||||
// final JacksonXmlModule xmlModule = new JacksonXmlModule();
|
||||
// mapper = new XmlMapper(xmlModule);
|
||||
// } else {
|
||||
// throw new IllegalArgumentException(String
|
||||
// .format("The provided path \"%s\" does not point to a theme "
|
||||
// + "manifest file.",
|
||||
// fileName));
|
||||
// }
|
||||
//
|
||||
// mapper.registerModule(new JaxbAnnotationModule());
|
||||
//
|
||||
// final ThemeManifest manifest;
|
||||
// try {
|
||||
// manifest = mapper.readValue(reader, ThemeManifest.class);
|
||||
// } catch (IOException ex) {
|
||||
// throw new UnexpectedErrorException(ex);
|
||||
// }
|
||||
// return manifest;
|
||||
}
|
||||
|
||||
private ThemeManifest parseManifest(final Reader reader, final String path) {
|
||||
|
||||
final String pathStr = path.toLowerCase(Locale.ROOT);
|
||||
|
||||
final ObjectMapper mapper;
|
||||
if (pathStr.endsWith(THEME_MANIFEST_JSON)) {
|
||||
mapper = new ObjectMapper();
|
||||
|
|
@ -73,7 +144,7 @@ public class ThemeManifestUtil implements Serializable {
|
|||
throw new IllegalArgumentException(String
|
||||
.format("The provided path \"%s\" does not point to a theme "
|
||||
+ "manifest file.",
|
||||
path.toString()));
|
||||
path));
|
||||
}
|
||||
|
||||
mapper.registerModule(new JaxbAnnotationModule());
|
||||
|
|
|
|||
|
|
@ -616,3 +616,12 @@ ui.user.roles.remove=Remove
|
|||
ui.role.parties.remove=Remove
|
||||
ui.admin.role_edit.description.label=Description
|
||||
ui.admin.tab.sites.title=Sites
|
||||
ui.admin.sites.add_new_site_link=Create new Site
|
||||
ui.admin.sites.no_sites=No Sites available
|
||||
ui.admin.sites.table.columns.domain.header=Domain
|
||||
ui.admin.sites.table.columns.default_site.header=Default Site?
|
||||
ui.admin.sites.table.columns.default_theme.header=Default theme
|
||||
ui.admin.sites.table.columns.applications.header=Applications
|
||||
ui.admin.sites.table.columns.delete.header=Delete
|
||||
ui.admin.sites.delete.confirm=Are you sure to delete this site?
|
||||
ui.admin.sites.table.columns.remove.label=Delete
|
||||
|
|
|
|||
|
|
@ -620,3 +620,12 @@ ui.user.roles.remove=Entfernen
|
|||
ui.role.parties.remove=Entfernen
|
||||
ui.admin.role_edit.description.label=Beschreibung
|
||||
ui.admin.tab.sites.title=Sites
|
||||
ui.admin.sites.add_new_site_link=Neue Site anlegen
|
||||
ui.admin.sites.no_sites=Keine Sites vorhanden
|
||||
ui.admin.sites.table.columns.domain.header=Domain
|
||||
ui.admin.sites.table.columns.default_site.header=Standard Site?
|
||||
ui.admin.sites.table.columns.default_theme.header=Standard Theme
|
||||
ui.admin.sites.table.columns.applications.header=Applications
|
||||
ui.admin.sites.table.columns.delete.header=L\u00f6schen
|
||||
ui.admin.sites.delete.confirm=Sind Sie sicher, dass Sie diese Site l\u00f6schen wollen?
|
||||
ui.admin.sites.table.columns.remove.label=L\u00f6schen
|
||||
|
|
|
|||
|
|
@ -613,3 +613,12 @@ ui.user.roles.remove=Remove
|
|||
ui.role.parties.remove=Remove
|
||||
ui.admin.role_edit.description.label=Description
|
||||
ui.admin.tab.sites.title=Sites
|
||||
ui.admin.sites.add_new_site_link=Create new Site
|
||||
ui.admin.sites.no_sites=No Sites available
|
||||
ui.admin.sites.table.columns.domain.header=Domain
|
||||
ui.admin.sites.table.columns.default_site.header=Default Site?
|
||||
ui.admin.sites.table.columns.default_theme.header=Default theme
|
||||
ui.admin.sites.table.columns.applications.header=Applications
|
||||
ui.admin.sites.table.columns.delete.header=Delete
|
||||
ui.admin.sites.delete.confirm=Are you sure to delete this site?
|
||||
ui.admin.sites.table.columns.remove.label=Delete
|
||||
|
|
|
|||
|
|
@ -604,3 +604,12 @@ ui.user.roles.remove=Remove
|
|||
ui.role.parties.remove=Remove
|
||||
ui.admin.role_edit.description.label=Description
|
||||
ui.admin.tab.sites.title=Sites
|
||||
ui.admin.sites.add_new_site_link=Create new Site
|
||||
ui.admin.sites.no_sites=No Sites available
|
||||
ui.admin.sites.table.columns.domain.header=Domain
|
||||
ui.admin.sites.table.columns.default_site.header=Default Site?
|
||||
ui.admin.sites.table.columns.default_theme.header=Default theme
|
||||
ui.admin.sites.table.columns.applications.header=Applications
|
||||
ui.admin.sites.table.columns.delete.header=Delete
|
||||
ui.admin.sites.delete.confirm=Are you sure to delete this site?
|
||||
ui.admin.sites.table.columns.remove.label=Delete
|
||||
|
|
|
|||
Loading…
Reference in New Issue