There are a lot of attempts to guess password in my application
public static boolean checkIfAddressBanned(InetSocketAddress from) {
String address = from.getAddress().getHostAddress();
if (bannedAddresses.contains(address)) {
if (loggingEnabled) {
log.info(String.format("IP [%s] is banned", address));
}
return true;
}
return false;
}
What I'm trying to do is to avoid multiple calls of log.info messages which degrade performance of the server. Code snippets above simple check boolean flag is logging is enabled. I would like to rewrite code above, to write to skip some of this events.
What is the less resource consuming way to skip some messages ? For example,
if (System.currentTimeMillis() % 3 == 0)
Another example
if (atomicLong.incrementAndGet % 3 == 0)
I don't know if you have control of the code defining bannedAddresses, but would something like this work for you?
private static Map<String, Integer> bannedAddresses = new HashMap<String, Integer>();
...
public static boolean checkIfAddressBanned(InetSocketAddress from) {
String address = from.getAddress().getHostAddress();
Integer attempts = bannedAddresses.get(address);
if (attempts == null) return false;
bannedAddresses.put(address, attempts+1);
if ( (loggingEnabled) && (attempts % 50 == 1) ) {
log.info(String.format("IP [%s] is banned, %d attempts", address, attempts));
}
return true;
}
Related
I have a method having multiple if-else conditions (which is growing with each new msg-type support)
public Message<?> doTransform(Message<String> message) throws TransformationException {
try {
MessageBuilder<String> messageBuilder = null;
String payload = message.getPayload();
String payloadSubStr = payload.substring(0, Math.min(payload.length(), 100));
if(payloadSubStr.contains("<Management>")){
messageBuilder = buildManagementMsg(message);
} else if (payloadSubStr.contains("<Administration>") || (payloadSubStr.contains("<OtherAdministationAlert>"))){
messageBuilder = buildAdminMessages(message);
} else if (payloadSubStr.startsWith("Council")){
messageBuilder = parseCouncilMessages(message);
} else if (payloadSubStr.indexOf("Security") >= 0
|| payloadSubStr.indexOf("OtherSecurityAlert") >= 0){
messageBuilder = buildSecurityMessages(message);
} else if ( payloadSubStr.indexOf("<Staff>") >= 0
|| payloadSubStr.indexOf("<OtherStaffAlert>") >= 0){
messageBuilder = buildStaffMessages(message);
} else if(payloadSubStr.indexOf("<Student>") >= 0) {
messageBuilder = buildStudentMessages(message);
}else {
messageBuilder = buildOtherMessages(message);
}
return messageBuilder.build();
} catch(Exception e) {
throw new TransformationException(e);
}
}
Reason for doing substring: To avoid complete msg traversing with each if/else condition
Reason for using contains/indexOf combination: Messages received by this method can vary
Wanted to replace these if/else statements with some more cleaner logic. Not getting if Switch/Enum can be used or need to use any pattern as suggested over https://www.baeldung.com/java-replace-if-statements.
Gone through various similar questions available but not getting anything. Any suggestion will be helpful.
Thanks
If you are concerned with the number of conditions you'd need to add you could introduce a list of "message builder factories" (for lack of a better name atm) that you could append to.
A factory would contain a predicate to test the substring for and a messageBuilder(...) method. Then you'd iterate over the factory, check each of the predicates and if execute messageBuilder() on the first that matches.
Example:
interface MessageBuilderFactory<T> {
boolean test(T payload);
MessageBuilder<T> messageBuilder(Message<T> message);
}
class ManagementMBFactory implements MessageBuilderFactory<String> {
boolean test(String payload) {
return payload.contains("Management");
}
MessageBuilder<String> messageBuilder(Message<String> message) {
//content of buildManagementMsg() here
}
}
And in your code:
List<MessageBuilderFactory<String>> factories = ... //get the list of factories from somewhere
for( MessageBuilderFactory<String> factory : factories) {
if( factory.test(payloadSubStr) {
messageBuilder = factory.messageBuilder(message);
}
}
An advantage of doing it that way would be that the list of possible message builder factories is easily available and classes can be kept small (not all those buildXxx() methods in one single class).
Alternatively, if your message payload allows for that, you could actually try to parse it (it looks like XML) and operate on events, i.e. elements being found. That might be faster in the case of many small payloads and a huge number of possible message builders.
People are divided on the idea of multiple return statements in java but in this case I think I would tend to do that:
if(payloadSubStr.contains("<Management>")){
return buildManagementMsg(message);
}
if (payloadSubStr.contains("<Administration>") || (payloadSubStr.contains("<OtherAdministationAlert>"))) {
return buildAdminMessages(message);
}
if (payloadSubStr.startsWith("Council")){
return parseCouncilMessages(message);
}
if (payloadSubStr.indexOf("Security") >= 0
|| payloadSubStr.indexOf("OtherSecurityAlert") >= 0){
return buildSecurityMessages(message);
}
if ( payloadSubStr.indexOf("<Staff>") >= 0
|| payloadSubStr.indexOf("<OtherStaffAlert>") >= 0){
return buildStaffMessages(message);
}
if (payloadSubStr.indexOf("<Student>") >= 0) {
return buildStudentMessages(message);
}
return buildOtherMessages(message);
Going one step further this could be done with a validation service.
public class ValidationService {
public boolean isManagement(String str) { return str.contains("<Management>");
// ... and so on
}
And you can inject the service into the code such that you have
if (validationService.isManagement(payloadSubStr)) {
return buildManagementMsg(message);
}
// ...
For a case with conditions currently in OR you could use a list in the service, for example
public boolean isSecurity(String str) {
for (String term : new String[]{"Security", "OtherSecurityAlert"}) {
if (str.contains(term)) {
return true;
}
}
return false;
}
I have the below utility method and I am using multiple if statements and getting cognitive complexity issue. I went through some links, but I am not able to understand how should I change my code without affecting users of this method.
public static boolean isWrapperValid(WrapperClass wrapper, boolean isTechnicalToken){
String key=null;
boolean isValidWrapper = false;
if (wrapper != null && wrapper.length() > 7
&& wrapper.substring(0, 6).equalsIgnoreCase("XYZ"))
{
wrapper= wrapper.substring(7, wrapper.lastIndexOf('.')+1);
}
if(wrapper != null && wrapper.equalsIgnoreCase("TFR")) {
isValidWrapper=Boolean.TRUE;
}
try {
key = wrapper.getKey();
}
catch (Exception exception) {
return isValidWrapper;
}
if(key!=null) {
Date tokenExpiryTime = key.getExpiresAt();
if(tokenExpiryTime!=null) {
return isValidWrapper;
}
String algorithm=key.getAlgorithm();
if(!DESIRED_ALGO.equals(algorithm)) {
return isValidWrapper;
}
String value6=key.getType();
if(!DESIRED_TYPE.equals(value6)) {
return isValidWrapper;
}
if(key.getValue1()!=null && key.getValue2().size()>0 && key.getValue3()!=null && key.getValue4()!=null && key.getValue5()!=null) {
isValidWrapper=Boolean.TRUE;
}
}
return isValidWrapper;
}
Please share your suggestions to refactor this code.
I don't think that merging many if conditions to one or simply do a code clean up, for example by changing the order of some instructions, can solve your problem.
Your code does not match the single responsibility principle. You should refactor this big method to smaller parts. Due to this it will testable, easier to maintain and read. I spent some time and did this:
public static boolean isWrapperValid(WrapperClass wrapper, boolean isTechnicalToken) {
final WrapperClass unpackedWrapper = unpackWrapper(wrapper);
boolean wrapperValid = isUnpackedWrapperValid(unpackedWrapper);
Key key = null;
try {
key = unpackedWrapper.getKey();
} catch (final Exception exception) {
return wrapperValid;
}
if (key != null) {
if (doesKeyMeetsBasicConditions(key)) {
return wrapperValid;
}
if (doesKeyMeetsValueConditions(key)) {
return true;
}
}
return wrapperValid;
}
protected static WrapperClass unpackWrapper(final WrapperClass wrapper) {
if (wrapper != null && wrapper.length() > 7 && wrapper.substring(0, 6).equalsIgnoreCase("XYZ")) {
return wrapper.substring(7, wrapper.lastIndexOf('.') + 1);
}
return wrapper;
}
protected static boolean isUnpackedWrapperValid(final WrapperClass wrapper) {
return wrapper != null && wrapper.equalsIgnoreCase("TFR");
}
protected static boolean doesKeyMeetsBasicConditions(final Key key) {
Date tokenExpiryTime = key.getExpiresAt();
if (tokenExpiryTime != null) {
return true;
}
String algorithm = key.getAlgorithm();
if (!DESIRED_ALGO.equals(algorithm)) {
return true;
}
String value6 = key.getType();
return !DESIRED_TYPE.equals(value6);
}
protected static boolean doesKeyMeetsValueConditions(final Key key) {
return key.getValue1() != null && key.getValue2().size() > 0
&& key.getValue3() != null && key.getValue4() != null
&& key.getValue5() != null;
}
I don't know the domain logic, so some of my methods have stupid names etc. As you can see, now you have a lot of smaller methods with not many branches (if conditions) - easier to test (a static code is not nice, but you can mock it by using for example PowerMock).
A bit of rewriting delivered a simplification, that still could be improved upon.
public static boolean isWrapperValid(WrapperClass wrapper, boolean isTechnicalToken){
if (wrapper != null && wrapper.length() > 7
&& wrapper.substring(0, 6).equalsIgnoreCase("XYZ"))
{
wrapper = wrapper.substring(7, wrapper.lastIndexOf('.')+1);
}
boolean isValidWrapper = wrapper != null && wrapper.equalsIgnoreCase("TFR");
try {
String key = wrapper.getKey();
if (key != null && key.getExpiresAt() == null
&& DESIRED_ALGO.equals(key.getAlgorithm())
&& DESIRED_TYPE.equals(key.getType())
&& key.getValue1() != null && !key.getValue2().isEmpty()
&& key.getValue3() != null && key.getValue4() != null
&& key.getValue5() != null) {
isValidWrapper = true;
}
}
catch (Exception exception) {
// DO NOTHING
}
return isValidWrapper;
}
After comment: here I catch any exception for all calls.
First of all, Sonar should give you more flags: reusing the wrapper parameter is usually a bad practice, NPE where invoking wrapper.getKey because wrapper can be null, but anyway, not the point...
Try reducing the number of if statements by creating local boolean variables (or possibly 1 big if statement if you have less than 5 or 6 tests, but often less readable). Once it's done, you should only have 1 block testing these boolean variables, and have one return statement, like the example above (not necessarily accurate!):
boolean expired = tokenExpiryTime != null;
boolean desiredAlgo = DESIRED_ALGO.equals(key.getAlgorithm());
boolean desiredType = DESIRED_TYPE.equals(value6);
if (expired || !desiredAlgo || !desiredType) {
return isValidWrapper;
}
However, your Cognitive complexity level seems pretty low if this kind of algorithm triggers it...
Another big way to reduce an algorithm complexity is to turn sub-blocks of code (loops, if and try-catch) into private methods. In your example, it could be something like a checkWrapperValidity method, responsible for every test returning isValidWrapper
Given an unordered set of Java File objects, I want to eliminate all those that are subdirectories (or files in subdirectories) of other Files in the set. For instance, given:
File("/john/paul/george/ringo")
File("/foo/bar/baz")
File("/foo/bar/elvis")
File("/john/paul")
File("/john/jacob")
File("/foo/bar/baz/qux/quux")
File("/john/")
File("/foo/bar/")
the set should reduce to:
File("/foo/bar/")
File("/john/")
I can imagine cobbling something together based on converting to Strings with File.getAbsolutePath() and sorting (possibly by length first, then lexicographically), but surely this is a solved problem, or at least somebody must already have written utility methods for things like determining whether one File is an ancestor of another.
I'm not the best of programmers, but here's my shot at it. There's quite a bit of recursion involved.
class UniqueDirectories {
private final Map<String, UniqueDirectories> directories = new HashMap<String, UniqueDirectories>();
private boolean locked = false;
public UniqueDirectories() {}
private UniqueDirectories(boolean locked) {
this.locked = locked;
}
public boolean add(String path) {
if (path == null)
return false;
if (path.isEmpty())
return false;
if (locked)
return false;
String[] tokens = path.split("(?<!^)[/\\\\]", 2);
UniqueDirectories existingDirectory = directories.get(tokens[0]);
if (existingDirectory == null) {
if (tokens.length < 2 || tokens[1].isEmpty()) {
directories.put(tokens[0], new UniqueDirectories(true));
return true;
} else {
UniqueDirectories newDirectory = new UniqueDirectories(false);
directories.put(tokens[0], newDirectory);
return newDirectory.add(tokens[1]);
}
} else if (tokens.length >= 2 && !tokens[1].isEmpty()) {
return existingDirectory.add(tokens[1]);
} else {
directories.put(tokens[0], new UniqueDirectories(true));
return true;
}
}
public List<String> toList(char delimiter) {
List<String> list = new ArrayList<String>();
for (Map.Entry<String, UniqueDirectories> entry : directories.entrySet()) {
if (entry.getValue().directories.size() == 0) {
list.add(entry.getKey());
} else {
for (String subdirectory : entry.getValue().toList(delimiter)) {
list.add(entry.getKey() + delimiter + subdirectory);
}
}
}
return list;
}
public static void main(String[] args) {
String[] testPaths = {
"/john/paul/george/ringo",
"/foo/bar/baz",
"/foo/bar/elvis",
"/john/paul",
"/john/jacob",
"/foo/bar/baz/qux/quux",
"/john/",
"/foo/bar/"
};
UniqueDirectories directories = new UniqueDirectories();
for (String path : testPaths) {
directories.add(path);
}
System.out.println(directories.toList('/'));
}
}
Sorry about the lack of comments. Too lazy to go back and do it, but at least the code's relatively short. I haven't put it through rigorous testing either (just used the ones you provided), so you may want to use some more test cases.
The biggest thing to be careful with is consistency. If you start a path with a delimiter, all paths should start with one. Conversely, if one path does not start with a delimiter, the rest shouldn't either. Otherwise, they will be treated as different paths. You could easily fix this by removing the lookbehind in the regex though; I just wasn't sure how you wanted it to behave.
I learned about terminary expression, but what I want is a little different.
I have the following:
int MODE = getMyIntValue();
I do comparison as the following:
if(MODE == 1 || MODE == 2 || MODE == 3) //do something
I would like to know if there is a short way of doing this, I tried something like this but it didn't work:
if(MODE == 1 || 2 || 3) //do something
There is a short|quick way of doing it? I like quick "ifs" because it makes the code more clear, for example, it is more clear this:
System.out.println(MODE == 1 ? text1 : text2):
Than this:
if(MODE == 1) System.out.println(text1):
else System.out.println(text1):
Thanks in advance!
May be you can do something like this
System.out.println(Mode == 1 ? "1" : Mode == 2 ? "2" : "3");
switch-case also makes code more readable than multiple if-else
Well, if you don't mind the boxing hit, you could use a set which you prepared earlier:
// Use a more appropriate name if necessary
private static final Set<Integer> VALID_MODES
= new HashSet<>(Arrays.asList(1, 2, 3));
...
if (VALID_MODES.contains(mode)) {
}
You could use an int[] and a custom "does this array contain this value" method if you wanted... it would be O(N) or O(log N) for a binary search, but I suspect we're talking about small sets anyway.
I strongly recommend to use a more typed approach:
public class QuickIntSample {
enum Modes {
ONE(1),TWO(2),THREE(3); // you may choose more useful and readable names
int code;
private Modes(int code) {
this.code = code;
}
public static Modes fromCode(final int intCode) {
for (final Modes mode : values()) {
if (mode.code == intCode) {
return mode;
}
}
return null;
}
} // -- END of enum
public static void main(String[] args) {
int mode = 2;
if( Modes.fromCode(mode) == Modes.TWO ) {
System.out.println("got code 2");
}
}
}
Can somebody please explain how can I use the composite design pattern to validate a registration form in android. In this form I have 8 EditText fields (Ussername, Password, Password re-enter, City, Gender, Age, Phone number, Email). I have already validated it using this code
public boolean validateInput() {
boolean validated = true;
if (mUserValues.getCity() == null || mUserValues.getCity().isEmpty()) {
mCityEditText.setError(getString(R.string.error));
validated = false;
}
if (mUserValues.getEmail() == null || mUserValues.getEmail().isEmpty()) {
Log.d("mEmail", "in mEmail");
mEmail.setError(getString(R.string.error));
validated = false;
}
if (mUserValues.getPassword() == null
|| mUserValues.getPassword().isEmpty()) {
mPasswordEditText.setError(getString(R.string.error));
validated = false;
}
if (mUserValues.getPasswordCheck() == null
|| mUserValues.getPasswordCheck().isEmpty()) {
mPasswordConfirm.setError(getString(R.string.error));
validated = false;
}
if (mUserValues.getPassword() != null
&& mUserValues.getPasswordCheck() != null
&& !mPasswordEditText.getText().toString()
.equals(mPasswordEditText.getText().toString())) {
mPasswordEditText.setError(getString(R.string.pass_check));
mPasswordConfirm.setError(getString(R.string.pass_check));
validated = false;
}
if (mUserValues.getSex() == null || mUserValues.getSex().isEmpty()) {
mSex.setError(getString(R.string.error));
validated = false;
}
if (mUserValues.getPhoneNumber() == 0) {
mPhone.setError(getString(R.string.error));
validated = false;
}
Pattern pattern = Pattern.compile(Constants.EMAIL_PATTERN);
Matcher matcher = pattern.matcher(mEmail.getText().toString());
mEmailCheck = matcher.matches();
if (mEmailCheck == false) {
mEmail.setError(getString(R.string.email_valid));
validated = false;
}
if (mUserValues.getUsername().length() <= 2) {
mUsername.setError(getString(R.string.username_check));
validated = false;
}
if ((mUserValues.getAge() < 18 || mUserValues.getAge() > 150)
&& mUserValues.getAge() > 0) {
mAge.setError(getString(R.string.age_check));
validated = false;
}
return validated;
}
A friend of mine told me that it can be done using the composite design pattern, but I don't really understand how can that be done.
I will be really grateful if somebody could explain.
Thanks in advance.
You are currently inspecting the state of an object (e.g. if (mUserValues.getCity() == null)) from the outside. And if you add a field to mUserValues you'll also have to add code to handle that field to validateInput.
That is bad encapsulation / strong coupling according to the OO principles. That object should handle / validate it's internal state itself (or know another object that can do it -> composite pattern).
I'd move the validation inside the object in a first step (e.g. if (!mUserValues.validateCity())).
After that you'd still need to know about the internals of your mUserValues object on the ouside - e.g. know that there is a city field to validate.
So in a next step you could get rid of that as well. The result could look roughly like
public boolean validateInput() {
boolean validated = true;
for (ValidatableField field : mUserValues.getValidatableFields()) {
if (!field.isValid()) {
field.showError(R.string.error);
validated = false;
}
}
return validated;
}
Now the validateInput code is completely independant of the amount of fields and how they have to be validated. Adding a filed does not require to change anything in there.
Wether you use composition or inheritance is up to you. But using Composition over inheritance is a good thing.