From d45bfb5095b62201ae5a9d8398ffd217236732a8 Mon Sep 17 00:00:00 2001 From: jensp Date: Tue, 31 Oct 2017 19:12:26 +0000 Subject: [PATCH] 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-94f89814c4df Former-commit-id: 6edf8e561faa318585a8ec6d34956216adcd19e0 --- ccm-core/pom.xml | 6 + .../arsdigita/ui/admin/sites/SitesTab.java | 12 +- .../libreccm/theming/StaticThemeProvider.java | 408 +++++++----------- .../theming/StaticThemeProvider.java.off | 376 ++++++++++++++++ .../theming/manifest/ThemeManifestUtil.java | 79 +++- .../ui/admin/AdminResources.properties | 9 + .../ui/admin/AdminResources_de.properties | 9 + .../ui/admin/AdminResources_en.properties | 9 + .../ui/admin/AdminResources_fr.properties | 9 + 9 files changed, 648 insertions(+), 269 deletions(-) create mode 100644 ccm-core/src/main/java/org/libreccm/theming/StaticThemeProvider.java.off 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