diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceIterator.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceIterator.java index 0ff058d542a049cd047313109915213bad4af14d..795775c15f1f5d0852aa4fb362b4dd5ced3600ec 100644 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceIterator.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceIterator.java @@ -19,17 +19,15 @@ package net.floodlightcontroller.devicemanager.internal; import java.util.Arrays; import java.util.Iterator; -import java.util.NoSuchElementException; import net.floodlightcontroller.devicemanager.IEntityClass; import net.floodlightcontroller.devicemanager.SwitchPort; +import net.floodlightcontroller.util.FilterIterator; /** * An iterator for handling device queries */ -public class DeviceIterator implements Iterator<Device> { - private Iterator<Device> subIterator; - +public class DeviceIterator extends FilterIterator<Device> { private IEntityClass[] entityClasses; private Long macAddress; @@ -37,8 +35,6 @@ public class DeviceIterator implements Iterator<Device> { private Integer ipv4Address; private Long switchDPID; private Integer switchPort; - - private Device next = null; /** * Construct a new device iterator over the key fields @@ -57,7 +53,7 @@ public class DeviceIterator implements Iterator<Device> { Integer ipv4Address, Long switchDPID, Integer switchPort) { - super(); + super(subIterator); this.entityClasses = entityClasses; this.subIterator = subIterator; this.macAddress = macAddress; @@ -68,80 +64,57 @@ public class DeviceIterator implements Iterator<Device> { } @Override - public boolean hasNext() { - if (next != null) return true; - + protected boolean matches(Device value) { boolean match; - while (subIterator.hasNext()) { - next = subIterator.next(); + if (entityClasses != null) { + IEntityClass[] classes = next.getEntityClasses(); + if (classes == null) return false; - if (entityClasses != null) { - IEntityClass[] classes = next.getEntityClasses(); - if (classes == null) continue; - - match = false; - for (IEntityClass clazz : classes) { - for (IEntityClass entityClass : entityClasses) { - if (clazz.equals(entityClass)) { - match = true; - break; - } + match = false; + for (IEntityClass clazz : classes) { + for (IEntityClass entityClass : entityClasses) { + if (clazz.equals(entityClass)) { + match = true; + break; } - if (match == true) break; } - if (!match) continue; - } - if (macAddress != null) { - if (macAddress.longValue() != next.getMACAddress()) - continue; - } - if (vlan != null) { - Short[] vlans = next.getVlanId(); - if (Arrays.binarySearch(vlans, vlan) < 0) - continue; + if (match == true) break; } - if (ipv4Address != null) { - Integer[] ipv4Addresses = next.getIPv4Addresses(); - if (Arrays.binarySearch(ipv4Addresses, ipv4Address) < 0) - continue; - } - if (switchDPID != null || switchPort != null) { - SwitchPort[] sps = next.getAttachmentPoints(); - if (sps == null) continue; - - match = false; - for (SwitchPort sp : sps) { - if (switchDPID != null) { - if (switchDPID.longValue() != sp.getSwitchDPID()) - continue; - } - if (switchPort != null) { - if (switchPort.intValue() != sp.getPort()) - continue; - } - match = true; - break; + if (!match) return false; + } + if (macAddress != null) { + if (macAddress.longValue() != next.getMACAddress()) + return false; + } + if (vlan != null) { + Short[] vlans = next.getVlanId(); + if (Arrays.binarySearch(vlans, vlan) < 0) + return false; + } + if (ipv4Address != null) { + Integer[] ipv4Addresses = next.getIPv4Addresses(); + if (Arrays.binarySearch(ipv4Addresses, ipv4Address) < 0) + return false; + } + if (switchDPID != null || switchPort != null) { + SwitchPort[] sps = next.getAttachmentPoints(); + if (sps == null) return false; + + match = false; + for (SwitchPort sp : sps) { + if (switchDPID != null) { + if (switchDPID.longValue() != sp.getSwitchDPID()) + return false; + } + if (switchPort != null) { + if (switchPort.intValue() != sp.getPort()) + return false; } - if (!match) continue; + match = true; + break; } - return true; + if (!match) return false; } - return false; + return true; } - - @Override - public Device next() { - if (hasNext()) { - Device cur = next; - next = null; - return cur; - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - } diff --git a/src/main/java/net/floodlightcontroller/devicemanager/web/AbstractDeviceResource.java b/src/main/java/net/floodlightcontroller/devicemanager/web/AbstractDeviceResource.java index 67a9db18dc0f6791dfcce6c2ef8bff0ba7f1bc30..58e79e49432764453b57af4dd7d1d61145c1bcc2 100644 --- a/src/main/java/net/floodlightcontroller/devicemanager/web/AbstractDeviceResource.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/web/AbstractDeviceResource.java @@ -21,7 +21,10 @@ import java.util.Iterator; import net.floodlightcontroller.devicemanager.IDevice; import net.floodlightcontroller.devicemanager.IDeviceService; +import net.floodlightcontroller.devicemanager.SwitchPort; +import net.floodlightcontroller.devicemanager.internal.Device; import net.floodlightcontroller.packet.IPv4; +import net.floodlightcontroller.util.FilterIterator; import org.openflow.util.HexString; import org.restlet.data.Form; @@ -113,12 +116,82 @@ public abstract class AbstractDeviceResource extends ServerResource { } } - Iterator<? extends IDevice> diter = + @SuppressWarnings("unchecked") + Iterator<Device> diter = (Iterator<Device>) deviceManager.queryDevices(macAddress, vlan, ipv4Address, switchDPID, switchPort); - return diter; + + final String macStartsWith = + form.getFirstValue("mac__startswith", true); + final String vlanStartsWith = + form.getFirstValue("vlan__startswith", true); + final String ipv4StartsWith = + form.getFirstValue("ipv4__startswith", true); + final String dpidStartsWith = + form.getFirstValue("dpid__startswith", true); + final String portStartsWith = + form.getFirstValue("port__startswith", true); + + return new FilterIterator<Device>(diter) { + @Override + protected boolean matches(Device value) { + if (macStartsWith != null) { + if (!value.getMACAddressString().startsWith(macStartsWith)) + return false; + } + if (vlanStartsWith != null) { + boolean match = false; + for (Short v : value.getVlanId()) { + if (v != null && + v.toString().startsWith(vlanStartsWith)) { + match = true; + break; + } + } + if (!match) return false; + } + if (ipv4StartsWith != null) { + boolean match = false; + for (Integer v : value.getIPv4Addresses()) { + String str = IPv4.fromIPv4Address(v); + if (v != null && + str.startsWith(ipv4StartsWith)) { + match = true; + break; + } + } + if (!match) return false; + } + if (dpidStartsWith != null) { + boolean match = false; + for (SwitchPort v : value.getAttachmentPoints(true)) { + String str = + HexString.toHexString(v.getSwitchDPID(), 8); + if (v != null && + str.startsWith(dpidStartsWith)) { + match = true; + break; + } + } + if (!match) return false; + } + if (portStartsWith != null) { + boolean match = false; + for (SwitchPort v : value.getAttachmentPoints(true)) { + String str = Integer.toString(v.getPort()); + if (v != null && + str.startsWith(portStartsWith)) { + match = true; + break; + } + } + if (!match) return false; + } + return true; + } + }; } } diff --git a/src/main/java/net/floodlightcontroller/util/FilterIterator.java b/src/main/java/net/floodlightcontroller/util/FilterIterator.java new file mode 100644 index 0000000000000000000000000000000000000000..47cd5c9e2d4db4bb1dddaaa14eb7441e7058314f --- /dev/null +++ b/src/main/java/net/floodlightcontroller/util/FilterIterator.java @@ -0,0 +1,80 @@ +/** +* Copyright 2012, Big Switch Networks, Inc. +* Originally created by David Erickson, Stanford University +* +* 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 net.floodlightcontroller.util; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * An iterator that will filter values from an iterator and return only + * those values that match the predicate. + */ +public abstract class FilterIterator<T> implements Iterator<T> { + protected Iterator<T> subIterator; + protected T next; + + /** + * Construct a filter iterator from the given sub iterator + * @param subIterator the sub iterator over which we'll filter + */ + public FilterIterator(Iterator<T> subIterator) { + super(); + this.subIterator = subIterator; + } + + /** + * Check whether the given value should be returned by the + * filter + * @param value the value to check + * @return true if the value should be included + */ + protected abstract boolean matches(T value); + + // *********** + // Iterator<T> + // *********** + + @Override + public boolean hasNext() { + if (next != null) return true; + + while (subIterator.hasNext()) { + next = subIterator.next(); + if (matches(next)) + return true; + } + next = null; + return false; + } + + @Override + public T next() { + if (hasNext()) { + T cur = next; + next = null; + return cur; + } + throw new NoSuchElementException(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + +}