diff options
Diffstat (limited to 'framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleDeviceStore.java')
-rw-r--r-- | framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleDeviceStore.java | 684 |
1 files changed, 0 insertions, 684 deletions
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleDeviceStore.java b/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleDeviceStore.java deleted file mode 100644 index 11a12040..00000000 --- a/framework/src/onos/core/common/src/test/java/org/onosproject/store/trivial/SimpleDeviceStore.java +++ /dev/null @@ -1,684 +0,0 @@ -/* - * Copyright 2014-2015 Open Networking Laboratory - * - * 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.onosproject.store.trivial; - -import com.google.common.collect.FluentIterable; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Service; -import org.onosproject.net.AnnotationsUtil; -import org.onosproject.net.DefaultAnnotations; -import org.onosproject.net.DefaultDevice; -import org.onosproject.net.DefaultPort; -import org.onosproject.net.Device; -import org.onosproject.net.Device.Type; -import org.onosproject.net.DeviceId; -import org.onosproject.net.Port; -import org.onosproject.net.PortNumber; -import org.onosproject.net.SparseAnnotations; -import org.onosproject.net.device.DefaultDeviceDescription; -import org.onosproject.net.device.DefaultPortDescription; -import org.onosproject.net.device.DefaultPortStatistics; -import org.onosproject.net.device.DeviceDescription; -import org.onosproject.net.device.DeviceEvent; -import org.onosproject.net.device.DeviceStore; -import org.onosproject.net.device.DeviceStoreDelegate; -import org.onosproject.net.device.PortDescription; -import org.onosproject.net.device.PortStatistics; -import org.onosproject.net.provider.ProviderId; -import org.onosproject.store.AbstractStore; -import org.onlab.packet.ChassisId; -import org.onlab.util.NewConcurrentHashMap; -import org.slf4j.Logger; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Predicates.notNull; -import static com.google.common.base.Verify.verify; -import static org.onosproject.net.device.DeviceEvent.Type.*; -import static org.slf4j.LoggerFactory.getLogger; -import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked; -import static org.onosproject.net.DefaultAnnotations.union; -import static org.onosproject.net.DefaultAnnotations.merge; - -/** - * Manages inventory of infrastructure devices using trivial in-memory - * structures implementation. - */ -@Component(immediate = true) -@Service -public class SimpleDeviceStore - extends AbstractStore<DeviceEvent, DeviceStoreDelegate> - implements DeviceStore { - - private final Logger log = getLogger(getClass()); - - public static final String DEVICE_NOT_FOUND = "Device with ID %s not found"; - - // Collection of Description given from various providers - private final ConcurrentMap<DeviceId, Map<ProviderId, DeviceDescriptions>> - deviceDescs = Maps.newConcurrentMap(); - - // Cache of Device and Ports generated by compositing descriptions from providers - private final ConcurrentMap<DeviceId, Device> devices = Maps.newConcurrentMap(); - private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, Port>> - devicePorts = Maps.newConcurrentMap(); - private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, PortStatistics>> - devicePortStats = Maps.newConcurrentMap(); - private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, PortStatistics>> - devicePortDeltaStats = Maps.newConcurrentMap(); - - // Available (=UP) devices - private final Set<DeviceId> availableDevices = Sets.newConcurrentHashSet(); - - - @Activate - public void activate() { - log.info("Started"); - } - - @Deactivate - public void deactivate() { - deviceDescs.clear(); - devices.clear(); - devicePorts.clear(); - availableDevices.clear(); - log.info("Stopped"); - } - - @Override - public int getDeviceCount() { - return devices.size(); - } - - @Override - public Iterable<Device> getDevices() { - return Collections.unmodifiableCollection(devices.values()); - } - - @Override - public Iterable<Device> getAvailableDevices() { - return FluentIterable.from(getDevices()) - .filter(input -> isAvailable(input.id())); - } - - @Override - public Device getDevice(DeviceId deviceId) { - return devices.get(deviceId); - } - - @Override - public DeviceEvent createOrUpdateDevice(ProviderId providerId, - DeviceId deviceId, - DeviceDescription deviceDescription) { - Map<ProviderId, DeviceDescriptions> providerDescs - = getOrCreateDeviceDescriptions(deviceId); - - synchronized (providerDescs) { - // locking per device - DeviceDescriptions descs - = getOrCreateProviderDeviceDescriptions(providerDescs, - providerId, - deviceDescription); - - Device oldDevice = devices.get(deviceId); - // update description - descs.putDeviceDesc(deviceDescription); - Device newDevice = composeDevice(deviceId, providerDescs); - - if (oldDevice == null) { - // ADD - return createDevice(providerId, newDevice); - } else { - // UPDATE or ignore (no change or stale) - return updateDevice(providerId, oldDevice, newDevice); - } - } - } - - // Creates the device and returns the appropriate event if necessary. - // Guarded by deviceDescs value (=Device lock) - private DeviceEvent createDevice(ProviderId providerId, Device newDevice) { - // update composed device cache - Device oldDevice = devices.putIfAbsent(newDevice.id(), newDevice); - verify(oldDevice == null, - "Unexpected Device in cache. PID:%s [old=%s, new=%s]", - providerId, oldDevice, newDevice); - - if (!providerId.isAncillary()) { - availableDevices.add(newDevice.id()); - } - - return new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, newDevice, null); - } - - // Updates the device and returns the appropriate event if necessary. - // Guarded by deviceDescs value (=Device lock) - private DeviceEvent updateDevice(ProviderId providerId, Device oldDevice, Device newDevice) { - // We allow only certain attributes to trigger update - boolean propertiesChanged = - !Objects.equals(oldDevice.hwVersion(), newDevice.hwVersion()) || - !Objects.equals(oldDevice.swVersion(), newDevice.swVersion()); - boolean annotationsChanged = - !AnnotationsUtil.isEqual(oldDevice.annotations(), newDevice.annotations()); - - // Primary providers can respond to all changes, but ancillary ones - // should respond only to annotation changes. - if ((providerId.isAncillary() && annotationsChanged) || - (!providerId.isAncillary() && (propertiesChanged || annotationsChanged))) { - - boolean replaced = devices.replace(newDevice.id(), oldDevice, newDevice); - if (!replaced) { - // FIXME: Is the enclosing if required here? - verify(replaced, - "Replacing devices cache failed. PID:%s [expected:%s, found:%s, new=%s]", - providerId, oldDevice, devices.get(newDevice.id()) - , newDevice); - } - if (!providerId.isAncillary()) { - availableDevices.add(newDevice.id()); - } - return new DeviceEvent(DeviceEvent.Type.DEVICE_UPDATED, newDevice, null); - } - - // Otherwise merely attempt to change availability if primary provider - if (!providerId.isAncillary()) { - boolean added = availableDevices.add(newDevice.id()); - return !added ? null : - new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, newDevice, null); - } - return null; - } - - @Override - public DeviceEvent markOffline(DeviceId deviceId) { - Map<ProviderId, DeviceDescriptions> providerDescs - = getOrCreateDeviceDescriptions(deviceId); - - // locking device - synchronized (providerDescs) { - Device device = devices.get(deviceId); - if (device == null) { - return null; - } - boolean removed = availableDevices.remove(deviceId); - if (removed) { - // TODO: broadcast ... DOWN only? - return new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, device, null); - } - return null; - } - } - - @Override - public List<DeviceEvent> updatePorts(ProviderId providerId, - DeviceId deviceId, - List<PortDescription> portDescriptions) { - Device device = devices.get(deviceId); - if (device == null) { - log.debug("Device {} doesn't exist or hasn't been initialized yet", deviceId); - return Collections.emptyList(); - } - - Map<ProviderId, DeviceDescriptions> descsMap = deviceDescs.get(deviceId); - checkArgument(descsMap != null, DEVICE_NOT_FOUND, deviceId); - - List<DeviceEvent> events = new ArrayList<>(); - synchronized (descsMap) { - DeviceDescriptions descs = descsMap.get(providerId); - // every provider must provide DeviceDescription. - checkArgument(descs != null, - "Device description for Device ID %s from Provider %s was not found", - deviceId, providerId); - - Map<PortNumber, Port> ports = getPortMap(deviceId); - - // Add new ports - Set<PortNumber> processed = new HashSet<>(); - for (PortDescription portDescription : portDescriptions) { - final PortNumber number = portDescription.portNumber(); - processed.add(portDescription.portNumber()); - - final Port oldPort = ports.get(number); - final Port newPort; - -// event suppression hook? - - // update description - descs.putPortDesc(portDescription); - newPort = composePort(device, number, descsMap); - - events.add(oldPort == null ? - createPort(device, newPort, ports) : - updatePort(device, oldPort, newPort, ports)); - } - - events.addAll(pruneOldPorts(device, ports, processed)); - } - return FluentIterable.from(events).filter(notNull()).toList(); - } - - // Creates a new port based on the port description adds it to the map and - // Returns corresponding event. - // Guarded by deviceDescs value (=Device lock) - private DeviceEvent createPort(Device device, Port newPort, - Map<PortNumber, Port> ports) { - ports.put(newPort.number(), newPort); - return new DeviceEvent(PORT_ADDED, device, newPort); - } - - // Checks if the specified port requires update and if so, it replaces the - // existing entry in the map and returns corresponding event. - // Guarded by deviceDescs value (=Device lock) - private DeviceEvent updatePort(Device device, Port oldPort, - Port newPort, - Map<PortNumber, Port> ports) { - if (oldPort.isEnabled() != newPort.isEnabled() || - oldPort.type() != newPort.type() || - oldPort.portSpeed() != newPort.portSpeed() || - !AnnotationsUtil.isEqual(oldPort.annotations(), newPort.annotations())) { - ports.put(oldPort.number(), newPort); - return new DeviceEvent(PORT_UPDATED, device, newPort); - } - return null; - } - - // Prunes the specified list of ports based on which ports are in the - // processed list and returns list of corresponding events. - // Guarded by deviceDescs value (=Device lock) - private List<DeviceEvent> pruneOldPorts(Device device, - Map<PortNumber, Port> ports, - Set<PortNumber> processed) { - List<DeviceEvent> events = new ArrayList<>(); - Iterator<Entry<PortNumber, Port>> iterator = ports.entrySet().iterator(); - while (iterator.hasNext()) { - Entry<PortNumber, Port> e = iterator.next(); - PortNumber portNumber = e.getKey(); - if (!processed.contains(portNumber)) { - events.add(new DeviceEvent(PORT_REMOVED, device, e.getValue())); - iterator.remove(); - } - } - return events; - } - - // Gets the map of ports for the specified device; if one does not already - // exist, it creates and registers a new one. - private ConcurrentMap<PortNumber, Port> getPortMap(DeviceId deviceId) { - return createIfAbsentUnchecked(devicePorts, deviceId, - NewConcurrentHashMap.<PortNumber, Port>ifNeeded()); - } - - private Map<ProviderId, DeviceDescriptions> getOrCreateDeviceDescriptions( - DeviceId deviceId) { - Map<ProviderId, DeviceDescriptions> r; - r = deviceDescs.get(deviceId); - if (r != null) { - return r; - } - r = new HashMap<>(); - final Map<ProviderId, DeviceDescriptions> concurrentlyAdded; - concurrentlyAdded = deviceDescs.putIfAbsent(deviceId, r); - if (concurrentlyAdded != null) { - return concurrentlyAdded; - } else { - return r; - } - } - - // Guarded by deviceDescs value (=Device lock) - private DeviceDescriptions getOrCreateProviderDeviceDescriptions( - Map<ProviderId, DeviceDescriptions> device, - ProviderId providerId, DeviceDescription deltaDesc) { - synchronized (device) { - DeviceDescriptions r = device.get(providerId); - if (r == null) { - r = new DeviceDescriptions(deltaDesc); - device.put(providerId, r); - } - return r; - } - } - - @Override - public DeviceEvent updatePortStatus(ProviderId providerId, DeviceId deviceId, - PortDescription portDescription) { - Device device = devices.get(deviceId); - checkArgument(device != null, DEVICE_NOT_FOUND, deviceId); - - Map<ProviderId, DeviceDescriptions> descsMap = deviceDescs.get(deviceId); - checkArgument(descsMap != null, DEVICE_NOT_FOUND, deviceId); - - synchronized (descsMap) { - DeviceDescriptions descs = descsMap.get(providerId); - // assuming all providers must give DeviceDescription first - checkArgument(descs != null, - "Device description for Device ID %s from Provider %s was not found", - deviceId, providerId); - - ConcurrentMap<PortNumber, Port> ports = getPortMap(deviceId); - final PortNumber number = portDescription.portNumber(); - final Port oldPort = ports.get(number); - final Port newPort; - - // update description - descs.putPortDesc(portDescription); - newPort = composePort(device, number, descsMap); - - if (oldPort == null) { - return createPort(device, newPort, ports); - } else { - return updatePort(device, oldPort, newPort, ports); - } - } - } - - @Override - public List<Port> getPorts(DeviceId deviceId) { - Map<PortNumber, Port> ports = devicePorts.get(deviceId); - if (ports == null) { - return Collections.emptyList(); - } - return ImmutableList.copyOf(ports.values()); - } - - @Override - public DeviceEvent updatePortStatistics(ProviderId providerId, DeviceId deviceId, - Collection<PortStatistics> newStatsCollection) { - - ConcurrentMap<PortNumber, PortStatistics> prvStatsMap = devicePortStats.get(deviceId); - ConcurrentMap<PortNumber, PortStatistics> newStatsMap = Maps.newConcurrentMap(); - ConcurrentMap<PortNumber, PortStatistics> deltaStatsMap = Maps.newConcurrentMap(); - - if (prvStatsMap != null) { - for (PortStatistics newStats : newStatsCollection) { - PortNumber port = PortNumber.portNumber(newStats.port()); - PortStatistics prvStats = prvStatsMap.get(port); - DefaultPortStatistics.Builder builder = DefaultPortStatistics.builder(); - PortStatistics deltaStats = builder.build(); - if (prvStats != null) { - deltaStats = calcDeltaStats(deviceId, prvStats, newStats); - } - deltaStatsMap.put(port, deltaStats); - newStatsMap.put(port, newStats); - } - } else { - for (PortStatistics newStats : newStatsCollection) { - PortNumber port = PortNumber.portNumber(newStats.port()); - newStatsMap.put(port, newStats); - } - } - devicePortDeltaStats.put(deviceId, deltaStatsMap); - devicePortStats.put(deviceId, newStatsMap); - return new DeviceEvent(PORT_STATS_UPDATED, devices.get(deviceId), null); - } - - public PortStatistics calcDeltaStats(DeviceId deviceId, PortStatistics prvStats, PortStatistics newStats) { - // calculate time difference - long deltaStatsSec, deltaStatsNano; - if (newStats.durationNano() < prvStats.durationNano()) { - deltaStatsNano = newStats.durationNano() - prvStats.durationNano() + TimeUnit.SECONDS.toNanos(1); - deltaStatsSec = newStats.durationSec() - prvStats.durationSec() - 1L; - } else { - deltaStatsNano = newStats.durationNano() - prvStats.durationNano(); - deltaStatsSec = newStats.durationSec() - prvStats.durationSec(); - } - DefaultPortStatistics.Builder builder = DefaultPortStatistics.builder(); - DefaultPortStatistics deltaStats = builder.setDeviceId(deviceId) - .setPort(newStats.port()) - .setPacketsReceived(newStats.packetsReceived() - prvStats.packetsReceived()) - .setPacketsSent(newStats.packetsSent() - prvStats.packetsSent()) - .setBytesReceived(newStats.bytesReceived() - prvStats.bytesReceived()) - .setBytesSent(newStats.bytesSent() - prvStats.bytesSent()) - .setPacketsRxDropped(newStats.packetsRxDropped() - prvStats.packetsRxDropped()) - .setPacketsTxDropped(newStats.packetsTxDropped() - prvStats.packetsTxDropped()) - .setPacketsRxErrors(newStats.packetsRxErrors() - prvStats.packetsRxErrors()) - .setPacketsTxErrors(newStats.packetsTxErrors() - prvStats.packetsTxErrors()) - .setDurationSec(deltaStatsSec) - .setDurationNano(deltaStatsNano) - .build(); - return deltaStats; - } - - @Override - public Port getPort(DeviceId deviceId, PortNumber portNumber) { - Map<PortNumber, Port> ports = devicePorts.get(deviceId); - return ports == null ? null : ports.get(portNumber); - } - - @Override - public List<PortStatistics> getPortStatistics(DeviceId deviceId) { - Map<PortNumber, PortStatistics> portStats = devicePortStats.get(deviceId); - if (portStats == null) { - return Collections.emptyList(); - } - return ImmutableList.copyOf(portStats.values()); - } - - @Override - public List<PortStatistics> getPortDeltaStatistics(DeviceId deviceId) { - Map<PortNumber, PortStatistics> portStats = devicePortDeltaStats.get(deviceId); - if (portStats == null) { - return Collections.emptyList(); - } - return ImmutableList.copyOf(portStats.values()); - } - - @Override - public boolean isAvailable(DeviceId deviceId) { - return availableDevices.contains(deviceId); - } - - @Override - public DeviceEvent removeDevice(DeviceId deviceId) { - Map<ProviderId, DeviceDescriptions> descs = getOrCreateDeviceDescriptions(deviceId); - synchronized (descs) { - Device device = devices.remove(deviceId); - // should DEVICE_REMOVED carry removed ports? - Map<PortNumber, Port> ports = devicePorts.get(deviceId); - if (ports != null) { - ports.clear(); - } - availableDevices.remove(deviceId); - descs.clear(); - return device == null ? null : - new DeviceEvent(DEVICE_REMOVED, device, null); - } - } - - /** - * Returns a Device, merging description given from multiple Providers. - * - * @param deviceId device identifier - * @param providerDescs Collection of Descriptions from multiple providers - * @return Device instance - */ - private Device composeDevice(DeviceId deviceId, - Map<ProviderId, DeviceDescriptions> providerDescs) { - - checkArgument(!providerDescs.isEmpty(), "No Device descriptions supplied"); - - ProviderId primary = pickPrimaryPid(providerDescs); - - DeviceDescriptions desc = providerDescs.get(primary); - - final DeviceDescription base = desc.getDeviceDesc(); - Type type = base.type(); - String manufacturer = base.manufacturer(); - String hwVersion = base.hwVersion(); - String swVersion = base.swVersion(); - String serialNumber = base.serialNumber(); - ChassisId chassisId = base.chassisId(); - DefaultAnnotations annotations = DefaultAnnotations.builder().build(); - annotations = merge(annotations, base.annotations()); - - for (Entry<ProviderId, DeviceDescriptions> e : providerDescs.entrySet()) { - if (e.getKey().equals(primary)) { - continue; - } - // TODO: should keep track of Description timestamp - // and only merge conflicting keys when timestamp is newer - // Currently assuming there will never be a key conflict between - // providers - - // annotation merging. not so efficient, should revisit later - annotations = merge(annotations, e.getValue().getDeviceDesc().annotations()); - } - - return new DefaultDevice(primary, deviceId, type, manufacturer, - hwVersion, swVersion, serialNumber, - chassisId, annotations); - } - - /** - * Returns a Port, merging description given from multiple Providers. - * - * @param device device the port is on - * @param number port number - * @param descsMap Collection of Descriptions from multiple providers - * @return Port instance - */ - private Port composePort(Device device, PortNumber number, - Map<ProviderId, DeviceDescriptions> descsMap) { - - ProviderId primary = pickPrimaryPid(descsMap); - DeviceDescriptions primDescs = descsMap.get(primary); - // if no primary, assume not enabled - // TODO: revisit this default port enabled/disabled behavior - boolean isEnabled = false; - DefaultAnnotations annotations = DefaultAnnotations.builder().build(); - - final PortDescription portDesc = primDescs.getPortDesc(number); - if (portDesc != null) { - isEnabled = portDesc.isEnabled(); - annotations = merge(annotations, portDesc.annotations()); - } - - for (Entry<ProviderId, DeviceDescriptions> e : descsMap.entrySet()) { - if (e.getKey().equals(primary)) { - continue; - } - // TODO: should keep track of Description timestamp - // and only merge conflicting keys when timestamp is newer - // Currently assuming there will never be a key conflict between - // providers - - // annotation merging. not so efficient, should revisit later - final PortDescription otherPortDesc = e.getValue().getPortDesc(number); - if (otherPortDesc != null) { - annotations = merge(annotations, otherPortDesc.annotations()); - } - } - - return portDesc == null ? - new DefaultPort(device, number, false, annotations) : - new DefaultPort(device, number, isEnabled, portDesc.type(), - portDesc.portSpeed(), annotations); - } - - /** - * @return primary ProviderID, or randomly chosen one if none exists - */ - private ProviderId pickPrimaryPid(Map<ProviderId, DeviceDescriptions> descsMap) { - ProviderId fallBackPrimary = null; - for (Entry<ProviderId, DeviceDescriptions> e : descsMap.entrySet()) { - if (!e.getKey().isAncillary()) { - return e.getKey(); - } else if (fallBackPrimary == null) { - // pick randomly as a fallback in case there is no primary - fallBackPrimary = e.getKey(); - } - } - return fallBackPrimary; - } - - /** - * Collection of Description of a Device and it's Ports given from a Provider. - */ - private static class DeviceDescriptions { - - private final AtomicReference<DeviceDescription> deviceDesc; - private final ConcurrentMap<PortNumber, PortDescription> portDescs; - - public DeviceDescriptions(DeviceDescription desc) { - this.deviceDesc = new AtomicReference<>(checkNotNull(desc)); - this.portDescs = new ConcurrentHashMap<>(); - } - - public DeviceDescription getDeviceDesc() { - return deviceDesc.get(); - } - - public PortDescription getPortDesc(PortNumber number) { - return portDescs.get(number); - } - - /** - * Puts DeviceDescription, merging annotations as necessary. - * - * @param newDesc new DeviceDescription - * @return previous DeviceDescription - */ - public synchronized DeviceDescription putDeviceDesc(DeviceDescription newDesc) { - DeviceDescription oldOne = deviceDesc.get(); - DeviceDescription newOne = newDesc; - if (oldOne != null) { - SparseAnnotations merged = union(oldOne.annotations(), - newDesc.annotations()); - newOne = new DefaultDeviceDescription(newOne, merged); - } - return deviceDesc.getAndSet(newOne); - } - - /** - * Puts PortDescription, merging annotations as necessary. - * - * @param newDesc new PortDescription - * @return previous PortDescription - */ - public synchronized PortDescription putPortDesc(PortDescription newDesc) { - PortDescription oldOne = portDescs.get(newDesc.portNumber()); - PortDescription newOne = newDesc; - if (oldOne != null) { - SparseAnnotations merged = union(oldOne.annotations(), - newDesc.annotations()); - newOne = new DefaultPortDescription(newOne, merged); - } - return portDescs.put(newOne.portNumber(), newOne); - } - } -} |