/*
* Copyright 2013 Eediom Inc.
*
* 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.araqne.logdb.query.expr;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
import org.araqne.logdb.QueryContext;
import org.araqne.logdb.Row;
import org.araqne.logdb.impl.InetAddresses;
/**
* @since 1.6.7
* @author darkluster
*
*/
public class Network extends FunctionExpression {
private static final byte[][] MASK_BITS;
private Expression valueExpr;
private Expression maskExpr;
static {
MASK_BITS = new byte[128][16];
for (int i = 0; i < 128; i++) {
MASK_BITS[i] = initializeMask(i);
}
}
public Network(QueryContext ctx, List<Expression> exprs) {
super("network", exprs, 2);
this.valueExpr = exprs.get(0);
this.maskExpr = exprs.get(1);
}
@Override
public Object eval(Row map) {
Object value = valueExpr.eval(map);
if (value == null)
return null;
Object maskValue = maskExpr.eval(map);
if (maskValue == null)
return null;
int maskNumber = -1;
if (maskValue instanceof Integer) {
maskNumber = (Integer) maskValue;
} else if (maskValue instanceof Long) {
maskNumber = ((Long) maskValue).intValue();
} else if (maskValue instanceof Short) {
maskNumber = ((Short) maskValue).intValue();
} else {
return null;
}
if (maskNumber < 0 || maskNumber > 128)
return null;
if (value instanceof InetAddress)
return applyMask((InetAddress) value, maskNumber);
else
return applyMask(InetAddresses.forString(value.toString()), maskNumber);
}
private String applyMask(InetAddress ip, int maskNumber) {
if (ip == null)
return null;
int length = ip.getAddress().length;
if (length == 4 && (maskNumber < 0 || maskNumber > 32))
return null;
else if (length == 16 && (maskNumber < 0 || maskNumber > 128))
return null;
byte[] mask = MASK_BITS[maskNumber];
byte[] ipByte = ip.getAddress();
byte[] result = new byte[length];
for (int i = 0; i < length; i++) {
result[i] = (byte) (mask[i] & ipByte[i]);
}
try {
return InetAddress.getByAddress(result).getHostAddress();
} catch (UnknownHostException e) {
return null;
}
}
private static byte[] initializeMask(int maskNumber) {
byte[] mask = new byte[16];
for (int i = 0; i < maskNumber; i++) {
int index = i / 8;
mask[index] |= 1 << 7 - (i % 8);
}
return mask;
}
}