diff --git a/ccm-core/pom.xml b/ccm-core/pom.xml
index 9185c46d8..89a3e444e 100644
--- a/ccm-core/pom.xml
+++ b/ccm-core/pom.xml
@@ -196,6 +196,12 @@
test
+
+ org.reflections
+ reflections
+ 0.9.11
+
+
org.primefaces
primefaces
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/sites/SitesTab.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/sites/SitesTab.java
index 150e8e10e..0df79b296 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/admin/sites/SitesTab.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/sites/SitesTab.java
@@ -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);
@@ -67,15 +71,15 @@ public class SitesTab extends LayoutPanel {
@Override
public void register(final Page page) {
-
+
super.register(page);
-
+
page.addGlobalStateParam(selectedSiteId.getStateParameter());
-
+
page.setVisibleDefault(sitesTable, true);
page.setVisibleDefault(sitesForm, false);
}
-
+
protected void showSiteForm(final PageState state) {
sitesTable.setVisible(state, false);
sitesForm.setVisible(state, true);
diff --git a/ccm-core/src/main/java/org/libreccm/theming/StaticThemeProvider.java b/ccm-core/src/main/java/org/libreccm/theming/StaticThemeProvider.java
index 2932d8a3f..23b36023c 100644
--- a/ccm-core/src/main/java/org/libreccm/theming/StaticThemeProvider.java
+++ b/ccm-core/src/main/java/org/libreccm/theming/StaticThemeProvider.java
@@ -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 Jens Pelzetter
*/
@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 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 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 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 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 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 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 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 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.
}
}
diff --git a/ccm-core/src/main/java/org/libreccm/theming/StaticThemeProvider.java.off b/ccm-core/src/main/java/org/libreccm/theming/StaticThemeProvider.java.off
new file mode 100644
index 000000000..2932d8a3f
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/theming/StaticThemeProvider.java.off
@@ -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 Jens Pelzetter
+ */
+@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 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 getLiveThemes() {
+ return getThemes();
+ }
+
+ @Override
+ public Optional 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 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 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 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 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;
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/theming/manifest/ThemeManifestUtil.java b/ccm-core/src/main/java/org/libreccm/theming/manifest/ThemeManifestUtil.java
index 1f96a18be..b2ef9883c 100644
--- a/ccm-core/src/main/java/org/libreccm/theming/manifest/ThemeManifestUtil.java
+++ b/ccm-core/src/main/java/org/libreccm/theming/manifest/ThemeManifestUtil.java
@@ -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;
@@ -38,7 +42,7 @@ import javax.enterprise.context.RequestScoped;
/**
* A Utility class for loading them manifest file of a theme.
- *
+ *
* @author Jens Pelzetter
*/
@RequestScoped
@@ -48,13 +52,14 @@ 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());
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties
index b77fb1bc7..bbd26aa4d 100644
--- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties
+++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties
@@ -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
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties
index 01f2ad4e3..912a54293 100644
--- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties
+++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties
@@ -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
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties
index 08e37f152..a54391731 100755
--- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties
+++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties
@@ -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
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties
index 06fa3f844..4e7788c21 100755
--- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties
+++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties
@@ -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