/* * Copyright 2004-2006 Stefan Reuter * * 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 org.asteriskjava.fastagi; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; /** * A MappingStrategy that is configured via a resource bundle.<p> * The resource bundle contains the script part of the url as key and the fully * qualified class name of the corresponding AgiScript as value.<p> * Example: * * <pre> * leastcostdial.agi = com.example.fastagi.LeastCostDialAgiScript * hello.agi = com.example.fastagi.HelloAgiScript * </pre> * * LeastCostDialAgiScript and HelloAgiScript must both implement the AgiScript * interface and have a default constructor with no parameters.<p> * The resource bundle (properties) file is called * <code>fastagi-mapping.properties</code> by default and must be available on * the classpath. * * @author srt * @version $Id: ResourceBundleMappingStrategy.java 938 2007-12-31 03:23:38Z srt $ */ public class ResourceBundleMappingStrategy extends AbstractMappingStrategy { private static final String DEFAULT_RESOURCE_BUNDLE_NAME = "fastagi-mapping"; private String resourceBundleName; private Map<String, String> mappings; private Map<String, AgiScript> instances; private boolean shareInstances; /** * Creates a new ResourceBundleMappingStrategy using shared instances.. */ public ResourceBundleMappingStrategy() { this(DEFAULT_RESOURCE_BUNDLE_NAME); } /** * Creates a new ResourceBundleMappingStrategy with the given basename * of the resource bundle to use. * * @param resourceBundleName basename of the resource bundle to use */ public ResourceBundleMappingStrategy(String resourceBundleName) { this(resourceBundleName, true); } /** * Creates a new ResourceBundleMappingStrategy indicating whether to use shared * instances or not. * * @param shareInstances <code>true</code> to use shared instances, * <code>false</code> to create a new instance for * each request. * @since 0.3 */ public ResourceBundleMappingStrategy(boolean shareInstances) { this(DEFAULT_RESOURCE_BUNDLE_NAME, shareInstances); } /** * Creates a new ResourceBundleMappingStrategy with the given basename * of the resource bundle to use and indicating whether to use shared * instances or not. * * @param resourceBundleName basename of the resource bundle to use * @param shareInstances <code>true</code> to use shared instances, * <code>false</code> to create a new instance for * each request. * @since 0.3 */ public ResourceBundleMappingStrategy(String resourceBundleName, boolean shareInstances) { super(); this.resourceBundleName = resourceBundleName; this.shareInstances = shareInstances; } /** * Sets the basename of the resource bundle to use.<p> * Default is "fastagi-mapping". * * @param resourceBundleName basename of the resource bundle to use */ public void setResourceBundleName(String resourceBundleName) { this.resourceBundleName = resourceBundleName; synchronized (this) { this.mappings = null; this.instances = null; } } /** * Sets whether to use shared instances or not. If set to <code>true</code> * all AgiRequests are served by the same instance of an * AgiScript, if set to <code>false</code> a new instance is created for * each request.<p> * Default is <code>true</code>. * * @param shareInstances <code>true</code> to use shared instances, * <code>false</code> to create a new instance for * each request. * @since 0.3 */ public void setShareInstances(boolean shareInstances) { this.shareInstances = shareInstances; } private synchronized void loadResourceBundle() { ResourceBundle resourceBundle; Enumeration keys; mappings = new HashMap<String, String>(); if (shareInstances) { instances = new HashMap<String, AgiScript>(); } try { resourceBundle = ResourceBundle.getBundle(resourceBundleName); } catch (MissingResourceException e) { logger.info("Resource bundle '" + resourceBundleName + "' not found."); return; } keys = resourceBundle.getKeys(); while (keys.hasMoreElements()) { String scriptName; String className; AgiScript agiScript; scriptName = (String) keys.nextElement(); className = resourceBundle.getString(scriptName); mappings.put(scriptName, className); if (shareInstances) { agiScript = createAgiScriptInstance(className); if (agiScript == null) { continue; } instances.put(scriptName, agiScript); } logger.info("Added mapping for '" + scriptName + "' to class " + className); } } public AgiScript determineScript(AgiRequest request) { synchronized (this) { if (mappings == null || (shareInstances && instances == null)) { loadResourceBundle(); } } if (shareInstances) { return instances.get(request.getScript()); } else { return createAgiScriptInstance(mappings.get(request.getScript())); } } }