Integrate Krazo Facelets View Engine with LibreCCM themes

ccm-docs
Jens Pelzetter 2020-09-13 16:51:50 +02:00
parent 5fec534c14
commit aa0a21f948
4 changed files with 280 additions and 0 deletions

View File

@ -0,0 +1,104 @@
/*
* 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.facelets;
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.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.Objects;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
class CcmThemeUrlConnection extends URLConnection {
private final Themes themes;
private final String path;
private ThemeInfo themeInfo;
private String filePath;
public CcmThemeUrlConnection(final Themes themes, final URL url) {
super(url);
this.themes = themes;
final String urlStr = url.toString();
if (urlStr.startsWith("/")) {
path = urlStr.substring(1);
} else {
path = urlStr;
}
}
@Override
public void connect() throws IOException {
final String[] tokens = path.split("/");
if (tokens.length >= 4) {
final String themeName = tokens[1];
final ThemeVersion version = ThemeVersion.valueOf(tokens[2]);
filePath = String.join(
"/",
Arrays.copyOfRange(
tokens, 3, tokens.length, String[].class
)
);
themeInfo = themes.getTheme(themeName, version)
.orElseThrow(() -> new IOException(
String.format(
"Theme %s is available as %s version.",
themeName,
Objects.toString(version)
)));
} else {
throw new IOException(
"Illegal URL for loading a facelets template from a theme."
);
}
}
@Override
public InputStream getInputStream() throws IOException {
return themes
.getFileFromTheme(themeInfo, filePath)
.orElseThrow(
() -> new IOException(
String.format(
"Template %s not found in %s version of the theme %s.",
filePath,
themeInfo.getVersion(),
themeInfo.getName()
)
)
);
}
}

View File

@ -0,0 +1,45 @@
/*
* 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.facelets;
import org.libreccm.theming.Themes;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
class CcmThemeUrlStreamHandler extends URLStreamHandler {
private final Themes themes;
public CcmThemeUrlStreamHandler(final Themes themes) {
this.themes = themes;
}
@Override
protected URLConnection openConnection(final URL url) throws IOException {
return new CcmThemeUrlConnection(themes, url);
}
}

View File

@ -0,0 +1,59 @@
/*
* 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.facelets;
import org.libreccm.core.UnexpectedErrorException;
import org.libreccm.theming.Themes;
import java.net.MalformedURLException;
import java.net.URL;
import javax.faces.application.ViewResource;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
class CcmThemeViewResource extends ViewResource {
private final String path;
private final Themes themes;
public CcmThemeViewResource(final Themes themes, final String path) {
this.themes = themes;
this.path = path;
}
@Override
public URL getURL() {
try {
return new URL(
"libreccm",
null,
0,
path,
new CcmThemeUrlStreamHandler(themes)
);
} catch (MalformedURLException ex) {
throw new UnexpectedErrorException(ex);
}
}
}

View File

@ -0,0 +1,72 @@
/*
* 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.facelets;
import org.libreccm.theming.Themes;
import javax.faces.application.ResourceHandler;
import javax.faces.application.ResourceHandlerWrapper;
import javax.faces.application.ViewResource;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
/**
* A Facelets resource handler that loads Facelets templates from LibreCCM
* themes.
*
* This handler only works for view resources. Only resource path which are
* starting with {@code @themes} or {@code /@themes} are used processed. All
* other paths are delegated to the wrapped resource handler.
*
* To enable this resource handler to following snippet must be present in the
* {@code faces-config.xml} file of the WAR (bundle):
*
* <pre>
* &lt;application&gt;
&tl;resource-handler&gt;org.libreccm.ui.CcmFaceletsResourceHandler&lt;/resource-handler&gt;
&lt;/application&gt;
* </pre>
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class CcmViewResourceHandler extends ResourceHandlerWrapper {
@Inject
private Themes themes;
private final ResourceHandler wrapped;
public CcmViewResourceHandler(final ResourceHandler wrapped) {
super(wrapped);
this.wrapped = wrapped;
}
@Override
public ViewResource createViewResource(
final FacesContext context, final String path
) {
if (path.startsWith("@themes") || path.startsWith("/@themes")) {
return new CcmThemeViewResource(themes, path);
} else {
return super.createViewResource(context, path);
}
}
}