blob: 8631e3ae4b0c3ad7b6559fd88ce19ae909d0e075 [file] [log] [blame]
/**
* 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.
*/
package org.apache.aries.cdi.container.internal.command;
import static java.util.stream.Collectors.*;
import java.util.Collection;
import java.util.Formatter;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.apache.aries.cdi.container.internal.CCR;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.service.cdi.ComponentType;
import org.osgi.service.cdi.MaximumCardinality;
import org.osgi.service.cdi.runtime.dto.ActivationDTO;
import org.osgi.service.cdi.runtime.dto.ComponentDTO;
import org.osgi.service.cdi.runtime.dto.ComponentInstanceDTO;
import org.osgi.service.cdi.runtime.dto.ConfigurationDTO;
import org.osgi.service.cdi.runtime.dto.ContainerDTO;
import org.osgi.service.cdi.runtime.dto.ReferenceDTO;
import org.osgi.service.cdi.runtime.dto.template.ActivationTemplateDTO;
import org.osgi.service.cdi.runtime.dto.template.ComponentTemplateDTO;
import org.osgi.service.cdi.runtime.dto.template.ConfigurationTemplateDTO;
import org.osgi.service.cdi.runtime.dto.template.ReferenceTemplateDTO;
public class CDICommand {
public CDICommand(CCR ccr) {
_ccr = ccr;
}
public String info(Bundle bundle) {
try (Formatter f = new Formatter()) {
Collection<ContainerDTO> containerDTOs = _ccr.getContainerDTOs(bundle);
if (containerDTOs.isEmpty()) {
f.format(NO_BUNDLES);
return f.toString();
}
list0(f, containerDTOs.iterator().next(), false, true);
return f.toString();
}
}
public String list(Bundle... bundles) {
try (Formatter f = new Formatter()) {
Collection<ContainerDTO> containerDTOs = _ccr.getContainerDTOs(bundles);
if (containerDTOs.isEmpty()) {
f.format(NO_BUNDLES);
return f.toString();
}
List<ContainerDTO> containerDTOList = containerDTOs.stream().sorted(
(a, b) -> Long.compare(a.bundle.id,b.bundle.id)
).collect(toList());
for (Iterator<ContainerDTO> itr = containerDTOList.iterator(); itr.hasNext();) {
ContainerDTO containerDTO = itr.next();
list0(f, containerDTO, itr.hasNext(), false);
}
return f.toString();
}
}
private void list0(Formatter f, ContainerDTO containerDTO, boolean hasNext, boolean verbose) {
String curb = hasNext ? TLLS : CLLS;
String prefix = hasNext ? PSSSSSSS : SSSSSSSS;
f.format(
"%s%s[%s]%n",
curb,
containerDTO.bundle.symbolicName,
containerDTO.bundle.id);
f.format(
"%s%sCOMPONENTS%n",
(hasNext ? PSSS : SSSS),
curb);
Map<Boolean, List<ComponentTemplateDTO>> componentTemplateDTOs = containerDTO.template.components.stream().collect(
partitioningBy(c -> c.type == ComponentType.CONTAINER)
);
ComponentTemplateDTO componentTemplateDTO = componentTemplateDTOs.get(Boolean.TRUE).get(0);
List<ComponentTemplateDTO> singleAndFactory = componentTemplateDTOs.get(Boolean.FALSE);
list0(
f,
containerDTO,
componentTemplateDTO,
prefix,
!singleAndFactory.isEmpty(),
!singleAndFactory.isEmpty(),
verbose);
for (Iterator<ComponentTemplateDTO> itr2 = singleAndFactory.iterator(); itr2.hasNext();) {
componentTemplateDTO = itr2.next();
list0(
f,
containerDTO,
componentTemplateDTO,
prefix,
itr2.hasNext(),
false, verbose);
}
}
private void list0(
Formatter f, ContainerDTO containerDTO, ComponentTemplateDTO componentTemplateDTO, String prefix,
boolean hasNext, boolean curb, boolean verbose) {
Map<Boolean, List<ConfigurationTemplateDTO>> configMap = configMap(componentTemplateDTO);
if (verbose) {
f.format(
"%s%sNAME: %s%n",
prefix,
(hasNext ? TLLS : CLLS),
componentTemplateDTO.name);
f.format(
"%s%s%sTYPE: %s%n",
prefix,
(hasNext ? PSSS : SSSS),
TLLS,
componentTemplateDTO.type);
}
else {
f.format(
"%s%sNAME: %s (%s%s)%n",
prefix,
(hasNext ? TLLS : CLLS),
componentTemplateDTO.name,
componentTemplateDTO.type,
factoryPid(configMap));
}
ComponentDTO componentDTO = containerDTO.components.stream().filter(
c -> c.template.name.equals(componentTemplateDTO.name)
).findFirst().orElse(null);
if ((componentDTO != null) && !componentDTO.instances.isEmpty()) {
Iterator<ComponentInstanceDTO> itr3 = componentDTO.instances.iterator();
for (;itr3.hasNext();) {
ComponentInstanceDTO instanceDTO = itr3.next();
formatInstance(
f,
prefix,
componentDTO,
instanceDTO,
pids(instanceDTO, configMap),
hasNext,
itr3.hasNext(),
verbose);
}
}
else {
formatInstance(
f,
prefix,
componentDTO,
null,
configMap.get(Boolean.FALSE).stream().map(c -> c.pid).collect(toList()).toString(),
hasNext,
false,
verbose);
}
}
private void formatInstance(
Formatter f, String prefix, ComponentDTO componentDTO,
ComponentInstanceDTO instanceDTO, String pids,
boolean hasNext, boolean hasNext2, boolean verbose) {
if (verbose) {
f.format(
"%s%s%sBEANS: %s%n",
prefix,
(hasNext ? PSSS : SSSS),
TLLS,
componentDTO.template.beans.toString());
f.format(
"%s%s%sCONFIGURATIONS%n",
prefix,
(hasNext ? PSSS : SSSS),
TLLS);
for (Iterator<ConfigurationTemplateDTO> itr = componentDTO.template.configurations.iterator();itr.hasNext();) {
ConfigurationTemplateDTO conf = itr.next();
ConfigurationDTO configurationDTO = null;
if (instanceDTO != null) {
configurationDTO = instanceDTO.configurations.stream().filter(
c -> c.template.maximumCardinality == conf.maximumCardinality &&
c.template.pid == conf.pid &&
c.template.policy == conf.policy
).findFirst().orElse(null);
}
f.format(
"%s%s%sPID: %s%n",
prefix,
(hasNext ? PSSSPSSS : SSSSPSSS),
(itr.hasNext() ? TLLS : CLLS),
(configurationDTO != null ? configurationDTO.properties.get(Constants.SERVICE_PID) + STAR : conf.pid));
f.format(
"%s%s%s%sPOLICY: %s%n",
prefix,
(hasNext ? PSSSPSSS : SSSSPSSS),
(itr.hasNext() ? PSSS : SSSS),
((conf.maximumCardinality == MaximumCardinality.MANY) ? TLLS : CLLS),
conf.policy);
if (conf.maximumCardinality == MaximumCardinality.MANY) {
f.format(
"%s%s%sFACTORY PID: %s%n",
prefix,
(hasNext ? PSSSPSSS : SSSSPSSS),
(itr.hasNext() ? PSSSTLLS : SSSSTLLS),
conf.pid);
}
}
if (instanceDTO != null) {
f.format(
"%s%s%sCOMPONENT PROPERTIES*%n",
prefix,
(hasNext ? PSSS : SSSS),
TLLS);
for (Iterator<String> itr = instanceDTO.properties.keySet().iterator(); itr.hasNext();) {
String key = itr.next();
f.format(
"%s%s%s%s=%s%n",
prefix,
(hasNext ? PSSSPSSS : SSSSPSSS),
(itr.hasNext() ? TLLS : CLLS),
key,
instanceDTO.properties.get(key));
}
}
if (!componentDTO.template.references.isEmpty()) {
f.format(
"%s%s%sREFERENCES%n",
prefix,
(hasNext ? PSSS : SSSS),
TLLS);
for (Iterator<ReferenceTemplateDTO> itr = componentDTO.template.references.iterator(); itr.hasNext();) {
ReferenceTemplateDTO dto = itr.next();
ReferenceDTO referenceDTO = null;
if (instanceDTO != null) {
referenceDTO = instanceDTO.references.stream().filter(
r -> r.template.maximumCardinality == dto.maximumCardinality &&
r.template.minimumCardinality == dto.minimumCardinality &&
r.template.name == dto.name &&
r.template.policy == dto.policy &&
r.template.policyOption == dto.policyOption &&
r.template.serviceType == dto.serviceType &&
r.template.targetFilter == dto.targetFilter
).findFirst().orElse(null);
}
f.format(
"%s%s%sNAME: %s%n",
prefix,
(hasNext ? PSSSPSSS : SSSSPSSS),
(itr.hasNext() ? TLLS : CLLS),
dto.name);
f.format(
"%s%s%sSERVICE TYPE: %s%n",
prefix,
(hasNext ? PSSSPSSS : SSSSPSSS),
(itr.hasNext() ? PSSSTLLS : SSSSTLLS),
dto.serviceType);
f.format(
"%s%s%sTARGET FILTER: %s%n",
prefix,
(hasNext ? PSSSPSSS : SSSSPSSS),
(itr.hasNext() ? PSSSTLLS : SSSSTLLS),
(referenceDTO != null ? referenceDTO.targetFilter + STAR : dto.targetFilter));
f.format(
"%s%s%sMAX CARDINALITY: %s%n",
prefix,
(hasNext ? PSSSPSSS : SSSSPSSS),
(itr.hasNext() ? PSSSTLLS : SSSSTLLS),
dto.maximumCardinality);
f.format(
"%s%s%sMIN CARDINALITY: %s%n",
prefix,
(hasNext ? PSSSPSSS : SSSSPSSS),
(itr.hasNext() ? PSSSTLLS : SSSSTLLS),
(referenceDTO != null ? referenceDTO.minimumCardinality + STAR : dto.minimumCardinality));
f.format(
"%s%s%sPOLICY: %s%n",
prefix,
(hasNext ? PSSSPSSS : SSSSPSSS),
(itr.hasNext() ? PSSSTLLS : SSSSTLLS),
dto.policy);
f.format(
"%s%s%s%sPOLICY OPTION: %s%n",
prefix,
(hasNext ? PSSSPSSS : SSSSPSSS),
(itr.hasNext() ? PSSS : SSSS),
(referenceDTO != null ? TLLS : CLLS),
dto.policyOption);
if (referenceDTO != null) {
f.format(
"%s%s%sMATCHES: %s*%n",
prefix,
(hasNext ? PSSSPSSS : SSSSPSSS),
(itr.hasNext() ? PSSSCLLS : SSSSCLLS),
referenceDTO.matches);
}
}
}
if (!componentDTO.template.activations.isEmpty()) {
f.format(
"%s%s%sACTIVATIONS%n",
prefix,
(hasNext ? PSSS : SSSS),
TLLS);
for (Iterator<ActivationTemplateDTO> itr = componentDTO.template.activations.iterator(); itr.hasNext();) {
ActivationTemplateDTO dto = itr.next();
ActivationDTO activationDTO = null;
if (instanceDTO != null) {
activationDTO = instanceDTO.activations.stream().filter(
a -> a.template.properties.equals(dto.properties) &&
a.template.scope == dto.scope &&
a.template.serviceClasses.equals(dto.serviceClasses)
).findFirst().orElse(null);
}
f.format(
"%s%s%sSERVICE TYPES: %s%n",
prefix,
(hasNext ? PSSSPSSS : SSSSPSSS),
(itr.hasNext() ? TLLS : CLLS),
dto.serviceClasses);
f.format(
"%s%s%s%sSERVICE SCOPE: %s%n",
prefix,
(hasNext ? PSSSPSSS : SSSSPSSS),
(itr.hasNext() ? PSSS : SSSS),
(activationDTO != null ? TLLS : CLLS),
dto.scope.toString().toLowerCase());
if (activationDTO != null) {
f.format(
"%s%s%sSERVICE REFERENCE: %s%n",
prefix,
(hasNext ? PSSSPSSS : SSSSPSSS),
(itr.hasNext() ? PSSSCLLS : SSSSCLLS),
activationDTO.service + STAR);
}
}
}
f.format(
"%s%s%sSTATE: %s*%n",
prefix,
(hasNext ? PSSS : SSSS),
(hasNext2 ? TLLS : CLLS),
state(componentDTO));
return;
}
f.format(
"%s%s%sSTATE: %s %s%n",
prefix,
(hasNext ? PSSS : SSSS),
(hasNext2 ? TLLS : CLLS),
state(componentDTO),
pids);
}
private String pids(
ComponentInstanceDTO instanceDTO,
Map<Boolean, List<ConfigurationTemplateDTO>> configMap) {
List<String> resolvedPids = instanceDTO.configurations.stream().map(
c -> c.properties
).filter(Objects::nonNull).map(
p -> (String)p.get(Constants.SERVICE_PID)
).collect(toList());
return configMap.values().stream().flatMap(v -> v.stream()).map(c -> c.pid).map(
c -> {
String pid = resolvedPids.stream().filter(
rp -> rp.startsWith(c + '~') || rp.startsWith(c + '.')
).findFirst().orElse(null);
if (pid != null) {
return pid + STAR;
}
else if (resolvedPids.stream().anyMatch(rp -> rp.equals(c))) {
return c + STAR;
}
return c;
}
).collect(toList()).toString();
}
private Map<Boolean, List<ConfigurationTemplateDTO>> configMap(ComponentTemplateDTO componentTemplateDTO) {
return componentTemplateDTO.configurations.stream().filter(
c -> c.pid != null
).collect(
partitioningBy(c -> c.maximumCardinality == MaximumCardinality.MANY)
);
}
private String factoryPid(Map<Boolean, List<ConfigurationTemplateDTO>> configMap) {
return configMap.get(Boolean.TRUE).stream().map(
c -> c.pid
).findFirst().map(
c -> EQUAL + c
).orElse(BLANK);
}
private Object state(ComponentDTO componentDTO) {
if (componentDTO == null) {
return NULL;
}
else if (!componentDTO.enabled) {
return DISABLED;
}
else if (componentDTO.instances.size() == 0) {
return WAITING;
}
return ACTIVE;
}
private static final String BLANK = "";
private static final String ACTIVE = "active";
private static final String DISABLED = "disabled";
private static final String EQUAL = "=";
private static final String NULL = "null";
private static final String STAR = "*";
private static final String WAITING = "waiting";
private static final String CLLS = "└── ";
private static final String PSSS = "│   ";
private static final String SSSS = "    ";
private static final String TLLS = "├── ";
private static final String SSSSSSSS = "        ";
private static final String PSSSSSSS = "│       ";
private static final String PSSSPSSS = "│   │   ";
private static final String PSSSTLLS = "│   ├── ";
private static final String SSSSTLLS = "    ├── ";
private static final String SSSSPSSS = "    │   ";
private static final String SSSSCLLS = "    └── ";
private static final String PSSSCLLS = "│   └── ";
private static final String NO_BUNDLES = "No matching CDI bundles";
private final CCR _ccr;
}