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

org.glassfish.appclient.server.core.jws.servedcontent.CachingDynamicContentImpl Maven / Gradle / Ivy

There is a newer version: 6.2024.6
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2014 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.
 *

*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. *

*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. *

*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 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); } @Override public boolean isMain() { return false; } 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; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy