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

patterntesting.runtime.log.LazyObjectRecorder Maven / Gradle / Ivy

Go to download

PatternTesting Runtime (patterntesting-rt) is the runtime component for the PatternTesting framework. It provides the annotations and base classes for the PatternTesting testing framework (e.g. patterntesting-check, patterntesting-concurrent or patterntesting-exception) but can be also used standalone for classpath monitoring or profiling. It uses AOP and AspectJ to perform this feat.

There is a newer version: 2.4.0
Show newest version
/*
 * Copyright (c) 2013 by Oli B.
 *
 * 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 orimplied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * (c)reated 01.09.2013 by Oli B. ([email protected])
 */

package patterntesting.runtime.log;

import java.io.*;
import java.util.*;

import org.apache.commons.lang.ObjectUtils;
import org.aspectj.lang.JoinPoint;
import org.slf4j.*;

import patterntesting.annotation.check.runtime.NullArgsAllowed;
import patterntesting.runtime.util.*;

/**
 * In contradiction to {@link ObjectRecorder} this class only records joinpoints
 * and return values if they are different from the last record. I.e. If a
 * return value is always the same for the same joinpoint this pair is only
 * recorded once.
 *
 * @author oliver ([email protected])
 * @since 1.3.1 (01.09.2013)
 */
public class LazyObjectRecorder extends ObjectRecorder {

    private static final Logger log = LoggerFactory.getLogger(LazyObjectRecorder.class);
    private final Map cachedJoinpoints = new HashMap();

    /**
     * Instantiates a new lazy object recorder.
     */
    public LazyObjectRecorder() {
        super();
    }

    /**
     * Instantiates a new lazy object recorder.
     *
     * @param logFile the log file
     */
    public LazyObjectRecorder(final File logFile) {
        super(logFile);
    }

    /**
     * Instantiates a new lazy object recorder.
     *
     * @param ostream the ostream
     */
    public LazyObjectRecorder(OutputStream ostream) {
        super(ostream);
    }

    /**
     * Both things are logged with this method: the call of a method (joinPoint)
     * and the return value of this method. Constructors or method of type
     * 'void' are not recorded because the have no return value.
     * 

* Because the given joinPoint cannot be used as key for a map in * * @param joinPoint the joinpoint * @param returnValue the return value * {@link ObjectPlayer} it is saved as string. As a side effect this will * speedup the serialization stuff and shorten the generated record file. *

*

* The given return value will be only stored if it is not the same as the * last time. *

*/ @Override @NullArgsAllowed public void log(final JoinPoint joinPoint, final Object returnValue) { String statement = JoinPointHelper.getAsLongString(joinPoint); if ((returnValue != null) && (SignatureHelper.hasReturnType(joinPoint.getSignature()))) { try { saveLazy(statement, returnValue); } catch (IOException ioe) { log.debug("Logging failed because of {}.", ioe.getMessage()); log.info("{} = {}", statement, returnValue); } } else { log.trace("Not recorded: {}", statement); } } private void saveLazy(final String statement, final Object returnValue) throws IOException { ValueContainer saved = this.cachedJoinpoints.get(statement); if (saved == null) { this.cachedJoinpoints.put(statement, new ValueContainer(returnValue)); save(statement, returnValue); } else { if (ObjectUtils.equals(saved.value, returnValue)) { log.trace("cached: {} = {}", statement, returnValue); saved.count++; } else { saveCache(statement, saved); saved.setValue(returnValue); save(statement, returnValue); } } } private void saveCache(final String statement, ValueContainer saved) throws IOException { log.trace("saving: {} = {}", statement, saved); for (int i = 0; i < saved.count; i++) { save(statement, saved.value); } } // ------------------------------------------------------------------------ /** * This container acts as a kind of cache. The count attribute is used to * store the number of (unsaved) values. */ private static class ValueContainer { protected Object value; protected int count; protected ValueContainer(final Object value) { this.value = value; } protected void setValue(final Object newValue) { this.value = newValue; this.count = 0; } @Override public String toString() { return value + " (" + count + " x cached)"; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy