ConfigNamesServlet.java
/*
* #%L
* wcm.io
* %%
* Copyright (C) 2016 wcm.io
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package io.wcm.caconfig.editor.impl;
import static io.wcm.caconfig.editor.impl.JsonMapper.OBJECT_MAPPER;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.caconfig.management.ConfigurationData;
import org.apache.sling.caconfig.management.ConfigurationManager;
import org.apache.sling.caconfig.resource.ConfigurationResourceResolver;
import org.apache.sling.caconfig.spi.metadata.ConfigurationMetadata;
import org.apache.sling.servlets.annotations.SlingServletResourceTypes;
import org.jetbrains.annotations.NotNull;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import io.wcm.caconfig.editor.impl.data.confignames.ConfigNameItem;
import io.wcm.caconfig.editor.impl.data.confignames.ConfigNamesResponse;
/**
* Get configuration names with labels and descriptions.
*/
@Component(service = Servlet.class)
@SlingServletResourceTypes(
resourceTypes = "/apps/wcm-io/caconfig/editor/components/page/editor",
selectors = ConfigNamesServlet.SELECTOR,
extensions = "json",
methods = "GET")
public class ConfigNamesServlet extends SlingSafeMethodsServlet {
private static final long serialVersionUID = 1L;
/**
* Selector
*/
public static final String SELECTOR = "configNames";
@Reference
private ConfigurationManager configManager;
@Reference
private ConfigurationResourceResolver configurationResourceResolver;
@Reference
private EditorConfig editorConfig;
@Reference(policy = ReferencePolicy.STATIC, cardinality = ReferenceCardinality.OPTIONAL,
policyOption = ReferencePolicyOption.GREEDY)
private ConfigurationEditorFilterService configurationEditorFilterService;
@Override
protected void doGet(@NotNull SlingHttpServletRequest request, @NotNull SlingHttpServletResponse response) throws ServletException, IOException {
if (!editorConfig.isEnabled()) {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return;
}
Resource contextResource = request.getResource();
ConfigNamesResponse result = new ConfigNamesResponse();
result.setContextPath(getContextPath(contextResource));
result.setConfigNames(getConfigNames(contextResource));
response.setContentType("application/json;charset=" + StandardCharsets.UTF_8.name());
response.getWriter().write(OBJECT_MAPPER.writeValueAsString(result));
}
private String getContextPath(Resource contextResource) {
return configurationResourceResolver.getContextPath(contextResource);
}
private Collection<ConfigNameItem> getConfigNames(Resource contextResource) {
SortedSet<String> configNames = configManager.getConfigurationNames();
SortedSet<ConfigNameItem> sortedResult = new TreeSet<>((ConfigNameItem o1, ConfigNameItem o2) -> {
String label1 = o1.getLabel();
String label2 = o2.getLabel();
if (StringUtils.equals(label1, label2)) {
String configName1 = o1.getConfigName();
String configName2 = o2.getConfigName();
return configName1.compareTo(configName2);
}
return label1.compareTo(label2);
});
for (String configName : configNames) {
ConfigurationMetadata metadata = configManager.getConfigurationMetadata(configName);
if (metadata != null) {
ConfigNameItem item = new ConfigNameItem();
item.setConfigName(configName);
item.setLabel(metadata.getLabel());
item.setDescription(metadata.getDescription());
item.setCollection(metadata.isCollection());
ConfigurationState state = getConfigurationState(contextResource, configName, metadata.isCollection());
item.setExists(state.exists);
item.setInherited(state.inherited);
item.setOverridden(state.overridden);
item.setAllowAdd(allowAdd(contextResource, configName));
sortedResult.add(item);
}
}
return sortedResult;
}
private boolean allowAdd(Resource contextResource, String configName) {
if (configurationEditorFilterService == null) {
return true;
}
return configurationEditorFilterService.allowAdd(contextResource, configName);
}
private ConfigurationState getConfigurationState(Resource contextResource, String configName, boolean collection) {
ConfigurationState result = new ConfigurationState();
if (collection) {
Collection<ConfigurationData> configs = configManager.getConfigurationCollection(contextResource, configName).getItems();
result.exists = !configs.isEmpty();
result.inherited = configs.stream().filter(ConfigurationData::isInherited).findAny().isPresent();
result.overridden = configs.stream().filter(ConfigurationData::isOverridden).findAny().isPresent();
}
else {
ConfigurationData config = configManager.getConfiguration(contextResource, configName);
if (config != null) {
result.exists = config.getResourcePath() != null || config.isOverridden();
result.inherited = config.isInherited();
result.overridden = config.isOverridden();
}
}
return result;
}
private static final class ConfigurationState {
private boolean exists;
private boolean inherited;
private boolean overridden;
}
}