Skip to content

Commit 22e0c60

Browse files
Doing static static member invocation the right way... fixing ObjConv is
protocols expr bug, optimizing and improving, docs
1 parent 6b93039 commit 22e0c60

File tree

10 files changed

+194
-209
lines changed

10 files changed

+194
-209
lines changed

SerialX-core/src/main/java/org/ugp/serialx/Utils.java

Lines changed: 86 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -181,17 +181,17 @@ public static Object InvokeFunc(Object obj, Class<?> objCls, String name, Class<
181181
try
182182
{
183183
Method method = objCls.getMethod(name, argClasses);
184-
Object resualt = method.invoke(obj, args);
185-
return method.getReturnType().equals(void.class) ? VOID : resualt;
184+
Object result = method.invoke(obj, args);
185+
return method.getReturnType().equals(void.class) ? VOID : result;
186186
}
187187
catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException find)
188188
{
189189
for (Method method : objCls.getMethods())
190190
if (method.getName().equals(name))
191191
try
192192
{
193-
Object resualt = method.invoke(obj, args);
194-
return method.getReturnType().equals(void.class) ? VOID : resualt;
193+
Object result = method.invoke(obj, args);
194+
return method.getReturnType().equals(void.class) ? VOID : result;
195195
}
196196
catch (IllegalArgumentException e)
197197
{}
@@ -224,8 +224,8 @@ public static <T> T Clone(T obj)
224224
/**
225225
* @param obj | Object to clone.
226226
* @param parsersToUse | Parsers that will be used for cloning...
227-
* @param converterArgs | Argument for {@link DataConverter#objToString(Registry, Object, Object...)}!
228-
* @param parserArgs | Arguments for {@link DataParser#parseObj(Registry, String, boolean, Class[], Object...)}!
227+
* @param converterArgs | Argument for {@link DataConverter#objToString(Object, Object...)}!
228+
* @param parserArgs | Arguments for {@link ParserRegistry#parse(String, boolean, Class, Object...)}!
229229
*
230230
* @return Cloned object using {@link DataParser}, {@link DataConverter} and {@link SerializationProtocol} or the same object as inserted one if cloning is not possible, for instance when protocol was not found and object is not instance of {@link Cloneable}.
231231
* This clone function will always prioritized the Protocol variation, regular cloning is used only when there is no protocol registered or exception occurs. <br>
@@ -534,18 +534,21 @@ public static String[] splitValues(String s, int i, int limit, int splittingStra
534534

535535
List<String> result = new ArrayList<>();
536536

537-
int brackets = 0, quote = 0, lastIndex = 0, len = s.length();
537+
int brackets = 0, lastIndex = 0, len = s.length();
538538
for (int count = 1, oldCh = 0; i < len && (limit <= 0 || count < limit); i++)
539539
{
540540
char ch = s.charAt(i);
541541
if (ch == '"')
542-
quote++;
543-
544-
if (quote % 2 == 0)
542+
{
543+
do if (++i >= len)
544+
throw new IllegalArgumentException("Unclosed or missing quotes in: " + s);
545+
while (s.charAt(i) != '"');
546+
}
547+
else
545548
{
546549
if (isOneOf(ch, splitBreaks))
547550
{
548-
brackets = quote = 0;
551+
brackets = 0;
549552
break;
550553
}
551554

@@ -576,13 +579,8 @@ else if ((ch | ' ') == '}')
576579

577580
if (brackets > 0)
578581
throw new IllegalArgumentException("Unclosed brackets in: " + s);
579-
else if (quote % 2 != 0)
580-
throw new IllegalArgumentException("Unclosed or missing quotes in: " + s);
581-
else
582-
{
583-
result.add(s.substring(lastIndex, len).trim());
584-
}
585-
582+
583+
result.add(s.substring(lastIndex, len).trim());
586584
return result.toArray(new String[0]);
587585
}
588586

@@ -609,98 +607,101 @@ public static int indexOfNotInObj(CharSequence s, char... oneOf)
609607
*
610608
* @return Index of first character found that is not in object meaning it is not in string nor between '{' or '[' and ']' or '}', otherwise -1!
611609
*
612-
* @since 1.3.5
610+
* @since 1.3.5 (expanded in 1.3.8)
613611
*/
614612
public static int indexOfNotInObj(CharSequence s, int from, int to, int defaultReturn, boolean firstIndex, char... oneOf)
615613
{
616-
for (int brackets = 0, quote = 0; from < to; from++)
614+
for (int brackets = 0; from < to; from++)
617615
{
618616
char ch = s.charAt(from);
619617
if (ch == '"')
620-
quote++;
621-
622-
if (quote % 2 == 0)
618+
while (++from < to && s.charAt(from) != '"');
619+
else if (brackets == 0 && /*oneOf.length == 0 ? ch == oneOf[0] :*/ isOneOf(ch, oneOf))
623620
{
624-
if (brackets == 0 && /*oneOf.length == 0 ? ch == oneOf[0] :*/ isOneOf(ch, oneOf))
625-
{
626-
if (firstIndex)
627-
return from;
628-
defaultReturn = from;
629-
}
630-
else if ((ch | ' ') == '{')
631-
brackets++;
632-
else if ((ch | ' ') == '}')
633-
{
634-
if (brackets > 0)
635-
brackets--;
636-
else
637-
throw new IllegalArgumentException("Missing closing bracket in: " + s);
638-
}
621+
if (firstIndex)
622+
return from;
623+
defaultReturn = from;
624+
}
625+
else if ((ch | ' ') == '{')
626+
brackets++;
627+
else if ((ch | ' ') == '}')
628+
{
629+
if (brackets > 0)
630+
brackets--;
631+
else
632+
throw new IllegalArgumentException("Missing closing bracket in: " + s);
639633
}
640634
}
641635
return defaultReturn;
642636
}
643637

644638
/**
645639
* @param s | CharSequence to search!
646-
* @param sequenceToFind | CharSequence to find!
640+
* @param sequencesToFind | Character sequences to find, index of any of these will be returned accordingly, none of these should contain and object structure!
647641
*
648642
* @return Index of first found CharSequence that is not in object meaning it is not in string nor between '{' or '[' and ']' or '}'!
649643
*
650644
* @since 1.3.0
651645
*/
652-
public static int indexOfNotInObj(CharSequence s, CharSequence sequenceToFind)
646+
public static int indexOfNotInObj(CharSequence s, CharSequence... sequencesToFind)
653647
{
654-
return indexOfNotInObj(s, sequenceToFind, true);
648+
return indexOfNotInObj(s, 0, s.length(), -1, true, sequencesToFind);
655649
}
656650

657651
/**
658652
* @param s | CharSequence to search!
659-
* @param sequenceToFind | CharSequence to find!
653+
* @param from | The beginning index, where to start the search (should be 0 in most cases).
654+
* @param to | Ending index of search (exclusive, should be s.length()).
655+
* @param defaultReturn | Index to return by default (usually -1).
660656
* @param firstIndex | If true, first index will be returned, if false last index will be returned.
657+
* @param sequencesToFind | Character sequences to find, index of any of these will be returned accordingly, none of these should contain and object structure!
661658
*
662659
* @return Index of first found CharSequence that is not in object meaning it is not in string nor between '{' or '[' and ']' or '}'!
663660
*
664-
* @since 1.3.5
661+
* @since 1.3.5 (expanded in 1.3.8)
665662
*/
666-
public static int indexOfNotInObj(CharSequence s, CharSequence sequenceToFind, boolean firstIndex)
663+
public static int indexOfNotInObj(CharSequence s, int from, int to, int defaultReturn, boolean firstIndex, CharSequence... sequencesToFind)
667664
{
668-
int len = s.length(), lenToFind = sequenceToFind.length();
669-
if (len < lenToFind)
670-
return -1;
671-
int found = -1;
672-
for (int i = 0, brackets = 0, quote = 0, match = 0; i < len; i++)
665+
if (sequencesToFind.length < 1)
666+
return defaultReturn;
667+
668+
for (int brackets = 0; from < to; from++)
673669
{
674-
char ch = s.charAt(i);
670+
char ch = s.charAt(from);
675671
if (ch == '"')
676-
quote++;
677-
678-
if (quote % 2 == 0)
672+
while (++from < to && s.charAt(from) != '"');
673+
else if ((ch | ' ') == '{')
674+
brackets++;
675+
else if ((ch | ' ') == '}')
679676
{
680-
if (brackets == 0 && ch == sequenceToFind.charAt(match++))
677+
if (brackets > 0)
678+
brackets--;
679+
else
680+
throw new IllegalArgumentException("Missing closing bracket in: " + s);
681+
}
682+
else if (brackets == 0)
683+
{
684+
findMatch: for (int cur = 0, seqsLen = sequencesToFind.length; cur < seqsLen; cur++)
681685
{
682-
if (match == lenToFind)
686+
CharSequence currentMatch;
687+
if (ch == (currentMatch = sequencesToFind[cur]).charAt(0))
683688
{
684-
found = i - match + 1;
685-
if (firstIndex)
686-
return found;
687-
match = 0;
689+
int match = 1, lenToFind = currentMatch.length();
690+
for (int i = from+1; i < to && match < lenToFind; i++, match++)
691+
if (s.charAt(i) != currentMatch.charAt(match))
692+
continue findMatch;
693+
694+
if (match == lenToFind)
695+
{
696+
defaultReturn = from;
697+
if (firstIndex)
698+
return defaultReturn;
699+
}
688700
}
689701
}
690-
else if ((ch | ' ') == '{')
691-
brackets++;
692-
else if ((ch | ' ') == '}')
693-
{
694-
if (brackets > 0)
695-
brackets--;
696-
else
697-
throw new IllegalArgumentException("Missing closing bracket in: " + s);
698-
}
699-
else
700-
match = 0;
701702
}
702703
}
703-
return found;
704+
return defaultReturn;
704705
}
705706

706707
/**
@@ -798,14 +799,26 @@ public static boolean equalsLowerCase(CharSequence str, CharSequence lowerCaseOt
798799
* @param str | String to display!
799800
* @param pos | Position to display!
800801
*
801-
* @return String with displayed position by using »!
802+
* @return String with displayed position by using » or ^ under it!
802803
* Use for debugging or error printing!
803804
*
804805
* @since 1.3.2
805806
*/
806807
public static String showPosInString(CharSequence str, int pos)
807808
{
808-
return str.subSequence(0, pos) + "»" + str.subSequence(pos, str.length());
809+
if (pos < 0)
810+
return str.toString();
811+
812+
try
813+
{
814+
if (contains(str, '\n', '\r'))
815+
return str.subSequence(0, pos) + "»" + str.subSequence(pos, str.length());
816+
return multilpy(' ', pos).append('^').insert(0, '\n').insert(0, str).toString();
817+
}
818+
catch (IndexOutOfBoundsException e)
819+
{
820+
return str.toString();
821+
}
809822
}
810823

811824
/* Arrays */

SerialX-core/src/main/java/org/ugp/serialx/converters/DataConverter.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package org.ugp.serialx.converters;
22

3-
import org.ugp.serialx.Registry;
4-
53
/**
64
* This is DataParser with extended functionality! {@link DataConverter} can also parse data like DataParser but is also capable of converting them back to string!
75
* This to string convertation is performed by {@link DataConverter#toString(Object)} and result of this convertation supposed to be parsable by {@link DataConverter#parse(String, Object...)} meaning one converter supposed to be parsing and converting via the same string format!
@@ -15,7 +13,7 @@
1513
public interface DataConverter extends DataParser
1614
{
1715
/**
18-
* @param myHomeRegistry | Registry where this parser is registered provided by {@link DataParser#parseObj(Registry, String, boolean, Class[], Object...)} otherwise it demands on implementation (it should not be null)!
16+
* @param myHomeRegistry | Registry where this parser is registered provided by {@link ParserRegistry#parse(String, boolean, Class, Object...)} otherwise it demands on implementation (it should not be null)!
1917
* @param obj | Object to convert into string!
2018
* @param args | Some additional args. This can be anything and it demands on implementation of DataConverter. Default SerialX API implementation will provide some flags about formating (2 ints)!
2119
*

SerialX-core/src/main/java/org/ugp/serialx/converters/DataParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public interface DataParser
4444
public static final ParserRegistry REGISTRY = new ParserRegistry(new VariableParser(), new StringConverter(), new ProtocolConverter(), new NumberConverter(), new BooleanConverter(), new CharacterConverter(), new NullConverter(), new SerializableBase64Converter());
4545

4646
/**
47-
* @param myHomeRegistry | Registry where this parser is registered provided by {@link DataParser#parseObj(Registry, String, boolean, Class[], Object...)} otherwise it demands on implementation (it should not be null)!
47+
* @param myHomeRegistry | Registry where this parser is registered provided by {@link DataParser#parse(String, boolean, Class, Object...)} otherwise it demands on implementation (it should not be null)!
4848
* @param str | Source string, preferably trimed!
4949
* @param args | Some additional args. This can be anything and it demands on implementation of DataParser. Default SerialX API implementation will provide one optional argument with {@link Scope} that value was loaded from!
5050
*

SerialX-core/src/main/java/org/ugp/serialx/converters/ProtocolConverter.java

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
import java.util.ArrayList;
1010
import java.util.Arrays;
1111
import java.util.Base64;
12+
import java.util.HashSet;
13+
import java.util.Set;
1214

1315
import org.ugp.serialx.GenericScope;
1416
import org.ugp.serialx.LogProvider;
15-
import org.ugp.serialx.Registry;
1617
import org.ugp.serialx.Scope;
1718
import org.ugp.serialx.Serializer;
1819
import org.ugp.serialx.Utils;
@@ -70,17 +71,17 @@ public class ProtocolConverter implements DataConverter
7071
*/
7172
protected boolean useBase64IfCan = false;
7273

73-
protected boolean allowStaticMemberInvocation = false;
74+
protected Set<Class<?>> invokableClasses = new HashSet<>(Arrays.asList(Math.class, Scope.class, Double.class, Float.class, String.class));
7475

7576
@Override
7677
public Object parse(ParserRegistry myHomeRegistry, String str, Object... compilerArgs)
7778
{
78-
int len;
79+
int len;
7980
if ((len = str.length()) > 0)
8081
{
8182
if ((str.charAt(0) | ' ') == '{' && (str.charAt(--len) | ' ') == '}') // Unwrap if wrapped in {}
8283
str = str.substring(1, len).trim();
83-
84+
8485
Class<?> objClass;
8586
if ((objClass = getProtocolExprClass(str, compilerArgs)) != null) // Get class of protocol expr or continue if there is none
8687
return parse(myHomeRegistry, objClass, str, compilerArgs);
@@ -117,9 +118,9 @@ protected Object parse(ParserRegistry myHomeRegistry, Class<?> objClass, String
117118
if ((args[0].charAt(0) | ' ') != '{' && (nameIndex = args[0].indexOf("::")) > -1) //Is static member invocation
118119
{
119120
String memberName = args[0].substring(nameIndex + 2);
120-
if (!isAllowStaticMemberInvocation())
121+
if (!getInvokableClasses().contains(objClass))
121122
{
122-
LogProvider.instance.logErr("Invocation of static member \"" + memberName + "\" from class \"" + objClass.getName() + "\" was denied because this feature is disabled by default for security reasons!", null);
123+
LogProvider.instance.logErr("Invocation of static member \"" + memberName + "\" from class \"" + objClass.getName() + "\" was denied because it was not enabled for this class for security reasons!", null);
123124
return null;
124125
}
125126

@@ -169,7 +170,7 @@ public CharSequence toString(ParserRegistry myHomeRegistry, Object arg, Object..
169170
}
170171

171172
/**
172-
* @param myHomeRegistry | Registry where this parser is registered provided by {@link DataParser#parseObj(Registry, String, boolean, Class[], Object...)} otherwise it demands on implementation (it should not be null)!
173+
* @param myHomeRegistry | Registry where this parser is registered provided by {@link ParserRegistry#parse(String, boolean, Class, Object...)} otherwise it demands on implementation (it should not be null)!
173174
* @param obj | Object to convert into string!
174175
* @param preferedProtocol | Protocol to use preferably.
175176
* @param args | Some additional args. This can be anything and it demands on implementation of DataConverter. Default SerialX API implementation will provide some flags about formating (2 ints)!
@@ -277,23 +278,14 @@ public void setUseBase64IfCan(boolean useBase64IfCan)
277278
}
278279

279280
/**
280-
* @return True if invocation of static members (:: operator) is allowed (false by default)!
281-
*
282-
* @since 1.3.8
283-
*/
284-
public boolean isAllowStaticMemberInvocation()
285-
{
286-
return allowStaticMemberInvocation;
287-
}
288-
289-
/**
290-
* @param allowStaticMemberInvocation | Enable/disable the invocation of static members (:: operator) (false by default)!
281+
* @return Classes that are eligible for public static member invocation (:: operator)!<br>
282+
* Note: {@link Math} {@link Scope} {@link Double}, {@link Float} and {@link String} are invokable by default! If you want to disable static member invocation completely, call {@link Set#clear()} on this method!
291283
*
292-
* @since 1.3.8
284+
* @since 1.3.8
293285
*/
294-
public void setAllowStaticMemberInvocation(boolean allowStaticMemberInvocation)
286+
public Set<Class<?>> getInvokableClasses()
295287
{
296-
this.allowStaticMemberInvocation = allowStaticMemberInvocation;
288+
return invokableClasses;
297289
}
298290

299291
/**

SerialX-core/src/main/java/org/ugp/serialx/converters/VariableParser.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import static org.ugp.serialx.Utils.splitValues;
66

77
import org.ugp.serialx.GenericScope;
8-
import org.ugp.serialx.Registry;
98
import org.ugp.serialx.Scope;
109
import org.ugp.serialx.Serializer;
1110

@@ -51,7 +50,7 @@ public Object getMemberOperator(Object source, Object member)
5150
}
5251

5352
/**
54-
* @param myHomeRegistry | Registry where this parser is registered provided by {@link DataParser#parseObj(Registry, String, boolean, Class[], Object...)} otherwise it demands on implementation (it should not be null)!
53+
* @param myHomeRegistry | Registry where this parser is registered provided by {@link ParserRegistry#parse(String, boolean, Class, Object...)} otherwise it demands on implementation (it should not be null)!
5554
* @param str | Source string, should not be null or empty (preferably with some variables to read)!
5655
* @param scope | Source scope to read from, can't be null!
5756
* @param args | Some additional args. This can be anything and it demands on implementation of DataParser.
@@ -112,4 +111,4 @@ else if (newModif = str.endsWith("::new"))
112111

113112
return CONTINUE;
114113
}
115-
}
114+
}

0 commit comments

Comments
 (0)