* listThemeFiles implementation for StaticThemeProvider
* profind method for Themes WebDAV service


git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5435 8810af33-2d31-482b-a856-94f89814c4df
ccm-docs
jensp 2018-05-17 13:19:46 +00:00
parent c615a2124c
commit 6e1b5e3fd6
8 changed files with 194 additions and 28 deletions

View File

@ -28,7 +28,6 @@ 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;
@ -36,15 +35,13 @@ import java.net.URI;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
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.logging.Level;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@ -54,6 +51,8 @@ import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonStructure;
import javax.json.JsonValue;
/**
*
@ -271,7 +270,7 @@ public class StaticThemeProvider implements ThemeProvider {
"The name of the theme can't be empty.");
}
final String[] pathTokens = path.split("/");
final List<String> pathTokens = Arrays.asList(path.split("/"));
final String indexFilePath = String.format("/"
+ THEMES_PACKAGE
@ -281,11 +280,30 @@ public class StaticThemeProvider implements ThemeProvider {
.getResourceAsStream(indexFilePath);
final JsonReader reader = Json.createReader(stream);
final JsonObject indexObj = reader.readObject();
final JsonArray filesArray = indexObj.getJsonArray("files");
filesArray
.forEach(value -> LOGGER.warn(value.toString()));
final JsonArray currentDir = indexObj.getJsonArray("files");
currentDir.forEach(value -> LOGGER.warn(value.toString()));
throw new UnsupportedOperationException();
final Optional<JsonObject> targetFile = findFile(pathTokens,
currentDir);
final List<ThemeFileInfo> result;
if (targetFile.isPresent()) {
if (targetFile.get().getBoolean("isDirectory")) {
final JsonArray files = targetFile.get().getJsonArray("files");
result = files
.stream()
.map(value -> generateFileInfo((JsonObject) value))
.collect(Collectors.toList());
} else {
final ThemeFileInfo fileInfo = generateFileInfo(
targetFile.get());
result = new ArrayList<>();
result.add(fileInfo);
}
} else {
result = Collections.emptyList();
}
return result;
}
@Override
@ -379,4 +397,59 @@ public class StaticThemeProvider implements ThemeProvider {
return Files.exists(manifestPathJson) || Files.exists(manifestPathXml);
}
private Optional<JsonObject> findFile(final List<String> path,
final JsonArray currentDirectory) {
Objects.requireNonNull(path);
Objects.requireNonNull(currentDirectory);
if (path.isEmpty()) {
return Optional.empty();
}
final String fileName = path.get(0);
final Optional<JsonObject> fileData = currentDirectory
.stream()
.map(value -> (JsonObject) value)
.filter(value -> filterFileData(value, fileName))
.findAny();
if (path.size() == 1) {
return fileData;
} else {
if (fileData.get().getBoolean("isDirectory")) {
return findFile(path.subList(1, path.size()),
fileData.get().getJsonArray("files"));
} else {
return Optional.empty();
}
}
}
private boolean filterFileData(final JsonObject fileData,
final String fileName) {
return fileData.getString("name").equals(fileName);
}
private ThemeFileInfo generateFileInfo(final JsonObject fileData) {
Objects.requireNonNull(fileData);
final ThemeFileInfo fileInfo = new ThemeFileInfo();
fileInfo.setName(fileData.getString("name"));
if (fileData.getBoolean("isDirectory")) {
fileInfo.setDirectory(true);
} else {
fileInfo.setDirectory(false);
fileInfo.setMimeType(fileData.getString("mimeType"));
}
fileInfo.setWritable(false);
if (fileData.getJsonNumber("size") != null) {
fileInfo.setSize(fileData.getJsonNumber("size").longValue());
}
return fileInfo;
}
}

View File

@ -41,6 +41,7 @@ import org.libreccm.theming.ThemeInfo;
import org.libreccm.theming.ThemeVersion;
import org.libreccm.theming.Themes;
import org.libreccm.webdav.ResponseStatus;
import org.libreccm.webdav.xml.elements.Collection;
import org.libreccm.webdav.xml.elements.HRef;
import org.libreccm.webdav.xml.elements.MultiStatus;
import org.libreccm.webdav.xml.elements.Prop;
@ -51,11 +52,12 @@ import org.libreccm.webdav.xml.properties.DisplayName;
import org.libreccm.webdav.xml.properties.GetContentLength;
import org.libreccm.webdav.xml.properties.GetContentType;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
@ -72,6 +74,12 @@ public class ThemeFiles {
@Inject
private Themes themes;
@Inject
private ServletContext servletContext;
@Inject
private HttpServletRequest request;
@GET
@Path("/{path}")
public Response getFile(@PathParam("theme") final String theme,
@ -137,9 +145,14 @@ public class ThemeFiles {
final List<ThemeFileInfo> fileInfos = themes.listThemesFiles(themeInfo,
path);
final MultiStatus result;
if (fileInfos.size() == 1) {
if (fileInfos.isEmpty()) {
throw new NotFoundException(String.format(
"No file \"%s\" in theme \"%s\".",
path,
theme));
} else if (fileInfos.size() == 1) {
final ThemeFileInfo fileInfo = fileInfos.get(1);
final ThemeFileInfo fileInfo = fileInfos.get(0);
result = new MultiStatus(buildWebDavResponse(fileInfo, uriInfo));
@ -150,7 +163,7 @@ public class ThemeFiles {
null,
null,
new PropStat(new Prop(new DisplayName(path),
org.libreccm.webdav.xml.elements.Collection.COLLECTION),
Collection.COLLECTION),
new Status(javax.ws.rs.core.Response.Status.OK)));
final List<WebDavResponse> responses = new LinkedList<>();
@ -158,8 +171,8 @@ public class ThemeFiles {
final List<WebDavResponse> fileResponses = fileInfos
.stream()
.map(fileInfo -> buildWebDavResponse(fileInfo, uriInfo))
.collect(Collectors.toList());
.map(fileInfo -> buildWebDavResponse(path, fileInfo))
.collect(Collectors.toList());
responses.addAll(fileResponses);
result = new MultiStatus(responses.toArray(new WebDavResponse[]{}));
@ -174,11 +187,18 @@ public class ThemeFiles {
private WebDavResponse buildWebDavResponse(final ThemeFileInfo fileInfo,
final UriInfo uriInfo) {
final PropStat propStat = new PropStat(
new Prop(new DisplayName(fileInfo.getName()),
new GetContentLength(fileInfo.getSize()),
new GetContentType(fileInfo.getMimeType())),
new Status(javax.ws.rs.core.Response.Status.OK));
final PropStat propStat;
if (fileInfo.isDirectory()) {
propStat = new PropStat(
new Prop(new DisplayName(fileInfo.getName())),
new Status(javax.ws.rs.core.Response.Status.OK));
} else {
propStat = new PropStat(
new Prop(new DisplayName(fileInfo.getName()),
new GetContentLength(fileInfo.getSize()),
new GetContentType(fileInfo.getMimeType())),
new Status(javax.ws.rs.core.Response.Status.OK));
}
final WebDavResponse response = new WebDavResponse(
new HRef(uriInfo.getRequestUri()),
@ -190,6 +210,38 @@ public class ThemeFiles {
return response;
}
private WebDavResponse buildWebDavResponse(final String basePath,
final ThemeFileInfo fileInfo) {
final PropStat propStat;
if (fileInfo.isDirectory()) {
propStat = new PropStat(
new Prop(new DisplayName(fileInfo.getName())),
new Status(javax.ws.rs.core.Response.Status.OK));
} else {
propStat = new PropStat(
new Prop(new DisplayName(fileInfo.getName()),
new GetContentLength(fileInfo.getSize()),
new GetContentType(fileInfo.getMimeType())),
new Status(javax.ws.rs.core.Response.Status.OK));
}
final WebDavResponse response = new WebDavResponse(
new HRef(String.format("%s://%s:%d%s/DAV/themes/%s/%s",
request.getScheme(),
request.getServerName(),
request.getServerPort(),
servletContext.getContextPath(),
basePath,
fileInfo.getName())),
null,
null,
null,
propStat);
return response;
}
private MediaType getMediaTypeFromPath(final String path) {
if (path.endsWith(".css")) {

View File

@ -18,11 +18,17 @@
*/
package org.libreccm.theming.webdav;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.libreccm.core.UnexpectedErrorException;
import org.libreccm.webdav.xml.WebDavContextResolver;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import javax.xml.bind.JAXBException;
/**
*
@ -31,6 +37,8 @@ import javax.ws.rs.core.Application;
@ApplicationPath("/DAV/themes")
public class WebDAV extends Application {
private static final Logger LOGGER = LogManager.getLogger(WebDAV.class);
@Override
public Set<Class<?>> getClasses() {
@ -40,4 +48,20 @@ public class WebDAV extends Application {
return classes;
}
@Override
public Set<Object> getSingletons() {
LOGGER.warn("Adding singletons...");
final HashSet<Object> singletons = new HashSet<>();
try {
singletons.add(new WebDavContextResolver());
} catch (JAXBException ex) {
throw new UnexpectedErrorException(ex);
}
LOGGER.warn("Added singletons");
return singletons;
}
}

View File

@ -61,7 +61,7 @@ public final class PropFindFiniteDepth {
// For unmarshalling only.
}
private static PropFindFiniteDepth createInstance() {
private static PropFindFiniteDepth createSingleton() {
return PROPFIND_FINITE_DEPTH;
}

View File

@ -60,6 +60,12 @@ public class WebDavContextResolver implements ContextResolver<JAXBContext> {
private final JAXBIntrospector introspector;
public WebDavContextResolver() throws JAXBException {
this.context = WebDavJAXBContextBuilder.build();
this.introspector = this.context.createJAXBIntrospector();
}
/**
* Creates an instance of this resolver, registering the provided custom XML
* Elements and Properties.

View File

@ -48,6 +48,7 @@ import org.libreccm.webdav.xml.elements.PropStat;
import org.libreccm.webdav.xml.elements.PropertyUpdate;
import org.libreccm.webdav.xml.elements.Remove;
import org.libreccm.webdav.xml.elements.ResponseDescription;
import org.libreccm.webdav.xml.elements.Set;
import org.libreccm.webdav.xml.elements.Shared;
import org.libreccm.webdav.xml.elements.Status;
import org.libreccm.webdav.xml.elements.TimeOut;
@ -66,9 +67,7 @@ import org.libreccm.webdav.xml.properties.SupportedLock;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import javax.swing.text.Utilities;
import javax.ws.rs.core.Response;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
@ -148,7 +147,8 @@ final class WebDavJAXBContextBuilder {
ResourceType.class,
Response.class,
ResponseDescription.class,
Set.class, Shared.class,
Set.class,
Shared.class,
Status.class,
SupportedLock.class,
TimeOut.class,

View File

@ -18,6 +18,9 @@
*/
package org.libreccm.webdav.xml.elements;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* WebDAV collection XML Element.
*
@ -38,6 +41,9 @@ package org.libreccm.webdav.xml.elements;
* Distributed Authoring and Versioning (WebDAV)"</a>
*
*/
@XmlRootElement
@XmlType(factoryMethod = "createSingleton")
public final class Collection {
private Collection() {

View File

@ -57,6 +57,11 @@
"mimeType": "text/x-java-properties"
}
]
},
{
"name": "theme.json",
"isDirectory": false,
"mimeType": "application/json"
}
]
}