| /* |
| * 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.ignite.development.utils; |
| |
| import java.util.Base64; |
| import org.apache.ignite.IgniteCheckedException; |
| import org.apache.ignite.IgniteException; |
| import org.apache.ignite.binary.BinaryObject; |
| import org.apache.ignite.internal.pagemem.wal.record.DataEntry; |
| import org.apache.ignite.internal.pagemem.wal.record.UnwrapDataEntry; |
| import org.apache.ignite.internal.processors.cache.CacheObject; |
| import org.apache.ignite.internal.processors.cache.CacheObjectValueContext; |
| import org.apache.ignite.internal.util.IgniteUtils; |
| import org.apache.ignite.internal.util.typedef.internal.S; |
| import org.apache.ignite.internal.util.typedef.internal.SB; |
| import org.jetbrains.annotations.Nullable; |
| |
| import static org.apache.ignite.development.utils.ProcessSensitiveData.HASH; |
| import static org.apache.ignite.development.utils.ProcessSensitiveData.HIDE; |
| import static org.apache.ignite.development.utils.ProcessSensitiveData.MD5; |
| |
| /** |
| * Wrapper {@link DataEntry} for sensitive data output. |
| */ |
| class DataEntryWrapper extends DataEntry { |
| /** |
| * Source DataEntry. |
| */ |
| @Nullable private final DataEntry source; |
| |
| /** Strategy for the processing of sensitive data. */ |
| private final ProcessSensitiveData sensitiveData; |
| |
| /** |
| * Constructor. |
| * |
| * @param dataEntry Instance of {@link DataEntry}. |
| * @param sensitiveData Strategy for the processing of sensitive data. |
| */ |
| public DataEntryWrapper( |
| DataEntry dataEntry, |
| ProcessSensitiveData sensitiveData |
| ) { |
| super( |
| dataEntry.cacheId(), |
| dataEntry.key(), |
| dataEntry.value(), |
| dataEntry.op(), |
| dataEntry.nearXidVersion(), |
| dataEntry.writeVersion(), |
| dataEntry.expireTime(), |
| dataEntry.partitionId(), |
| dataEntry.partitionCounter(), |
| dataEntry.flags() |
| ); |
| |
| this.source = dataEntry; |
| |
| this.sensitiveData = sensitiveData; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override public String toString() { |
| final String keyStr; |
| final String valueStr; |
| if (source instanceof UnwrapDataEntry) { |
| final UnwrapDataEntry unwrappedDataEntry = (UnwrapDataEntry)this.source; |
| |
| keyStr = toString(unwrappedDataEntry.unwrappedKey(), this.source.key()); |
| |
| valueStr = toString(unwrappedDataEntry.unwrappedValue(), this.source.value()); |
| } |
| else { |
| keyStr = toString(null, this.source.key()); |
| |
| valueStr = toString(null, this.source.value()); |
| } |
| |
| return new SB(this.source.getClass().getSimpleName()) |
| .a("[k = ").a(keyStr) |
| .a(", v = [").a(valueStr).a("]") |
| .a(", super = [").a(S.toString(DataEntry.class, source)).a("]]") |
| .toString(); |
| } |
| |
| /** |
| * Returns a string representation of the entry key or entry value. |
| * |
| * @param value unwrappedKey or unwrappedValue |
| * @param co key or value |
| * @return String presentation of the entry key or entry value depends on {@code isValue}. |
| */ |
| public String toString(Object value, CacheObject co) { |
| String str; |
| if (sensitiveData == HIDE) |
| return ""; |
| |
| if (sensitiveData == HASH) |
| if (value != null) |
| return Integer.toString(value.hashCode()); |
| else |
| return Integer.toString(co.hashCode()); |
| |
| if (value instanceof String) |
| str = (String)value; |
| else if (value instanceof BinaryObject) |
| str = value.toString(); |
| else if (value != null) |
| str = toStringRecursive(value.getClass(), value); |
| else if (co instanceof BinaryObject) |
| str = co.toString(); |
| else |
| str = null; |
| |
| if (str == null || str.isEmpty()) { |
| |
| try { |
| CacheObjectValueContext ctx = null; |
| try { |
| ctx = IgniteUtils.field(source, "cacheObjValCtx"); |
| } |
| catch (Exception e) { |
| throw new IgniteException(e); |
| } |
| str = Base64.getEncoder().encodeToString(co.valueBytes(ctx)); |
| } |
| catch (IgniteCheckedException e) { |
| throw new IgniteException(e); |
| } |
| } |
| |
| if (sensitiveData == MD5) |
| str = ProcessSensitiveDataUtils.md5(str); |
| |
| return str; |
| } |
| |
| /** |
| * Produces auto-generated output of string presentation for given object (given the whole hierarchy). |
| * |
| * @param cls Declaration class of the object. |
| * @param obj Object to get a string presentation for. |
| * @return String presentation of the given object. |
| */ |
| public static String toStringRecursive(Class cls, Object obj) { |
| String result = null; |
| |
| if (cls != Object.class) |
| result = S.toString(cls, obj, toStringRecursive(cls.getSuperclass(), obj)); |
| |
| return result; |
| } |
| } |