Integration of CCM themes and EE/MVC Krazo

Former-commit-id: 402ea5614d
pull/6/head
Jens Pelzetter 2020-09-13 12:08:59 +02:00
parent b0f9935685
commit a21a31f76e
5 changed files with 375 additions and 0 deletions

View File

@ -0,0 +1,90 @@
/*
* Copyright (C) 2020 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.mvc.freemarker;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import javax.servlet.ServletContext;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
/**
* A copy of the {@link TemplateLoader} used by Krazo.
*
* The {@code TemplateLoader} used by Krazo is defined as inner class. This
* class provides the same behaviour as "real" class so that we can use it with
* Freemarker {@link MultiTemplateLoader}.
*
* As extension this implementation of the {@code TemplateLoader} interface will
* not process template paths which start with {@code @themes/} or
* {@code /@themes/}. These path are processed by the templates loaders for the
* theming system.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class KrazoTemplateLoader implements TemplateLoader {
private final ServletContext servletContext;
public KrazoTemplateLoader(final ServletContext servletContext) {
super();
this.servletContext = servletContext;
}
@Override
public Object findTemplateSource(final String name) throws IOException {
if (name.startsWith("@themes") || name.startsWith("/@themes")) {
return null;
} else {
// Freemarker drops "/"
return servletContext.getResourceAsStream(
String.format("/%s", name)
);
}
}
@Override
public long getLastModified(final Object templateSource) {
return -1;
}
@Override
public Reader getReader(
final Object templateSource, final String encoding
) throws IOException {
return new InputStreamReader((InputStream) templateSource, encoding);
}
@Override
public void closeTemplateSource(
final Object templateSource
) throws IOException {
final InputStream inputStream = (InputStream) templateSource;
inputStream.close();
}
}

View File

@ -0,0 +1,89 @@
/*
* Copyright (C) 2020 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.mvc.freemarker;
import freemarker.cache.ClassTemplateLoader;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.cache.WebappTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.TemplateExceptionHandler;
import org.eclipse.krazo.engine.ViewEngineConfig;
import org.eclipse.krazo.ext.freemarker.DefaultConfigurationProducer;
import org.libreccm.theming.Themes;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Specializes;
import javax.inject.Inject;
import javax.servlet.ServletContext;
import javax.ws.rs.Produces;
/**
* Extends the default configuration for Freemarker of Eclipse Krazo to
* support Freemarker templates in CCM themes.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@ApplicationScoped
public class MvcFreemarkerConfigurationProducer
extends DefaultConfigurationProducer {
@Inject
private ServletContext servletContext;
@Inject
private Themes themes;
@Produces
@ViewEngineConfig
@Specializes
@Override
public Configuration getConfiguration() {
final Configuration configuration = new Configuration(
Configuration.VERSION_2_3_30
);
configuration.setDefaultEncoding("UTF-8");
configuration.setTemplateExceptionHandler(
TemplateExceptionHandler.RETHROW_HANDLER
);
configuration.setLogTemplateExceptions(false);
configuration.setWrapUncheckedExceptions(false);
configuration.setLocalizedLookup(false);
configuration.setTemplateLoader(
new MultiTemplateLoader(
new TemplateLoader[]{
new KrazoTemplateLoader(servletContext),
new ThemesTemplateLoader(themes),
// For loading Freemarker macro libraries from WEB-INF
// resources
new WebappTemplateLoader(
servletContext, "/themes/freemarker"
),
// For loading Freemarker macro libraries from classpath
// resources
new ClassTemplateLoader(getClass(), "/themes/freemarker")
}
)
);
return configuration;
}
}

View File

@ -0,0 +1,149 @@
/*
* Copyright (C) 2020 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.mvc.freemarker;
import freemarker.cache.TemplateLoader;
import org.libreccm.theming.ThemeInfo;
import org.libreccm.theming.ThemeVersion;
import org.libreccm.theming.Themes;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Arrays;
import java.util.Optional;
/**
* Loads Freemarker templates from a theme.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ThemesTemplateLoader implements TemplateLoader {
private final Themes themes;
public ThemesTemplateLoader(final Themes themes) {
this.themes = themes;
}
/**
* Loads the template from a theme. The path of the theme file must follow
* the following format:
*
* {@code @themes/$themeName/$version/$path/$to/$file}
*
* The {@code @themes} prefix is mandantory. {@code $themeName} is the name
* of the theme from which the template is loaded. {@code $version} is the
* version of the theme to use. This token is converted to
* {@link ThemeVersion}. Valid values are therefore {@code DRAFT} and
* {@code LIVE}. The remainder of the path is the path to the file inside the
* theme.
*
* @param path The path of the file. The path must include the theme and its
* version.
*
* @return An {@link InputStream} for the template if the template was found
* in the theme. Otherwise {@code null} is returned.
*
* @throws IOException
*/
@Override
public Object findTemplateSource(final String path) throws IOException {
if (path.startsWith("@themes") || path.startsWith("/@themes")) {
final String[] tokens;
if (path.startsWith("/")) {
tokens = path.substring(1).split("/");
} else {
tokens = path.split("/");
}
return findTemplateSource(tokens);
} else {
return null;
}
}
private InputStream findTemplateSource(final String[] tokens) {
if (tokens.length >= 4) {
final String themeName = tokens[1];
final ThemeVersion themeVersion = ThemeVersion
.valueOf(tokens[2]);
final String filePath = String.join(
"/",
Arrays.copyOfRange(
tokens, 3, tokens.length, String[].class
)
);
return findTemplateSource(themeName, themeVersion, filePath);
} else {
return null;
}
}
private InputStream findTemplateSource(
final String themeName,
final ThemeVersion themeVersion,
final String filePath
) {
final Optional<ThemeInfo> themeInfo = themes.getTheme(
themeName, themeVersion
);
if (themeInfo.isPresent()) {
return findTemplateSource(themeInfo.get(), filePath);
} else {
return null;
}
}
private InputStream findTemplateSource(
final ThemeInfo themeInfo, final String filePath
) {
final Optional<InputStream> source = themes.getFileFromTheme(
themeInfo, filePath
);
if (source.isPresent()) {
return source.get();
} else {
return null;
}
}
@Override
public long getLastModified(Object templateSource) {
return -1;
}
@Override
public Reader getReader(
final Object templateSource, final String encoding
) throws IOException {
final InputStream inputStream = (InputStream) templateSource;
return new InputStreamReader(inputStream, encoding);
}
@Override
public void closeTemplateSource(
final Object templateSource
) throws IOException {
final InputStream inputStream = (InputStream) templateSource;
inputStream.close();
}
}

View File

@ -0,0 +1,22 @@
/*
* Copyright (C) 2020 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
*/
/**
* Integration of the Freemarker View Engine of Eclipse Krazo with LibreCCM.
*/
package org.libreccm.mvc.freemarker;

View File

@ -0,0 +1,25 @@
/*
* Copyright (C) 2020 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
*/
/**
* The classes in this package integrate LibreCCM with Jakarta EE MVC and its
* reference implementation Eclipse Krazo.
*
* @see https://www.mvc-spec.org/
*/
package org.libreccm.mvc;