| /******************************************************************************* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.apache.olingo.odata2.jpa.processor.core; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import java.io.InputStream; |
| import java.sql.Timestamp; |
| import java.util.Calendar; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| |
| import org.apache.olingo.odata2.api.edm.Edm; |
| import org.apache.olingo.odata2.api.edm.EdmException; |
| import org.apache.olingo.odata2.api.ep.EntityProvider; |
| import org.apache.olingo.odata2.api.ep.EntityProviderException; |
| import org.apache.olingo.odata2.api.exception.ODataException; |
| import org.apache.olingo.odata2.api.exception.ODataMessageException; |
| import org.apache.olingo.odata2.api.uri.UriParser; |
| import org.apache.olingo.odata2.api.uri.expression.ExpressionParserException; |
| import org.apache.olingo.odata2.api.uri.expression.FilterExpression; |
| import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLStatement; |
| import org.junit.BeforeClass; |
| import org.junit.Test; |
| |
| public class ODataFilterExpressionParserTest { |
| private static final short INPUT = 0; |
| private static final short OUTPUT = 1; |
| private static final String TABLE_ALIAS = "E1"; |
| private static final String NAMESPACE = "SalesOrderProcessing"; |
| private static final String ENTITY_NOTE = "Note"; |
| // Index 0 - Is test input and Index 1 - Is expected output |
| private static final String[] EXPRESSION_EQ = { "id eq '123'", "(E1.id LIKE '123' ESCAPE '\\')" }; |
| private static final String[] EXPRESSION_NE = { "id ne '123'", "(E1.id <> '123')" }; |
| private static final String[] EXPRESSION_ESCAPE = { "id ne '123''22'", "(E1.id <> '123''22')" }; |
| private static final String[] EXPRESSION_BINARY_AND = |
| { |
| "id le '123' and soId eq 123L and not (substringof(id,'123') eq false) eq true", |
| "(((E1.id <= '123') AND (E1.soId = 123)) AND (NOT(((CASE WHEN ('123' LIKE CONCAT('%',CONCAT(E1.id,'%')" |
| + ") ESCAPE '\\') " |
| + "THEN TRUE ELSE FALSE END) = false)) = true))" }; |
| private static final String[] EXPRESSION_BINARY_OR = { "id ge '123' or soId gt 123L", |
| "((E1.id >= '123') OR (E1.soId > 123))" }; |
| private static final String[] EXPRESSION_MEMBER_OR = { "id lt '123' or oValue/Currency eq 'INR'", |
| "((E1.id < '123') OR (E1.oValue.Currency LIKE 'INR' ESCAPE '\\'))" }; |
| private static final String[] EXPRESSION_STARTS_WITH = { "startswith(oValue/Currency,'INR')", |
| "E1.oValue.Currency LIKE CONCAT('INR','%') ESCAPE '\\'" }; |
| private static final String[] EXPRESSION_STARTS_WITH_EQUAL = { "startswith(oValue/Currency,'INR') eq true", |
| "(E1.oValue.Currency LIKE CONCAT('INR','%') ESCAPE '\\' )" }; |
| private static final String[] EXPRESSION_NOT_STARTS_WITH = { "startswith(oValue/Currency,'INR') eq false", |
| "(E1.oValue.Currency NOT LIKE CONCAT('INR','%') ESCAPE '\\' )" }; |
| private static final String[] EXPRESSION_NOT_ENDS_WITH = { "endswith(oValue/Currency,tolower('INR')) eq false", |
| "(E1.oValue.Currency NOT LIKE CONCAT('%',LOWER('INR')) ESCAPE '\\' )" }; |
| private static final String[] EXPRESSION_NESTED_METHOD = { |
| "endswith(substring(oValue/Currency,2),'INR') eq false", |
| "(SUBSTRING(E1.oValue.Currency, 2 + 1 ) NOT LIKE CONCAT('%','INR') ESCAPE '\\' )" }; |
| private static final String[] EXPRESSION_SUBSTRING_OF = { |
| "substringof(id,'123') ne true", |
| "((CASE WHEN ('123' LIKE CONCAT('%',CONCAT(E1.id,'%')) ESCAPE '\\') THEN TRUE ELSE FALSE END) <> true)" }; |
| private static final String[] EXPRESSION_STARTS_WITH_WRONG_OP = { "startswith(oValue/Currency,'INR') lt true", "" }; |
| private static final String[] EXPRESSION_SUBSTRING_ALL_OP = { "substring(oValue/Currency,1,3) eq 'INR'", |
| "(SUBSTRING(E1.oValue.Currency, 1 + 1 , 3) LIKE 'INR' ESCAPE '\\')" }; |
| private static final String[] EXPRESSION_SUBSTRINGOF_INJECTION1 = { |
| "substringof('a'' OR 1=1 OR E1.id LIKE ''b',id) eq true", |
| "((CASE WHEN (E1.id LIKE CONCAT('%',CONCAT('a'' OR 1=1 OR E1.id LIKE ''b','%')) ESCAPE '\\') " |
| + "THEN TRUE ELSE FALSE END) = true)" }; |
| private static final String[] EXPRESSION_SUBSTRINGOF_INJECTION2 = |
| { |
| "substringof('substringof(''a'' OR 1=1 OR E1.id LIKE ''b'',id)',id) eq true", |
| "((CASE WHEN (E1.id LIKE CONCAT('%',CONCAT('substringof(''a'' OR 1=1 OR E1.id LIKE ''b'',id)','%')) ESCAPE '\\') " |
| + "THEN TRUE ELSE FALSE END) = true)" }; |
| private static final String[] EXPRESSION_SUBSTRINGOF_INJECTION3 = |
| { |
| "substringof( substring(' ) OR execute_my_sql OR '' LIKE ',3),'de''') eq true", |
| "((CASE WHEN ('de''' LIKE CONCAT('%',CONCAT(SUBSTRING(' ) OR execute_my_sql OR '' LIKE ', 3 + 1 ),'%')" |
| + ") ESCAPE '\\') " |
| + "THEN TRUE ELSE FALSE END) = true)" }; |
| private static final String[] EXPRESSION_ENDSWITH_INJECTION1 = { "endswith(id,'Str''eet') eq true", |
| "(E1.id LIKE CONCAT('%','Str''eet') ESCAPE '\\' )" }; |
| private static final String[] EXPRESSION_PRECEDENCE = { |
| "id eq '123' and id ne '123' or (id eq '123' and id ne '123')", |
| "(((E1.id LIKE '123' ESCAPE '\\') AND (E1.id <> '123')) OR ((E1.id LIKE '123' ESCAPE '\\') " |
| + "AND (E1.id <> '123')))" }; |
| private static final String[] EXPRESSION_DATETIME = { "date eq datetime'2000-01-01T00:00:00'", |
| "(E1.date = 2000-01-01 00:00:00.000)" }; |
| |
| private static final String[] EXPRESSION_NULL = { "date eq null", "(E1.date IS null)" }; |
| |
| private static final String[] EXPRESSION_NOT_NULL = { "date ne null", "(E1.date IS NOT null)" }; |
| |
| private static final String[] EXPRESSION_STARTSWITH_EQBINARY = { "startswith(id,'123') and text eq 'abc'", |
| "(E1.id LIKE CONCAT('123','%') ESCAPE '\\' AND (E1.text LIKE 'abc' ESCAPE '\\'))" }; |
| |
| private static final String[] EXPRESSION_STARTSWITHEQ_EQBINARY = { "startswith(id,'123') eq true and text eq 'abc'", |
| "((E1.id LIKE CONCAT('123','%') ESCAPE '\\' ) AND (E1.text LIKE 'abc' ESCAPE '\\'))" }; |
| |
| private static final String[] EXPRESSION_EQBINARY_STARTSWITH = { "text eq 'abc' and startswith(id,'123')", |
| "((E1.text LIKE 'abc' ESCAPE '\\') AND E1.id LIKE CONCAT('123','%') ESCAPE '\\')" }; |
| |
| private static final String[] EXPRESSION_EQBINARY_STARTSWITHEQ = { "text eq 'abc' and startswith(id,'123') eq true", |
| "((E1.text LIKE 'abc' ESCAPE '\\') AND (E1.id LIKE CONCAT('123','%') ESCAPE '\\' ))" }; |
| |
| private static final String[] EXPRESSION_STARTSWITH_STARTSWITH = { "startswith(text,'abc') and startswith(id,'123')", |
| "(E1.text LIKE CONCAT('abc','%') ESCAPE '\\' AND E1.id LIKE CONCAT('123','%') ESCAPE '\\')" }; |
| |
| private static final String[] EXPRESSION_STARTSWITHEQ_STARTSWITHEQ = { |
| "startswith(text,'abc') eq true and startswith(id,'123') eq true", |
| "((E1.text LIKE CONCAT('abc','%') ESCAPE '\\' ) AND (E1.id LIKE CONCAT('123','%') ESCAPE '\\' ))" }; |
| |
| private static final String[] EXPRESSION_STARTSWITH_ANDTRUE = {"startswith(text,'abc') and true", |
| "(E1.text LIKE CONCAT('abc','%') ESCAPE '\\' AND true)"}; |
| |
| private static final String[] EXPRESSION_STARTSWITHEQTRUE_ANDTRUE = {"startswith(text,'abc') eq true and true", |
| "((E1.text LIKE CONCAT('abc','%') ESCAPE '\\' ) AND true)"}; |
| |
| private static final String[] EXPRESSION_NULL_EQ = { "id eq null", "(E1.id IS null)" }; |
| |
| private static final String[] EXPRESSION_GUID_EQ = { |
| "ExternalRecommendationUUID eq guid'56fe79b1-1c88-465b-b309-33bf8b8f6800'", |
| "(E1.ExternalRecommendationUUID = 56fe79b1-1c88-465b-b309-33bf8b8f6800)" }; |
| |
| private static Edm edm = null; |
| |
| @BeforeClass |
| public static void setup() { |
| InputStream metadataStream = |
| ODataFilterExpressionParserTest.class.getClassLoader().getResourceAsStream("metadata.xml"); |
| try { |
| edm = EntityProvider.readMetadata(metadataStream, true); |
| } catch (EntityProviderException e) { |
| fail("Not expected"); |
| } |
| } |
| |
| @Test |
| public void testUUID() { |
| String whereExpression = parseWhereExpression(EXPRESSION_GUID_EQ[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_GUID_EQ[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testDateTime() { |
| String whereExpression = parseWhereExpression(EXPRESSION_DATETIME[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_DATETIME[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testPrecedence() { |
| String whereExpression = parseWhereExpression(EXPRESSION_PRECEDENCE[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_PRECEDENCE[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testSubStringOfSQLInjection() { |
| String whereExpression = parseWhereExpression(EXPRESSION_SUBSTRINGOF_INJECTION1[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_SUBSTRINGOF_INJECTION1[OUTPUT], whereExpression); |
| |
| whereExpression = parseWhereExpression(EXPRESSION_SUBSTRINGOF_INJECTION2[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_SUBSTRINGOF_INJECTION2[OUTPUT], whereExpression); |
| |
| whereExpression = parseWhereExpression(EXPRESSION_SUBSTRINGOF_INJECTION3[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_SUBSTRINGOF_INJECTION3[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testEndsWithSQLInjection() { |
| String whereExpression = parseWhereExpression(EXPRESSION_ENDSWITH_INJECTION1[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_ENDSWITH_INJECTION1[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testSubStringWithAllOperator() { |
| String whereExpression = parseWhereExpression(EXPRESSION_SUBSTRING_ALL_OP[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_SUBSTRING_ALL_OP[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testStartsWithWrongOperator() { |
| parseWhereExpression(EXPRESSION_STARTS_WITH_WRONG_OP[INPUT], true); |
| } |
| |
| @Test |
| public void testSubStringOf() { |
| String whereExpression = parseWhereExpression(EXPRESSION_SUBSTRING_OF[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_SUBSTRING_OF[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testStartsWithEqual() { |
| String whereExpression = parseWhereExpression(EXPRESSION_STARTS_WITH_EQUAL[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_STARTS_WITH_EQUAL[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testEscapeCharacters() { |
| String whereExpression = parseWhereExpression(EXPRESSION_ESCAPE[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_ESCAPE[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testNotEndsWithToLowerMethod() { |
| String whereExpression = parseWhereExpression(EXPRESSION_NOT_ENDS_WITH[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_NOT_ENDS_WITH[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testNestedMethod() { |
| String whereExpression = parseWhereExpression(EXPRESSION_NESTED_METHOD[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_NESTED_METHOD[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testNotStartsWith() { |
| String whereExpression = parseWhereExpression(EXPRESSION_NOT_STARTS_WITH[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_NOT_STARTS_WITH[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testStartsWith() { |
| String whereExpression = parseWhereExpression(EXPRESSION_STARTS_WITH[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_STARTS_WITH[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testSimpleEqRelation() { |
| String whereExpression = parseWhereExpression(EXPRESSION_EQ[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_EQ[OUTPUT], whereExpression); |
| |
| } |
| |
| @Test |
| public void testNullEqRelation() { |
| String whereExpression = parseWhereExpression(EXPRESSION_NULL_EQ[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_NULL_EQ[OUTPUT], whereExpression); |
| |
| } |
| |
| @Test |
| public void testSimpleNeRelation() { |
| String whereExpression = parseWhereExpression(EXPRESSION_NE[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_NE[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testBinaryAnd() { |
| String whereExpression = parseWhereExpression(EXPRESSION_BINARY_AND[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_BINARY_AND[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testBinaryOr() { |
| String whereExpression = parseWhereExpression(EXPRESSION_BINARY_OR[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_BINARY_OR[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testMemberOr() { |
| String whereExpression = parseWhereExpression(EXPRESSION_MEMBER_OR[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_MEMBER_OR[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testNull() { |
| String whereExpression = parseWhereExpression(EXPRESSION_NULL[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_NULL[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testNotNull() { |
| String whereExpression = parseWhereExpression(EXPRESSION_NOT_NULL[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_NOT_NULL[OUTPUT], whereExpression); |
| } |
| |
| private String parseWhereExpression(final String input, final boolean isExceptionExpected) { |
| FilterExpression expression; |
| try { |
| expression = UriParser.parseFilter(edm, edm.getEntityType(NAMESPACE, ENTITY_NOTE), input); |
| String expressionString = ODataExpressionParser.parseToJPAWhereExpression(expression, TABLE_ALIAS); |
| return expressionString; |
| } catch (ExpressionParserException e) { |
| fail("Not expected"); |
| } catch (EdmException e) { |
| fail("Not expected"); |
| } catch (ODataMessageException e) { |
| fail("Not expected"); |
| } catch (ODataException e) { |
| if (isExceptionExpected) { |
| assertTrue(true); |
| } else { |
| fail("Not expected"); |
| } |
| } |
| return ""; |
| } |
| |
| @Test |
| public void testStartsWith_BinaryEq() { |
| String whereExpression = parseWhereExpression( |
| EXPRESSION_STARTSWITH_EQBINARY[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_STARTSWITH_EQBINARY[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testBinaryEq_StartsWith() { |
| String whereExpression = parseWhereExpression( |
| EXPRESSION_EQBINARY_STARTSWITH[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_EQBINARY_STARTSWITH[OUTPUT], whereExpression); |
| } |
| |
| public void testStartsWithEq_BinaryEq() { |
| String whereExpression = parseWhereExpression( |
| EXPRESSION_STARTSWITHEQ_EQBINARY[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_STARTSWITHEQ_EQBINARY[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testBinaryEq_StartsWithEq() { |
| String whereExpression = parseWhereExpression( |
| EXPRESSION_EQBINARY_STARTSWITHEQ[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_EQBINARY_STARTSWITHEQ[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testStartsWith_StartsWith() { |
| String whereExpression = parseWhereExpression( |
| EXPRESSION_STARTSWITH_STARTSWITH[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_STARTSWITH_STARTSWITH[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testStartsWithEq_StartsWithEq() { |
| String whereExpression = parseWhereExpression( |
| EXPRESSION_STARTSWITHEQ_STARTSWITHEQ[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_STARTSWITHEQ_STARTSWITHEQ[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testStartsWithEq_AndTrue() { |
| String whereExpression = parseWhereExpression( |
| EXPRESSION_STARTSWITHEQTRUE_ANDTRUE[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_STARTSWITHEQTRUE_ANDTRUE[OUTPUT], whereExpression); |
| } |
| |
| @Test |
| public void testStarts_AndTrue() { |
| String whereExpression = parseWhereExpression( |
| EXPRESSION_STARTSWITH_ANDTRUE[INPUT], false); |
| whereExpression = replacePositionalParameters(whereExpression); |
| assertEquals(EXPRESSION_STARTSWITH_ANDTRUE[OUTPUT], whereExpression); |
| } |
| |
| private String replacePositionalParameters(String whereExpression) { |
| Map<Integer, Object> positionalParameters = ODataExpressionParser.getPositionalParametersThreadLocal(); |
| for (Entry<Integer, Object> param : positionalParameters.entrySet()) { |
| Integer key = param.getKey(); |
| if (param.getValue() instanceof String) { |
| whereExpression = whereExpression.replaceAll("\\?" + String.valueOf(key), "\'" + param.getValue() + "\'"); |
| } else if (param.getValue() instanceof Timestamp || param.getValue() instanceof Calendar){ |
| Calendar datetime = (Calendar) param.getValue(); |
| String year = String.format("%04d", datetime.get(Calendar.YEAR)); |
| String month = String.format("%02d", datetime.get(Calendar.MONTH) + 1); |
| String day = String.format("%02d", datetime.get(Calendar.DAY_OF_MONTH)); |
| String hour = String.format("%02d", datetime.get(Calendar.HOUR_OF_DAY)); |
| String min = String.format("%02d", datetime.get(Calendar.MINUTE)); |
| String sec = String.format("%02d", datetime.get(Calendar.SECOND)); |
| String value = |
| year + JPQLStatement.DELIMITER.HYPHEN + month + JPQLStatement.DELIMITER.HYPHEN + day |
| + JPQLStatement.DELIMITER.SPACE + hour + JPQLStatement.DELIMITER.COLON + min |
| + JPQLStatement.DELIMITER.COLON + sec + JPQLStatement.KEYWORD.OFFSET; |
| whereExpression = whereExpression.replaceAll("\\?" + String.valueOf(key), value); |
| } else if(param.getValue() instanceof Byte[]){ |
| byte[] byteValue = convertToByte((Byte[])param.getValue()); |
| whereExpression = whereExpression.replaceAll("\\?" + String.valueOf(key), new String(byteValue)); |
| }else { |
| whereExpression = whereExpression.replaceAll("\\?" + String.valueOf(key), param.getValue().toString()); |
| } |
| } |
| return whereExpression; |
| } |
| |
| private byte[] convertToByte(Byte[] value) { |
| int length = value.length; |
| if (length == 0) { |
| return new byte[0]; |
| } |
| final byte[] result = new byte[length]; |
| for (int i = 0; i < length; i++) { |
| result[i] = value[i]; |
| } |
| return result; |
| } |
| } |