blob: 69a4ea86083df21e6a150b026161189b07b1ce7b [file] [log] [blame]
/*
* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2002 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache Tapestry" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache Tapestry", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package net.sf.tapestry.spec;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.sf.tapestry.IResourceResolver;
import net.sf.tapestry.Tapestry;
import net.sf.tapestry.util.BasePropertyHolder;
/**
* Specification for a library. {@link net.sf.tapestry.spec.ApplicationSpecification}
* is a specialized kind of library.
*
* @author Howard Lewis Ship
* @version $Id$
* @since 2.2
*
**/
public class LibrarySpecification extends BasePropertyHolder implements ILibrarySpecification
{
/**
* Resource resolver (used to instantiate extensions).
*
**/
private IResourceResolver _resolver;
/**
* Map of page name to page specification path.
*
**/
private Map _pages;
/**
* Map of component alias to component specification path.
*
**/
private Map _components;
/**
* Map of service name to service class name.
*
**/
private Map _services;
/**
* Map of library id to library specification path.
*
**/
private Map _libraries;
private String _description;
/**
* Map of extension name to {@link ExtensionSpecification}.
*
**/
private Map _extensions;
/**
* Map of extension name to Object for instantiated extensions.
*
**/
private Map _instantiatedExtensions;
/**
* The XML Public Id used when the library specification was read
* (if applicable).
*
* @since 2.2
*
**/
private String _publicId;
public String getLibrarySpecificationPath(String id)
{
return (String) get(_libraries, id);
}
/**
* Sets the specification path for an embedded library.
*
* @throws IllegalArgumentException if a library with the given
* id already exists
*
**/
public void setLibrarySpecificationPath(String id, String path)
{
if (_libraries == null)
_libraries = new HashMap();
if (_libraries.containsKey(id))
throw new IllegalArgumentException(
Tapestry.getString("LibrarySpecification.duplicate-child-namespace-id", id));
_libraries.put(id, path);
}
public List getLibraryIds()
{
return sortedKeys(_libraries);
}
public String getPageSpecificationPath(String name)
{
return (String) get(_pages, name);
}
public void setPageSpecificationPath(String name, String path)
{
if (_pages == null)
_pages = new HashMap();
if (_pages.containsKey(name))
throw new IllegalArgumentException(Tapestry.getString("LibrarySpecification.duplicate-page-name", name));
_pages.put(name, path);
}
public List getPageNames()
{
return sortedKeys(_pages);
}
public void setComponentSpecificationPath(String alias, String path)
{
if (_components == null)
_components = new HashMap();
if (_components.containsKey(alias))
throw new IllegalArgumentException(
Tapestry.getString("LibrarySpecification.duplicate-component-alias", alias));
_components.put(alias, path);
}
public String getComponentSpecificationPath(String alias)
{
return (String) get(_components, alias);
}
public List getComponentAliases()
{
return sortedKeys(_components);
}
public String getServiceClassName(String name)
{
return (String) get(_services, name);
}
public List getServiceNames()
{
return sortedKeys(_services);
}
public void setServiceClassName(String name, String className)
{
if (_services == null)
_services = new HashMap();
if (_services.containsKey(name))
throw new IllegalArgumentException(Tapestry.getString("LibrarySpecification.duplicate-service-name", name));
_services.put(name, className);
}
private List sortedKeys(Map map)
{
if (map == null)
return Collections.EMPTY_LIST;
List result = new ArrayList(map.keySet());
Collections.sort(result);
return result;
}
private Object get(Map map, Object key)
{
if (map == null)
return null;
return map.get(key);
}
/**
*
* Returns the documentation for this library..
*
*
**/
public String getDescription()
{
return _description;
}
/**
*
* Sets the documentation for this library.
*
*
**/
public void setDescription(String description)
{
_description = description;
}
/**
* Returns a Map of extensions; key is extension name, value is
* {@link net.sf.tapestry.spec.ExtensionSpecification}.
* May return null. The returned Map is immutable.
*
**/
public Map getExtensionSpecifications()
{
if (_extensions == null)
return null;
return Collections.unmodifiableMap(_extensions);
}
/**
* Adds another extension specification.
*
* @throws IllegalArgumentException if an extension with the given name already exists.
*
**/
public void addExtensionSpecification(String name, ExtensionSpecification extension)
{
if (_extensions == null)
_extensions = new HashMap();
if (_extensions.containsKey(name))
throw new IllegalArgumentException(
Tapestry.getString("LibrarySpecification.duplicate-extension-name", this, name));
_extensions.put(name, extension);
}
/**
* Returns a sorted List of the names of all extensions. May return the empty list,
* but won't return null.
*
**/
public List getExtensionNames()
{
return sortedKeys(_instantiatedExtensions);
}
/**
* Returns the named ExtensionSpecification, or null if it doesn't exist.
*
**/
public ExtensionSpecification getExtensionSpecification(String name)
{
if (_extensions == null)
return null;
return (ExtensionSpecification) _extensions.get(name);
}
/**
* Returns true if this library specification has a specification
* for the named extension.
*
**/
public boolean checkExtension(String name)
{
if (_extensions == null)
return false;
return _extensions.containsKey(name);
}
/**
* Returns an instantiated extension. Extensions are created as needed and
* cached for later use.
*
* @throws IllegalArgumentException if no extension specification exists for the
* given name.
*
**/
public synchronized Object getExtension(String name)
{
if (_instantiatedExtensions == null)
_instantiatedExtensions = new HashMap();
Object result = _instantiatedExtensions.get(name);
if (result == null)
{
ExtensionSpecification spec = getExtensionSpecification(name);
if (spec == null)
throw new IllegalArgumentException(
Tapestry.getString("LibrarySpecification.no-such-extension", name));
result = spec.instantiateExtension(_resolver);
_instantiatedExtensions.put(name, result);
}
return result;
}
/**
* Invoked after the entire specification has been constructed
* to instantiate any extensions marked immediate.
*
**/
public synchronized void instantiateImmediateExtensions()
{
if (_extensions == null)
return;
Iterator i = _extensions.entrySet().iterator();
while (i.hasNext())
{
Map.Entry entry = (Map.Entry) i.next();
ExtensionSpecification spec = (ExtensionSpecification) entry.getValue();
if (!spec.isImmediate())
continue;
String name = (String) entry.getKey();
getExtension(name);
}
}
public IResourceResolver getResourceResolver()
{
return _resolver;
}
public void setResourceResolver(IResourceResolver resolver)
{
_resolver = resolver;
}
/**
* Returns the extensions map.
* @return Map of objects.
*
**/
protected Map getExtensions()
{
return _extensions;
}
/**
* Updates the extension map.
* @param extensions A Map of extension specification paths
* keyed on extension id.
*
* <p>The map is retained, not copied.
*
**/
protected void setExtensions(Map extension)
{
_extensions = extension;
}
/**
* Returns the libraries map.
* @return Map of {@link LibrarySpecification}.
*
**/
protected Map getLibraries()
{
return _libraries;
}
/**
* Updates the library map.
* @param libraries A Map of library specification paths
* keyed on library id.
*
* <p>The map is retained, not copied.
*
**/
protected void setLibraries(Map libraries)
{
_libraries = libraries;
}
/**
* Returns the pages map.
* @return Map of {@link ComponentSpecification}.
*
**/
protected Map getPages()
{
return _pages;
}
/**
* Updates the page map.
* @param pages A Map of page specification paths
* keyed on page id.
*
* <p>The map is retained, not copied.
*
**/
protected void setPages(Map pages)
{
_pages = pages;
}
/**
* Returns the services.
* @return Map of service class names.
*
**/
protected Map getServices()
{
return _services;
}
/**
* Updates the services map.
* @param services A Map of the fully qualified names of classes
* which implement
* {@link net.sf.tapestry.IEngineService}
* keyed on service id.
*
* <p>The map is retained, not copied.
*
**/
protected void setServices(Map services)
{
_services = services;
}
/**
* Returns the components map.
* @return Map of {@link ContainedComponent}.
*
**/
protected Map getComponents()
{
return _components;
}
/**
* Updates the components map.
* @param components A Map of {@link ContainedComponent} keyed on component id.
* The map is retained, not copied.
*
**/
protected void setComponents(Map components)
{
_components = components;
}
/**
* Returns the XML Public Id for the library file, or null
* if not applicable.
*
* <p>
* This method exists as a convienience for the Spindle plugin.
* A previous method used an arbitrary version string, the
* public id is more useful and less ambiguous.
*
*
**/
public String getPublicId()
{
return _publicId;
}
public void setPublicId(String publicId)
{
_publicId = publicId;
}
}