alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Glassfish example source code file (CachingDynamicContentImpl.java)

This example Glassfish source code file (CachingDynamicContentImpl.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Glassfish tags/keywords

cachingdynamiccontentimpl, cachingdynamiccontentimpl, default_max_instances, dynamiccontent, instance, instance, instanceadapter, linkedlist, mime, override, properties, properties, string, string, util

The Glassfish CachingDynamicContentImpl.java source code

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package org.glassfish.appclient.server.core.jws.servedcontent;

import java.util.LinkedList;
import java.util.Properties;
import org.glassfish.appclient.server.core.jws.Util;
import org.glassfish.appclient.server.core.jws.servedcontent.DynamicContent.InstanceAdapter;

/**
 *
 * @author tjquinn
 */
/**
 *Represents dynamic content in template form.
 *<p>
 *This class also keeps track of the most recent times the object's template
 *was used to generate content that was different from the result of the
 *previous generation using this template.  This
 *information is used in responding to HTTP HEAD requests.  Java Web Start uses
 *HEAD requests to find out if a document on the server is more recent than
 *the locally cached copy on the client.  If so, then Java Web Start will 
 *request the updated version with a routine GET request. 
 *<p>
 *To avoid incorrectly reporting obsolete cached documents as current, this
 *class keeps track of when the content generated by the template is different
 *from the previous generation.  
 *<p>
 *The generated content can depend on request-time information
 *(such as command line arguments passed in the query string of the HTTP request).
 *We save and track only a few individual response instances, because the assumption
 *is that requests that carry query strings (which are converted into command line
 *arguments passed to ACC and on through to the app client) are likely to change
 *frequently and not necessarily be reused often.  Keeping a few allows caching
 *the different content resulting from a small number of different argument
 *value settings, but avoids the problems of caching every single response
 *which could become a large memory drain if each request specified a 
 *different set of arguments (for instance, one of the arguments could be a
 *timestamp that would change every time).
 */
public class CachingDynamicContentImpl extends Content.Adapter implements DynamicContent {

    /** maximum number of instances of content to keep for each template */
    private static final int DEFAULT_MAX_INSTANCES = 4;
    
    /**
     *the template which will be used at runtime to create the actual response
     *to the HTTP request
     */
    private final String template;

    /** the MIME type of the data represented by this CachingDynamicContentImpl instance */
    protected final String mimeType;

    /** content instances resulting from previous HTTP GET requests */
    private final LinkedList<Instance> instances = new LinkedList();
    
    /** max. number of instances to cache */
    private final int maxInstances;

    /**
     * Returns a new instance of CachingDynamicContentImpl.
     * @param origin the ContentOrigin for the new content instance
     * @param contentKey the content key used to store and retrieve the content
     * @param path the path relative to the subcategory in which this document is addressable
     * @param mimeType the MIME type of data represented by the content generated by this
     * object.
     * @return new CachingDynamicContentImpl object
     */
    public CachingDynamicContentImpl(final String template, final String mimeType) {
        this(template, mimeType, DEFAULT_MAX_INSTANCES);
    }

    public CachingDynamicContentImpl(final String template, final String mimeType,
            final int maxInstances) {

        this.template = template;
        this.mimeType = mimeType;
        this.maxInstances = maxInstances;
    }

    /**
     * Returns the CachingDynamicContentImpl.InstanceImpl for this template corresponding to
     * the specified substitution token values.
     * @param tokenValues the name/value pairs to be substituted in the template
     * @param createIfAbsent selects whether a new CachingDynamicContentImpl.InstanceImpl should
     * be created for the resulting text if the content text resulting from the
     * substitution is not already cached by this CachingDynamicContentImpl.
     * @return the instance corresponding to the content generated by the tokenValues;
     * null if no such instance already exists for this CachingDynamicContentImpl and createIfAbsent
     * was false.
     */
    public Instance getExistingInstance(final Properties tokenValues) {
        return getOrCreateInstance(tokenValues, false);
    }

    public Instance getOrCreateInstance(final Properties tokenValues) {
        return getOrCreateInstance(tokenValues, true);
    }

    private Instance getOrCreateInstance(final Properties tokenValues, final boolean createIfAbsent) {
        /*
         * I generally avoid passing in flags to control the inner flow of a
         * method, but in this case we want the search and the optional addition
         * to take place atomically inside the synchronized block.  This way
         * the synchronized clause is in one place.
         */
        final String textWithPlaceholdersReplaced =
                Util.replaceTokens(template, tokenValues);

        /*
         * Look for an instance with its text matching the just-computed
         * replacement text.
         */
        Instance result = null;
        synchronized (instances) {
            for (Instance i : instances) {
                if (i.getText().equals(textWithPlaceholdersReplaced)) {
                    return i;
                }
            }
            
            if (createIfAbsent) {
                result = new InstanceAdapter(textWithPlaceholdersReplaced);
                addInstance(result);
            }
        }
        return result;
    }

    
    /**
     * Adds a new content instance to this dynamic content.  If adding the instance
     * makes the cache too long, discards the oldest instance.
     * @param newInstance the new instance to be added to the cache
     */
    private void addInstance(final Instance newInstance) {
        synchronized (instances) {
            instances.addFirst(newInstance);
            if (instances.size() > maxInstances) {
                instances.removeLast();
            }
        }
    }
    

    /**
     * Returns the MIME type associated with this content.
     * @return the MIME type for this content
     */
    public String getMimeType() {
        return mimeType;
    }

    /**
     * Clears the cached instances.
     */
    protected void clearInstances() {
        instances.clear();
    }
    
    /**
     * Returns a string representation of the CachingDynamicContentImpl.
     */
    @Override
    public String toString() {
        return super.toString() + ", template=" + template + ", MIME type=" + mimeType;// + ", most recent change in generated content=" + timestamp;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final CachingDynamicContentImpl other = (CachingDynamicContentImpl) obj;
        if ((this.template == null) ? (other.template != null) : !this.template.equals(other.template)) {
            return false;
        }
        if ((this.mimeType == null) ? (other.mimeType != null) : !this.mimeType.equals(other.mimeType)) {
            return false;
        }
        if (this.maxInstances != other.maxInstances) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 89 * hash + (this.template != null ? this.template.hashCode() : 0);
        hash = 89 * hash + (this.mimeType != null ? this.mimeType.hashCode() : 0);
        hash = 89 * hash + this.maxInstances;
        return hash;
    }

    
}

Other Glassfish examples (source code examples)

Here is a short list of links related to this Glassfish CachingDynamicContentImpl.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.