All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.firebase.database.core.ValidationPath Maven / Gradle / Ivy

Go to download

This is the official Firebase Admin Java SDK. Build extraordinary native JVM apps in minutes with Firebase. The Firebase platform can power your app’s backend, user authentication, static hosting, and more.

There is a newer version: 9.3.0
Show newest version
/*
 * Copyright 2017 Google 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 com.google.firebase.database.core;

import com.google.firebase.database.DatabaseException;
import com.google.firebase.database.snapshot.ChildKey;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Dynamic (mutable) path used to count path lengths.
 *
 * 

This class is used to efficiently check paths for valid length (in UTF8 bytes) and depth (used * in path validation). * *

The definition of a path always begins with '/'. */ public class ValidationPath { public static final int MAX_PATH_LENGTH_BYTES = 768; public static final int MAX_PATH_DEPTH = 32; private final List parts = new ArrayList<>(); private int byteLength = 0; private ValidationPath(Path path) throws DatabaseException { for (ChildKey key : path) { parts.add(key.asString()); } // Initialize to number of '/' chars needed in path. byteLength = Math.max(1, parts.size()); for (int i = 0; i < parts.size(); i++) { byteLength += utf8Bytes(parts.get(i)); } checkValid(); } public static void validateWithObject(Path path, Object value) throws DatabaseException { new ValidationPath(path).withObject(value); } private static String joinStringList(String delimeter, List parts) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < parts.size(); i++) { if (i > 0) { sb.append(delimeter); } sb.append(parts.get(i)); } return sb.toString(); } /* * Compute UTF-8 encoding size in bytes w/o realizing the string in * memory (which is what String.getBytes('UTF-8').length would do). */ private static int utf8Bytes(CharSequence sequence) { int count = 0; for (int i = 0, len = sequence.length(); i < len; i++) { char ch = sequence.charAt(i); if (ch <= 0x7F) { count++; } else if (ch <= 0x7FF) { count += 2; } else if (Character.isHighSurrogate(ch)) { count += 4; ++i; } else { count += 3; } } return count; } @SuppressWarnings({"unchecked", "rawtypes"}) private void withObject(Object value) throws DatabaseException { if (value instanceof Map) { Map mapValue = (Map) value; for (String key : mapValue.keySet()) { if (key.startsWith(".")) { continue; } push(key); withObject(mapValue.get(key)); pop(); } return; } if (value instanceof List) { List listValue = (List) value; for (int i = 0; i < listValue.size(); ++i) { String key = Integer.toString(i); push(key); withObject(listValue.get(i)); pop(); } } } private void push(String child) throws DatabaseException { // Count the '/' if (parts.size() > 0) { byteLength += 1; } parts.add(child); byteLength += utf8Bytes(child); checkValid(); } private String pop() { String last = parts.remove(parts.size() - 1); byteLength -= utf8Bytes(last); // Un-count the previous '/' if (parts.size() > 0) { byteLength -= 1; } return last; } private void checkValid() throws DatabaseException { if (byteLength > MAX_PATH_LENGTH_BYTES) { throw new DatabaseException( "Data has a key path longer than " + MAX_PATH_LENGTH_BYTES + " bytes (" + byteLength + ")."); } if (parts.size() > MAX_PATH_DEPTH) { throw new DatabaseException( "Path specified exceeds the maximum depth that can be written (" + MAX_PATH_DEPTH + ") or object contains a cycle " + toErrorString()); } } private String toErrorString() { if (parts.size() == 0) { return ""; } return "in path \'" + joinStringList("/", parts) + "\'"; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy