CCM NG:
* 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-94f89814c4dfccm-docs
parent
c615a2124c
commit
6e1b5e3fd6
|
|
@ -28,7 +28,6 @@ import org.reflections.scanners.ResourcesScanner;
|
||||||
import org.reflections.util.ClasspathHelper;
|
import org.reflections.util.ClasspathHelper;
|
||||||
import org.reflections.util.ConfigurationBuilder;
|
import org.reflections.util.ConfigurationBuilder;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
@ -36,15 +35,13 @@ import java.net.URI;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
@ -54,6 +51,8 @@ import javax.json.Json;
|
||||||
import javax.json.JsonArray;
|
import javax.json.JsonArray;
|
||||||
import javax.json.JsonObject;
|
import javax.json.JsonObject;
|
||||||
import javax.json.JsonReader;
|
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.");
|
"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("/"
|
final String indexFilePath = String.format("/"
|
||||||
+ THEMES_PACKAGE
|
+ THEMES_PACKAGE
|
||||||
|
|
@ -281,11 +280,30 @@ public class StaticThemeProvider implements ThemeProvider {
|
||||||
.getResourceAsStream(indexFilePath);
|
.getResourceAsStream(indexFilePath);
|
||||||
final JsonReader reader = Json.createReader(stream);
|
final JsonReader reader = Json.createReader(stream);
|
||||||
final JsonObject indexObj = reader.readObject();
|
final JsonObject indexObj = reader.readObject();
|
||||||
final JsonArray filesArray = indexObj.getJsonArray("files");
|
final JsonArray currentDir = indexObj.getJsonArray("files");
|
||||||
filesArray
|
currentDir.forEach(value -> LOGGER.warn(value.toString()));
|
||||||
.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
|
@Override
|
||||||
|
|
@ -379,4 +397,59 @@ public class StaticThemeProvider implements ThemeProvider {
|
||||||
return Files.exists(manifestPathJson) || Files.exists(manifestPathXml);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ import org.libreccm.theming.ThemeInfo;
|
||||||
import org.libreccm.theming.ThemeVersion;
|
import org.libreccm.theming.ThemeVersion;
|
||||||
import org.libreccm.theming.Themes;
|
import org.libreccm.theming.Themes;
|
||||||
import org.libreccm.webdav.ResponseStatus;
|
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.HRef;
|
||||||
import org.libreccm.webdav.xml.elements.MultiStatus;
|
import org.libreccm.webdav.xml.elements.MultiStatus;
|
||||||
import org.libreccm.webdav.xml.elements.Prop;
|
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.GetContentLength;
|
||||||
import org.libreccm.webdav.xml.properties.GetContentType;
|
import org.libreccm.webdav.xml.properties.GetContentType;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.ws.rs.OPTIONS;
|
import javax.ws.rs.OPTIONS;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
|
@ -72,6 +74,12 @@ public class ThemeFiles {
|
||||||
@Inject
|
@Inject
|
||||||
private Themes themes;
|
private Themes themes;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ServletContext servletContext;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private HttpServletRequest request;
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/{path}")
|
@Path("/{path}")
|
||||||
public Response getFile(@PathParam("theme") final String theme,
|
public Response getFile(@PathParam("theme") final String theme,
|
||||||
|
|
@ -137,9 +145,14 @@ public class ThemeFiles {
|
||||||
final List<ThemeFileInfo> fileInfos = themes.listThemesFiles(themeInfo,
|
final List<ThemeFileInfo> fileInfos = themes.listThemesFiles(themeInfo,
|
||||||
path);
|
path);
|
||||||
final MultiStatus result;
|
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));
|
result = new MultiStatus(buildWebDavResponse(fileInfo, uriInfo));
|
||||||
|
|
||||||
|
|
@ -150,7 +163,7 @@ public class ThemeFiles {
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
new PropStat(new Prop(new DisplayName(path),
|
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)));
|
new Status(javax.ws.rs.core.Response.Status.OK)));
|
||||||
|
|
||||||
final List<WebDavResponse> responses = new LinkedList<>();
|
final List<WebDavResponse> responses = new LinkedList<>();
|
||||||
|
|
@ -158,8 +171,8 @@ public class ThemeFiles {
|
||||||
|
|
||||||
final List<WebDavResponse> fileResponses = fileInfos
|
final List<WebDavResponse> fileResponses = fileInfos
|
||||||
.stream()
|
.stream()
|
||||||
.map(fileInfo -> buildWebDavResponse(fileInfo, uriInfo))
|
.map(fileInfo -> buildWebDavResponse(path, fileInfo))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
responses.addAll(fileResponses);
|
responses.addAll(fileResponses);
|
||||||
|
|
||||||
result = new MultiStatus(responses.toArray(new WebDavResponse[]{}));
|
result = new MultiStatus(responses.toArray(new WebDavResponse[]{}));
|
||||||
|
|
@ -174,11 +187,18 @@ public class ThemeFiles {
|
||||||
private WebDavResponse buildWebDavResponse(final ThemeFileInfo fileInfo,
|
private WebDavResponse buildWebDavResponse(final ThemeFileInfo fileInfo,
|
||||||
final UriInfo uriInfo) {
|
final UriInfo uriInfo) {
|
||||||
|
|
||||||
final PropStat propStat = new PropStat(
|
final PropStat propStat;
|
||||||
new Prop(new DisplayName(fileInfo.getName()),
|
if (fileInfo.isDirectory()) {
|
||||||
new GetContentLength(fileInfo.getSize()),
|
propStat = new PropStat(
|
||||||
new GetContentType(fileInfo.getMimeType())),
|
new Prop(new DisplayName(fileInfo.getName())),
|
||||||
new Status(javax.ws.rs.core.Response.Status.OK));
|
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(
|
final WebDavResponse response = new WebDavResponse(
|
||||||
new HRef(uriInfo.getRequestUri()),
|
new HRef(uriInfo.getRequestUri()),
|
||||||
|
|
@ -190,6 +210,38 @@ public class ThemeFiles {
|
||||||
return response;
|
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) {
|
private MediaType getMediaTypeFromPath(final String path) {
|
||||||
|
|
||||||
if (path.endsWith(".css")) {
|
if (path.endsWith(".css")) {
|
||||||
|
|
|
||||||
|
|
@ -18,11 +18,17 @@
|
||||||
*/
|
*/
|
||||||
package org.libreccm.theming.webdav;
|
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.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.ws.rs.ApplicationPath;
|
import javax.ws.rs.ApplicationPath;
|
||||||
import javax.ws.rs.core.Application;
|
import javax.ws.rs.core.Application;
|
||||||
|
import javax.xml.bind.JAXBException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -31,6 +37,8 @@ import javax.ws.rs.core.Application;
|
||||||
@ApplicationPath("/DAV/themes")
|
@ApplicationPath("/DAV/themes")
|
||||||
public class WebDAV extends Application {
|
public class WebDAV extends Application {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(WebDAV.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Class<?>> getClasses() {
|
public Set<Class<?>> getClasses() {
|
||||||
|
|
||||||
|
|
@ -40,4 +48,20 @@ public class WebDAV extends Application {
|
||||||
return classes;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ public final class PropFindFiniteDepth {
|
||||||
// For unmarshalling only.
|
// For unmarshalling only.
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PropFindFiniteDepth createInstance() {
|
private static PropFindFiniteDepth createSingleton() {
|
||||||
return PROPFIND_FINITE_DEPTH;
|
return PROPFIND_FINITE_DEPTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,12 @@ public class WebDavContextResolver implements ContextResolver<JAXBContext> {
|
||||||
|
|
||||||
private final JAXBIntrospector introspector;
|
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
|
* Creates an instance of this resolver, registering the provided custom XML
|
||||||
* Elements and Properties.
|
* Elements and Properties.
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ import org.libreccm.webdav.xml.elements.PropStat;
|
||||||
import org.libreccm.webdav.xml.elements.PropertyUpdate;
|
import org.libreccm.webdav.xml.elements.PropertyUpdate;
|
||||||
import org.libreccm.webdav.xml.elements.Remove;
|
import org.libreccm.webdav.xml.elements.Remove;
|
||||||
import org.libreccm.webdav.xml.elements.ResponseDescription;
|
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.Shared;
|
||||||
import org.libreccm.webdav.xml.elements.Status;
|
import org.libreccm.webdav.xml.elements.Status;
|
||||||
import org.libreccm.webdav.xml.elements.TimeOut;
|
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.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.swing.text.Utilities;
|
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.xml.bind.JAXBContext;
|
import javax.xml.bind.JAXBContext;
|
||||||
import javax.xml.bind.JAXBException;
|
import javax.xml.bind.JAXBException;
|
||||||
|
|
@ -148,7 +147,8 @@ final class WebDavJAXBContextBuilder {
|
||||||
ResourceType.class,
|
ResourceType.class,
|
||||||
Response.class,
|
Response.class,
|
||||||
ResponseDescription.class,
|
ResponseDescription.class,
|
||||||
Set.class, Shared.class,
|
Set.class,
|
||||||
|
Shared.class,
|
||||||
Status.class,
|
Status.class,
|
||||||
SupportedLock.class,
|
SupportedLock.class,
|
||||||
TimeOut.class,
|
TimeOut.class,
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@
|
||||||
*/
|
*/
|
||||||
package org.libreccm.webdav.xml.elements;
|
package org.libreccm.webdav.xml.elements;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
import javax.xml.bind.annotation.XmlType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WebDAV collection XML Element.
|
* WebDAV collection XML Element.
|
||||||
*
|
*
|
||||||
|
|
@ -38,6 +41,9 @@ package org.libreccm.webdav.xml.elements;
|
||||||
* Distributed Authoring and Versioning (WebDAV)"</a>
|
* Distributed Authoring and Versioning (WebDAV)"</a>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@XmlRootElement
|
||||||
|
@XmlType(factoryMethod = "createSingleton")
|
||||||
|
|
||||||
public final class Collection {
|
public final class Collection {
|
||||||
|
|
||||||
private Collection() {
|
private Collection() {
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,11 @@
|
||||||
"mimeType": "text/x-java-properties"
|
"mimeType": "text/x-java-properties"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "theme.json",
|
||||||
|
"isDirectory": false,
|
||||||
|
"mimeType": "application/json"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue