You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2007/01/27 04:13:32 UTC
svn commit: r500470 - in /tapestry/tapestry5/tapestry-core/trunk/src:
main/java/org/apache/tapestry/internal/services/
main/java/org/apache/tapestry/services/
test/java/org/apache/tapestry/internal/services/
Author: hlship
Date: Fri Jan 26 19:13:31 2007
New Revision: 500470
URL: http://svn.apache.org/viewvc?view=rev&rev=500470
Log:
Check in first stage of case insensitive URLs -- ComponentClassResolver now does a scan, using ComponentClassLocator, to locate all page, component and mixin classes.
Added:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassLocator.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassLocatorImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentClassLocatorImplTest.java
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassResolverImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentClassResolverImplTest.java
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassLocator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassLocator.java?view=auto&rev=500470
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassLocator.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassLocator.java Fri Jan 26 19:13:31 2007
@@ -0,0 +1,34 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// 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.apache.tapestry.internal.services;
+
+import java.util.Collection;
+
+/**
+ * Scans the classpath for component classes, classes within particular packages.
+ */
+public interface ComponentClassLocator
+{
+ /**
+ * Searches for all component classes under the given package name. This consists of all
+ * top-level classes in the indicated package (or a sub-package), but excludes inner classes.
+ * <p>
+ * TODO: Sniff files for the ComponentClass annotation? A pain because of inheritance and such.
+ *
+ * @param packageName
+ * @return fully qualified class names.
+ */
+ Collection<String> locateComponentClassNames(String packageName);
+}
Added: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassLocatorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassLocatorImpl.java?view=auto&rev=500470
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassLocatorImpl.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassLocatorImpl.java Fri Jan 26 19:13:31 2007
@@ -0,0 +1,194 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// 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.apache.tapestry.internal.services;
+
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newLinkedList;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.io.Reader;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.jar.JarEntry;
+
+import org.apache.tapestry.internal.TapestryUtils;
+import org.apache.tapestry.ioc.internal.util.CollectionFactory;
+
+public class ComponentClassLocatorImpl implements ComponentClassLocator
+{
+ private static final String CLASS_SUFFIX = ".class";
+
+ private final ClassLoader _contextClassLoader = Thread.currentThread().getContextClassLoader();
+
+ static class Queued
+ {
+ final URL _packageURL;
+
+ final String _packagePath;
+
+ public Queued(final URL packageURL, final String packagePath)
+ {
+ _packageURL = packageURL;
+ _packagePath = packagePath;
+ }
+ }
+
+ public Collection<String> locateComponentClassNames(String packageName)
+ {
+ String packagePath = packageName.replace('.', '/') + "/";
+
+ try
+ {
+ return findClassesWithinPath(packagePath);
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private Collection<String> findClassesWithinPath(String packagePath) throws IOException
+ {
+ Collection<String> result = CollectionFactory.newList();
+
+ Enumeration<URL> urls = _contextClassLoader.getResources(packagePath);
+
+ while (urls.hasMoreElements())
+ scanURL(packagePath, result, urls.nextElement());
+
+ return result;
+ }
+
+ private void scanURL(String packagePath, Collection<String> componentClassNames, URL url)
+ throws IOException
+ {
+ URLConnection connection = url.openConnection();
+
+ if (connection instanceof JarURLConnection)
+ {
+ scanJarConnection(packagePath, componentClassNames, (JarURLConnection) connection);
+ return;
+ }
+
+ // Otherwise, we're forced to assume that it is a file: URL for files in the user's
+ // workspace.
+
+ LinkedList<Queued> queue = newLinkedList();
+
+ queue.addFirst(new Queued(url, packagePath));
+
+ while (!queue.isEmpty())
+ {
+ Queued queued = queue.removeFirst();
+
+ scan(queued._packagePath, queued._packageURL, componentClassNames, queue);
+ }
+
+ }
+
+ private void scan(String packagePath, URL packageURL, Collection<String> componentClassNames,
+ LinkedList<Queued> queue) throws IOException
+ {
+ InputStream is = new BufferedInputStream(packageURL.openStream());
+ Reader reader = new InputStreamReader(is);
+ LineNumberReader lineReader = new LineNumberReader(reader);
+
+ String packageName = null;
+
+ try
+ {
+ while (true)
+ {
+ String line = lineReader.readLine();
+
+ if (line == null)
+ break;
+
+ if (line.contains("$"))
+ continue;
+
+ if (line.endsWith(CLASS_SUFFIX))
+ {
+ if (packageName == null)
+ packageName = packagePath.replace('/', '.');
+
+ // packagePath ends with '/', packageName ends with '.'
+
+ String fullClassName = packageName
+ + line.substring(0, line.length() - CLASS_SUFFIX.length());
+
+ componentClassNames.add(fullClassName);
+
+ continue;
+ }
+
+ // Either a file or a hidden directory (such as .svn)
+
+ if (line.contains("."))
+ continue;
+
+ // The name of a subdirectory.
+
+ URL newURL = new URL(packageURL.toExternalForm() + line + "/");
+ String newPackagePath = packagePath + line + "/";
+
+ queue.addFirst(new Queued(newURL, newPackagePath));
+ }
+
+ lineReader.close();
+ lineReader = null;
+ }
+ finally
+ {
+ TapestryUtils.close(lineReader);
+ }
+
+ }
+
+ private void scanJarConnection(String packagePath, Collection<String> componentClassNames,
+ JarURLConnection connection) throws IOException
+ {
+ Enumeration<JarEntry> e = connection.getJarFile().entries();
+
+ while (e.hasMoreElements())
+ {
+ String name = e.nextElement().getName();
+
+ if (!name.startsWith(packagePath))
+ continue;
+
+ if (!name.endsWith(CLASS_SUFFIX))
+ continue;
+
+ if (name.contains("$"))
+ continue;
+
+ // Strip off .class and convert the slashes back to periods.
+
+ String className = name.substring(0, name.length() - CLASS_SUFFIX.length()).replace(
+ "/",
+ ".");
+
+ componentClassNames.add(className);
+ }
+ }
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassResolverImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassResolverImpl.java?view=diff&rev=500470&r1=500469&r2=500470
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassResolverImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentClassResolverImpl.java Fri Jan 26 19:13:31 2007
@@ -12,313 +12,233 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.internal.services;
-
+package org.apache.tapestry.internal.services;
+
import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
-import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newThreadSafeMap;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.tapestry.events.InvalidationListener;
-import org.apache.tapestry.services.ComponentClassResolver;
-import org.apache.tapestry.services.LibraryMapping;
-
-/**
- *
- */
-public class ComponentClassResolverImpl implements ComponentClassResolver, InvalidationListener
-{
- private final ComponentInstantiatorSource _componentInstantiatorSource;
-
- private String _appRootPackage;
-
- private final Map<String, List<String>> _mappings = newMap();
-
- // Cache of logical page names to page class names
-
- private final Map<String, String> _pageClassCache = newThreadSafeMap();
-
- // Cache of component types to component class names
-
- private final Map<String, String> _componentClassCache = newThreadSafeMap();
-
- private final Map<String, String> _mixinClassCache = newThreadSafeMap();
-
- // Cache of page class names back to logical page names
-
- private final Map<String, String> _logicalPageNameCache = newThreadSafeMap();
-
- public ComponentClassResolverImpl(ComponentInstantiatorSource componentInstantiatorSource,
- Collection<LibraryMapping> mappings)
- {
- _componentInstantiatorSource = componentInstantiatorSource;
-
- for (LibraryMapping mapping : mappings)
- {
- String prefix = mapping.getPathPrefix();
-
- // TODO: Check that prefix is well formed (no leading or trailing slash)
-
- String rootPackage = mapping.getRootPackage();
-
- List<String> packages = _mappings.get(prefix);
-
- if (packages == null)
- {
- packages = newList();
- _mappings.put(prefix, packages);
- }
-
- packages.add(rootPackage);
-
- // These packages, which will contain classes subject to class transformation,
- // must be registered with the component instantiator (which is responsible
- // for transformation).
-
- addPackagesToInstantiatorSource(rootPackage);
- }
-
- }
-
- private void addPackagesToInstantiatorSource(String rootPackage)
- {
- _componentInstantiatorSource.addPackage(rootPackage + ".pages");
- _componentInstantiatorSource.addPackage(rootPackage + ".components");
- _componentInstantiatorSource.addPackage(rootPackage + ".mixins");
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tapestry.events.InvalidationListener;
+import org.apache.tapestry.services.ComponentClassResolver;
+import org.apache.tapestry.services.LibraryMapping;
+
+public class ComponentClassResolverImpl implements ComponentClassResolver, InvalidationListener
+{
+ private static final String MIXINS_SUBPACKAGE = "mixins";
+
+ private static final String COMPONENTS_SUBPACKAGE = "components";
+
+ private static final String PAGES_SUBPACKAGE = "pages";
+
+ private final ComponentInstantiatorSource _componentInstantiatorSource;
+
+ private final ComponentClassLocator _componentClassLocator;
+
+ private String _appRootPackage;
+
+ // Map from folder name to a list of root package names.
+ // The key does not begin or end with a slash.
+
+ private final Map<String, List<String>> _mappings = newMap();
+
+ // Flag indicating that the maps have been cleared following an invalidation
+ // and need to be rebuilt. The flag and the four maps below are not synchronized
+ // because they are only modified inside a synchronized block. That should be strong enough ...
+ // and changes made will become "visible" at the end of the synchronized block. Because of the
+ // structure of Tapestry, there should not be any reader threads while the write thread
+ // is operating.
+
+ private boolean _rebuild = true;
+
+ private final Map<String, String> _pageToClassName = newMap();
+
+ private final Map<String, String> _componentToClassName = newMap();
+
+ private final Map<String, String> _mixinToClassName = newMap();
+
+ private final Map<String, String> _pageClassNameToLogicalName = newMap();
+
+ public ComponentClassResolverImpl(ComponentInstantiatorSource componentInstantiatorSource,
+ ComponentClassLocator componentClassLocator, Collection<LibraryMapping> mappings)
+ {
+ _componentInstantiatorSource = componentInstantiatorSource;
+ _componentClassLocator = componentClassLocator;
+
+ for (LibraryMapping mapping : mappings)
+ {
+ String prefix = mapping.getPathPrefix();
+
+ // TODO: Check that prefix is well formed (no leading or trailing slash)
+
+ String rootPackage = mapping.getRootPackage();
+
+ List<String> packages = _mappings.get(prefix);
+
+ if (packages == null)
+ {
+ packages = newList();
+ _mappings.put(prefix, packages);
+ }
+
+ packages.add(rootPackage);
+
+ // These packages, which will contain classes subject to class transformation,
+ // must be registered with the component instantiator (which is responsible
+ // for transformation).
+
+ addPackagesToInstantiatorSource(rootPackage);
+ }
+
+ }
+
+ private void addPackagesToInstantiatorSource(String rootPackage)
+ {
+ _componentInstantiatorSource.addPackage(rootPackage + ".pages");
+ _componentInstantiatorSource.addPackage(rootPackage + ".components");
+ _componentInstantiatorSource.addPackage(rootPackage + ".mixins");
_componentInstantiatorSource.addPackage(rootPackage + ".base");
- }
-
- /** When the class loader is invalidated, clear any cached page names or component types. */
- public void objectWasInvalidated()
- {
- _pageClassCache.clear();
- _componentClassCache.clear();
- _mixinClassCache.clear();
-
- _logicalPageNameCache.clear();
-
- }
-
- public String resolvePageNameToClassName(String pageName)
- {
- String result = resolve(pageName, "pages", _pageClassCache);
-
- if (result == null)
- throw new IllegalArgumentException(ServicesMessages.couldNotResolvePageName(pageName));
-
- return result;
- }
-
- public String resolveComponentTypeToClassName(String componentType)
- {
- String result = resolve(componentType, "components", _componentClassCache);
-
- if (result == null)
- throw new IllegalArgumentException(ServicesMessages.couldNotResolveComponentType(componentType));
-
- return result;
- }
-
- public String resolveMixinTypeToClassName(String mixinType)
- {
- String result = resolve(mixinType, "mixins", _mixinClassCache);
-
- if (result == null)
- throw new IllegalArgumentException(ServicesMessages.couldNotResolveMixinType(mixinType));
-
- return result;
- }
-
- // Used a thread-safe (concurrent) map rather than making this method itself
- // concurrent to keep from single-threading the resolve process. If resolve() was
- // @Concurrent.Write, then it would only be possible to resolve a single class name
- // at a time, and there's no need for that.
-
- private String resolve(String name, String subpackage, Map<String, String> cache)
- {
- // ConcurrentHashMap can't store a null, so we sometimes re-resolve
- // a name, even though it can't be resolved. We could avoid this,
- // but since its a transient programmer error, that's pretty low
- // priority.
-
- String result = cache.get(name);
-
- if (result == null)
- {
- result = resolve(name, subpackage);
-
- // Again, ConcurrentHashMap can't store a null.
-
- if (result != null)
- cache.put(name, result);
- }
-
- return result;
- }
-
- private String resolve(String name, String subpackage)
- {
- int lastx = name.length();
-
- while (true)
- {
- int posx = name.lastIndexOf('/', lastx - 1);
-
- if (posx < 0)
- break;
-
- // Extract up to but not including the slash
-
- String prefix = name.substring(0, posx);
-
- List<String> packages = _mappings.get(prefix);
-
- if (packages != null)
- {
- String extension = name.substring(posx + 1).replace('/', '.');
-
- String result = search(packages, subpackage, extension);
-
- if (result != null)
- return result;
- }
-
- lastx = posx;
- }
-
- // Not found by prefix, lets try the application root package
-
- String extension = name.replace('/', '.');
-
- String result = buildClassName(_appRootPackage, subpackage, extension);
-
- if (_componentInstantiatorSource.exists(result))
- return result;
-
- // We always expect there to be a core package.
-
- return search(_mappings.get("core"), subpackage, extension);
- }
-
- /**
- * Searches a number of root packages for the given class.
- *
- * @param packages
- * the list of packages
- * @param subpackage
- * "page" or "component"
- * @param extension
- * the portion of the page name / component type after the library mapping prefix
- * @return the fully qualified class name, if it exists or null if it does not exist
- */
- private String search(List<String> packages, String subpackage, String extension)
- {
- for (String rootPackage : packages)
- {
- String result = buildClassName(rootPackage, subpackage, extension);
-
- if (_componentInstantiatorSource.exists(result))
- return result;
- }
-
- return null;
- }
-
- private String buildClassName(String rootPackage, String subpackage, String extension)
- {
- return rootPackage + "." + subpackage + "." + extension;
- }
-
- public String resolvePageClassNameToPageName(String pageClassName)
- {
- String result = _logicalPageNameCache.get(pageClassName);
-
- if (result == null)
- {
- result = findLogicalPageNameForClassName(pageClassName);
- _logicalPageNameCache.put(pageClassName, result);
- }
-
- return result;
- }
-
- private String findLogicalPageNameForClassName(String pageClassName)
- {
- String bestName = null;
-
- for (Map.Entry<String, List<String>> entry : _mappings.entrySet())
- {
- String prefix = entry.getKey();
-
- for (String packageName : entry.getValue())
- {
- String potential = convertToLogicalPageName(pageClassName, packageName, prefix);
-
- if (potential == null)
- continue;
-
- if (bestName == null)
- {
- bestName = potential;
- continue;
- }
-
- // Generally, for there to be more than one match, something borderline illegal
- // must be going on.
-
- if (potential.length() < bestName.length())
- bestName = potential;
- }
- }
-
- if (bestName == null)
- bestName = convertToLogicalPageName(pageClassName, _appRootPackage, null);
-
- if (bestName == null)
- throw new IllegalArgumentException(ServicesMessages.pageNameUnresolved(pageClassName));
-
- return bestName;
- }
-
- private String convertToLogicalPageName(String pageClassName, String packageName, String prefix)
- {
- if (!pageClassName.startsWith(packageName))
- return null;
-
- String afterPackage = pageClassName.substring(packageName.length() + 1);
- String[] names = afterPackage.split("\\.");
-
- // The package name is the *root* package; we ignore it, but build up the rest
- // of the logical page name from any intermediate folders/packages, leading
- // up to the actual class name. If packages are nested in an ambiguous way,
- // we may find something that looks like a mapping, but isn't.
-
- if (!names[0].equals("pages"))
- return null;
-
- StringBuilder builder = new StringBuilder();
-
- if (prefix != null)
- builder.append(prefix);
-
- for (int i = 1; i < names.length; i++)
- {
- if (builder.length() > 0)
- builder.append("/");
-
- builder.append(names[i]);
- }
-
- return builder.toString();
- }
-
- public void setApplicationPackage(String packageName)
- {
- _appRootPackage = packageName;
-
- addPackagesToInstantiatorSource(packageName);
- }
+ }
+
+ /** When the class loader is invalidated, clear any cached page names or component types. */
+ public synchronized void objectWasInvalidated()
+ {
+ _rebuild = true;
+
+ _pageToClassName.clear();
+ _componentToClassName.clear();
+ _mixinToClassName.clear();
+ _pageClassNameToLogicalName.clear();
+
+ }
+
+ private synchronized void rebuild()
+ {
+ if (!_rebuild)
+ return;
+
+ rebuild("", _appRootPackage);
+
+ for (String prefix : _mappings.keySet())
+ {
+ List<String> packages = _mappings.get(prefix);
+
+ String folder = prefix + "/";
+
+ for (String packageName : packages)
+ rebuild(folder, packageName);
+ }
+
+ _rebuild = false;
+ }
+
+ private void rebuild(String pathPrefix, String rootPackage)
+ {
+ fillCaselessMap(pathPrefix, rootPackage, PAGES_SUBPACKAGE, _pageToClassName);
+ fillCaselessMap(pathPrefix, rootPackage, COMPONENTS_SUBPACKAGE, _componentToClassName);
+ fillCaselessMap(pathPrefix, rootPackage, MIXINS_SUBPACKAGE, _mixinToClassName);
+ }
+
+ private void fillCaselessMap(String pathPrefix, String rootPackage, String subPackage,
+ Map<String, String> logicalNameToClassName)
+ {
+ String searchPackage = rootPackage + "." + subPackage;
+ boolean isPage = subPackage.equals(PAGES_SUBPACKAGE);
+
+ Collection<String> classNames = _componentClassLocator
+ .locateComponentClassNames(searchPackage);
+
+ int startPos = searchPackage.length() + 1;
+
+ for (String name : classNames)
+ {
+ String withinPackage = name.substring(startPos).replace('.', '/');
+
+ String logicalName = pathPrefix + withinPackage;
+
+ if (isPage)
+ _pageClassNameToLogicalName.put(name, logicalName);
+
+ logicalNameToClassName.put(logicalName.toLowerCase(), name);
+ }
+ }
+
+ public String resolvePageNameToClassName(String pageName)
+ {
+ String result = locate(pageName, _pageToClassName);
+
+ if (result == null)
+ throw new IllegalArgumentException(ServicesMessages.couldNotResolvePageName(pageName));
+
+ return result;
+ }
+
+ public String resolveComponentTypeToClassName(String componentType)
+ {
+ String result = locate(componentType, _componentToClassName);
+
+ if (result == null)
+ throw new IllegalArgumentException(ServicesMessages
+ .couldNotResolveComponentType(componentType));
+
+ return result;
+ }
+
+ public String resolveMixinTypeToClassName(String mixinType)
+ {
+ String result = locate(mixinType, _mixinToClassName);
+
+ if (result == null)
+ throw new IllegalArgumentException(ServicesMessages.couldNotResolveMixinType(mixinType));
+
+ return result;
+ }
+
+ /**
+ * Locates a class name within the provided map, given its logical name. If not found naturally,
+ * a search inside the "core" library is included.
+ *
+ * @param logicalName
+ * name to search for
+ * @param logicalNameToClassName
+ * mapping from logical name to class name
+ * @return the located class name or null
+ */
+ private String locate(String logicalName, Map<String, String> logicalNameToClassName)
+ {
+ rebuild();
+
+ String key = logicalName.toLowerCase();
+
+ String result = logicalNameToClassName.get(key);
+
+ // If not found, see if it exists under the core package. In this way,
+ // anything in core is "inherited" (but overridable) by the application.
+
+ if (result == null)
+ result = logicalNameToClassName.get("core/" + key);
+
+ return result;
+ }
+
+ public String resolvePageClassNameToPageName(String pageClassName)
+ {
+ rebuild();
+
+ String result = _pageClassNameToLogicalName.get(pageClassName);
+
+ if (result == null)
+ throw new IllegalArgumentException(ServicesMessages.pageNameUnresolved(pageClassName));
+
+ return result;
+ }
+
+ public void setApplicationPackage(String packageName)
+ {
+ _appRootPackage = packageName;
+
+ addPackagesToInstantiatorSource(packageName);
+ }
}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java?view=diff&rev=500470&r1=500469&r2=500470
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java Fri Jan 26 19:13:31 2007
@@ -60,6 +60,7 @@
import org.apache.tapestry.internal.services.BindingSourceImpl;
import org.apache.tapestry.internal.services.ClasspathAssetAliasManagerImpl;
import org.apache.tapestry.internal.services.CommonResourcesInjectionProvider;
+import org.apache.tapestry.internal.services.ComponentClassLocatorImpl;
import org.apache.tapestry.internal.services.ComponentClassResolverImpl;
import org.apache.tapestry.internal.services.ComponentEventDispatcher;
import org.apache.tapestry.internal.services.ComponentInstanceResultProcessor;
@@ -549,7 +550,7 @@
Collection<LibraryMapping> configuration)
{
ComponentClassResolverImpl service = new ComponentClassResolverImpl(
- _componentInstantiatorSource, configuration);
+ _componentInstantiatorSource, new ComponentClassLocatorImpl(), configuration);
// Allow the resolver to clean its cache when the source is invalidated
Added: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentClassLocatorImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentClassLocatorImplTest.java?view=auto&rev=500470
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentClassLocatorImplTest.java (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentClassLocatorImplTest.java Fri Jan 26 19:13:31 2007
@@ -0,0 +1,141 @@
+// Copyright 2007 The Apache Software Foundation
+//
+// 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.apache.tapestry.internal.services;
+
+import java.util.Collection;
+import java.util.Set;
+
+import org.apache.tapestry.ioc.internal.util.CollectionFactory;
+import org.apache.tapestry.ioc.internal.util.InternalUtils;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Tricky to test, since the code is literally hunting around inside its own brain. There's a lot of
+ * room for unintended consequences here.
+ */
+public class ComponentClassLocatorImplTest extends Assert
+{
+ /**
+ * Use various packages in tapestry-ioc to test this, as those don't change unexpectedly(-ish)
+ * and we know they are in a JAR on the classpath.
+ */
+ @Test
+ public void classes_in_jar_file()
+ {
+ ComponentClassLocator locator = new ComponentClassLocatorImpl();
+
+ Collection<String> names = locator
+ .locateComponentClassNames("org.apache.tapestry.ioc.internal.util");
+
+ assertInList(
+ names,
+ "org.apache.tapestry.ioc.internal.util",
+ "MessagesImpl",
+ "LocalizedNameGenerator",
+ "IdAllocator");
+ assertNotInList(
+ names,
+ "org.apache.tapestry.ioc.internal.util",
+ "Orderer$1",
+ "InheritanceSearch$State");
+ }
+
+ @Test
+ public void classes_in_subpackage_in_jar_file()
+ {
+ ComponentClassLocator locator = new ComponentClassLocatorImpl();
+
+ Collection<String> names = locator.locateComponentClassNames("org.apache.tapestry.ioc");
+
+ assertInList(
+ names,
+ "org.apache.tapestry.ioc",
+ "internal.Module",
+ "internal.util.MessagesImpl");
+
+ }
+
+ /**
+ * This time, we use a selection of classes from tapestry-core, since those will never be
+ * packaged inside a JAR at this time.
+ */
+
+ @Test
+ public void classes_in_local_folders()
+ {
+ ComponentClassLocator locator = new ComponentClassLocatorImpl();
+
+ Collection<String> names = locator
+ .locateComponentClassNames("org.apache.tapestry.corelib.components");
+
+ assertInList(names, "org.apache.tapestry.corelib.components", "ActionLink", "Label");
+
+ assertNotInList(names, "org.apache.tapestry.corelib", "Label$1", "Loop$1");
+ }
+
+ @Test
+ public void classes_in_subpackages_in_local_folders()
+ {
+ ComponentClassLocator locator = new ComponentClassLocatorImpl();
+
+ Collection<String> names = locator.locateComponentClassNames("org.apache.tapestry.corelib");
+
+ assertInList(
+ names,
+ "org.apache.tapestry.corelib",
+ "components.ActionLink",
+ "base.AbstractField",
+ "mixins.RenderInformals");
+
+ assertNotInList(names, "org.apache.tapestry.corelib", "components.Label$1");
+ }
+
+ void assertInList(Collection<String> names, String packageName, String... classNames)
+ {
+ Set<String> classNameSet = CollectionFactory.newSet(names);
+
+ for (String className : classNames)
+ {
+ String fullName = packageName + "." + className;
+
+ if (classNameSet.contains(fullName))
+ continue;
+
+ String message = String.format("%s not found in %s.", fullName, InternalUtils
+ .joinSorted(names));
+
+ throw new AssertionError(message);
+ }
+ }
+
+ void assertNotInList(Collection<String> names, String packageName, String... classNames)
+ {
+ Set<String> classNameSet = CollectionFactory.newSet(names);
+
+ for (String className : classNames)
+ {
+ String fullName = packageName + "." + className;
+
+ if (!classNameSet.contains(fullName))
+ continue;
+
+ String message = String.format("%s found in %s.", fullName, InternalUtils
+ .joinSorted(names));
+
+ throw new AssertionError(message);
+ }
+ }
+}
Modified: tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentClassResolverImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentClassResolverImplTest.java?view=diff&rev=500470&r1=500469&r2=500470
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentClassResolverImplTest.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentClassResolverImplTest.java Fri Jan 26 19:13:31 2007
@@ -14,7 +14,11 @@
package org.apache.tapestry.internal.services;
+import static org.easymock.EasyMock.isA;
+
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import org.apache.tapestry.internal.test.InternalBaseTestCase;
@@ -35,11 +39,11 @@
private static final String LIB_ROOT_PACKAGE = "org.example.lib";
private ComponentClassResolverImpl create(ComponentInstantiatorSource source,
- LibraryMapping... mappings)
+ ComponentClassLocator locator, LibraryMapping... mappings)
{
List<LibraryMapping> list = Arrays.asList(mappings);
- ComponentClassResolverImpl resolver = new ComponentClassResolverImpl(source, list);
+ ComponentClassResolverImpl resolver = new ComponentClassResolverImpl(source, locator, list);
resolver.setApplicationPackage(APP_ROOT_PACKAGE);
@@ -50,53 +54,83 @@
public void simple_page_name()
{
ComponentInstantiatorSource source = newComponentInstantiatorSource();
+ ComponentClassLocator locator = newComponentClassLocator();
train_for_app_packages(source);
- train_exists(source, APP_ROOT_PACKAGE + ".pages.SimplePage", true);
+ String className = APP_ROOT_PACKAGE + ".pages.SimplePage";
+
+ train_locateComponentClassNames(locator, APP_ROOT_PACKAGE + ".pages", className);
replay();
- ComponentClassResolver resolver = create(source);
+ ComponentClassResolver resolver = create(source, locator);
- assertEquals(resolver.resolvePageNameToClassName("SimplePage"), APP_ROOT_PACKAGE
- + ".pages.SimplePage");
+ assertEquals(resolver.resolvePageNameToClassName("SimplePage"), className);
verify();
}
+ protected final ComponentClassLocator newComponentClassLocator()
+ {
+ ComponentClassLocator locator = newMock(ComponentClassLocator.class);
+
+ stub_locateComponentClassNames(locator);
+
+ return locator;
+ }
+
+ private void stub_locateComponentClassNames(ComponentClassLocator locator)
+ {
+ Collection<String> noMatches = Collections.emptyList();
+
+ expect(locator.locateComponentClassNames(isA(String.class))).andStubReturn(noMatches);
+ }
+
+ protected final void train_locateComponentClassNames(ComponentClassLocator locator,
+ String packageName, String... classNames)
+ {
+ expect(locator.locateComponentClassNames(packageName)).andReturn(Arrays.asList(classNames));
+ }
+
@Test
public void class_name_to_simple_page_name()
{
+ String className = APP_ROOT_PACKAGE + ".pages.SimplePage";
+
ComponentInstantiatorSource source = newComponentInstantiatorSource();
+ ComponentClassLocator locator = newComponentClassLocator();
train_for_app_packages(source);
+ train_locateComponentClassNames(locator, APP_ROOT_PACKAGE + ".pages", className);
+
replay();
- ComponentClassResolver resolver = create(source);
+ ComponentClassResolver resolver = create(source, locator);
- assertEquals(
- resolver.resolvePageClassNameToPageName(APP_ROOT_PACKAGE + ".pages.SimplePage"),
- "SimplePage");
+ assertEquals(resolver.resolvePageClassNameToPageName(className), "SimplePage");
verify();
}
+ /** All of the caches are handled identically, so we just test the pages for caching. */
@Test
public void resolved_page_names_are_cached()
{
+
+ String pageClassName = APP_ROOT_PACKAGE + ".pages.SimplePage";
+
ComponentInstantiatorSource source = newComponentInstantiatorSource();
+ ComponentClassLocator locator = newComponentClassLocator();
train_for_app_packages(source);
- String pageClassName = APP_ROOT_PACKAGE + ".pages.SimplePage";
-
- train_exists(source, pageClassName, true);
+ train_locateComponentClassNames(locator, APP_ROOT_PACKAGE + ".pages", pageClassName);
replay();
- ComponentClassResolverImpl resolver = create(source);
+ ComponentClassResolverImpl resolver = create(source, locator);
assertEquals(resolver.resolvePageNameToClassName("SimplePage"), pageClassName);
@@ -112,7 +146,8 @@
// After clearing the cache, redoes the work.
- train_exists(source, pageClassName, true);
+ train_locateComponentClassNames(locator, APP_ROOT_PACKAGE + ".pages", pageClassName);
+ stub_locateComponentClassNames(locator);
replay();
@@ -126,21 +161,22 @@
@Test
public void page_found_in_core_lib()
{
+ String className = CORE_ROOT_PACKAGE + ".pages.CorePage";
+
ComponentInstantiatorSource source = newComponentInstantiatorSource();
+ ComponentClassLocator locator = newComponentClassLocator();
train_for_packages(source, CORE_ROOT_PACKAGE);
train_for_app_packages(source);
- train_exists(source, APP_ROOT_PACKAGE + ".pages.CorePage", false);
- train_exists(source, CORE_ROOT_PACKAGE + ".pages.CorePage", true);
+ train_locateComponentClassNames(locator, CORE_ROOT_PACKAGE + ".pages", className);
replay();
- ComponentClassResolver resolver = create(source, new LibraryMapping(CORE_PREFIX,
+ ComponentClassResolver resolver = create(source, locator, new LibraryMapping(CORE_PREFIX,
CORE_ROOT_PACKAGE));
- assertEquals(resolver.resolvePageNameToClassName("CorePage"), CORE_ROOT_PACKAGE
- + ".pages.CorePage");
+ assertEquals(resolver.resolvePageNameToClassName("CorePage"), className);
verify();
}
@@ -148,45 +184,22 @@
@Test
public void page_class_name_resolved_to_core_page()
{
- ComponentInstantiatorSource source = newComponentInstantiatorSource();
-
- train_for_packages(source, CORE_ROOT_PACKAGE);
- train_for_app_packages(source);
-
- replay();
-
- ComponentClassResolver resolver = create(source, new LibraryMapping(CORE_PREFIX,
- CORE_ROOT_PACKAGE));
-
- assertEquals(
- resolver.resolvePageClassNameToPageName(CORE_ROOT_PACKAGE + ".pages.CorePage"),
- "core/CorePage");
-
- verify();
- }
+ String className = CORE_ROOT_PACKAGE + ".pages.CorePage";
- @Test
- public void resolved_logical_page_names_are_cached()
- {
ComponentInstantiatorSource source = newComponentInstantiatorSource();
+ ComponentClassLocator locator = newComponentClassLocator();
train_for_packages(source, CORE_ROOT_PACKAGE);
train_for_app_packages(source);
+ train_locateComponentClassNames(locator, CORE_ROOT_PACKAGE + ".pages", className);
+
replay();
- ComponentClassResolver resolver = create(source, new LibraryMapping(CORE_PREFIX,
+ ComponentClassResolver resolver = create(source, locator, new LibraryMapping(CORE_PREFIX,
CORE_ROOT_PACKAGE));
- String className = CORE_ROOT_PACKAGE + ".pages.CorePage";
-
- String logicalName1 = resolver.resolvePageClassNameToPageName(className);
- String logicalName2 = resolver.resolvePageClassNameToPageName(className);
-
- // Given that the value is computed on the fly, if its the same (not just equal, but the
- // same), that proves that the value was cached.
-
- assertSame(logicalName2, logicalName1);
+ assertEquals(resolver.resolvePageClassNameToPageName(className), "core/CorePage");
verify();
}
@@ -194,41 +207,48 @@
@Test
public void page_found_in_library()
{
+ String className = LIB_ROOT_PACKAGE + ".pages.LibPage";
+
ComponentInstantiatorSource source = newComponentInstantiatorSource();
+ ComponentClassLocator locator = newComponentClassLocator();
train_for_packages(source, LIB_ROOT_PACKAGE);
train_for_packages(source, CORE_ROOT_PACKAGE);
train_for_app_packages(source);
- train_exists(source, LIB_ROOT_PACKAGE + ".pages.LibPage", true);
+ train_locateComponentClassNames(locator, LIB_ROOT_PACKAGE + ".pages", className);
replay();
- ComponentClassResolver resolver = create(source, new LibraryMapping(LIB_PREFIX,
+ ComponentClassResolver resolver = create(source, locator, new LibraryMapping(LIB_PREFIX,
LIB_ROOT_PACKAGE), new LibraryMapping(CORE_PREFIX, CORE_ROOT_PACKAGE));
- assertEquals(resolver.resolvePageNameToClassName("lib/LibPage"), LIB_ROOT_PACKAGE
- + ".pages.LibPage");
+ assertEquals(resolver.resolvePageNameToClassName("lib/LibPage"), className);
verify();
}
@Test
- public void class_name_resolves_to_folder_under_library()
+ public void lookup_by_logical_name_is_case_insensitive()
{
+ String className = LIB_ROOT_PACKAGE + ".pages.LibPage";
+
ComponentInstantiatorSource source = newComponentInstantiatorSource();
+ ComponentClassLocator locator = newComponentClassLocator();
train_for_packages(source, LIB_ROOT_PACKAGE);
train_for_packages(source, CORE_ROOT_PACKAGE);
train_for_app_packages(source);
+ train_locateComponentClassNames(locator, LIB_ROOT_PACKAGE + ".pages", className);
+
replay();
- ComponentClassResolver resolver = create(source, new LibraryMapping(LIB_PREFIX,
+ ComponentClassResolver resolver = create(source, locator, new LibraryMapping(LIB_PREFIX,
LIB_ROOT_PACKAGE), new LibraryMapping(CORE_PREFIX, CORE_ROOT_PACKAGE));
- assertEquals(resolver.resolvePageClassNameToPageName(LIB_ROOT_PACKAGE
- + ".pages.foo.bar.LibPage"), LIB_PREFIX + "/foo/bar/LibPage");
+ assertEquals(resolver.resolvePageNameToClassName("lib/libpage"), className);
+ assertEquals(resolver.resolvePageNameToClassName("LIB/LIBPAGE"), className);
verify();
}
@@ -237,13 +257,14 @@
public void class_name_does_not_resolve_to_page_name()
{
ComponentInstantiatorSource source = newComponentInstantiatorSource();
+ ComponentClassLocator locator = newComponentClassLocator();
train_for_packages(source, CORE_ROOT_PACKAGE);
train_for_app_packages(source);
replay();
- ComponentClassResolver resolver = create(source, new LibraryMapping(CORE_PREFIX,
+ ComponentClassResolver resolver = create(source, locator, new LibraryMapping(CORE_PREFIX,
CORE_ROOT_PACKAGE));
String className = LIB_ROOT_PACKAGE + ".pages.LibPage";
@@ -266,13 +287,14 @@
public void class_name_not_in_a_pages_package()
{
ComponentInstantiatorSource source = newComponentInstantiatorSource();
+ ComponentClassLocator locator = newComponentClassLocator();
train_for_packages(source, CORE_ROOT_PACKAGE);
train_for_app_packages(source);
replay();
- ComponentClassResolver resolver = create(source, new LibraryMapping(CORE_PREFIX,
+ ComponentClassResolver resolver = create(source, locator, new LibraryMapping(CORE_PREFIX,
CORE_ROOT_PACKAGE));
String className = CORE_ROOT_PACKAGE + ".foo.CorePage";
@@ -295,27 +317,28 @@
public void multiple_mappings_for_same_prefix()
{
String secondaryLibPackage = "org.examples.addon.lib";
+ String className = secondaryLibPackage + ".pages.LibPage";
ComponentInstantiatorSource source = newComponentInstantiatorSource();
+ ComponentClassLocator locator = newComponentClassLocator();
train_for_packages(source, LIB_ROOT_PACKAGE);
train_for_packages(source, secondaryLibPackage);
train_for_packages(source, CORE_ROOT_PACKAGE);
train_for_app_packages(source);
- train_exists(source, LIB_ROOT_PACKAGE + ".pages.LibPage", false);
- train_exists(source, secondaryLibPackage + ".pages.LibPage", true);
+ train_locateComponentClassNames(locator, secondaryLibPackage + ".pages", className);
replay();
ComponentClassResolver resolver = create(
source,
+ locator,
new LibraryMapping(LIB_PREFIX, LIB_ROOT_PACKAGE),
new LibraryMapping(LIB_PREFIX, secondaryLibPackage),
new LibraryMapping(CORE_PREFIX, CORE_ROOT_PACKAGE));
- assertEquals(resolver.resolvePageNameToClassName("lib/LibPage"), secondaryLibPackage
- + ".pages.LibPage");
+ assertEquals(resolver.resolvePageNameToClassName("lib/LibPage"), className);
verify();
}
@@ -326,27 +349,20 @@
String deepPackage = "org.deep";
ComponentInstantiatorSource source = newComponentInstantiatorSource();
+ ComponentClassLocator locator = newComponentClassLocator();
train_for_packages(source, deepPackage);
train_for_packages(source, LIB_ROOT_PACKAGE);
train_for_packages(source, CORE_ROOT_PACKAGE);
train_for_app_packages(source);
- // In early searches, the prefix is "absorbed" into the root package.
- // In later searches, the prefix is used as a sub-package.
-
- train_exists(source, deepPackage + ".pages.DeepPage", false);
- train_exists(source, LIB_ROOT_PACKAGE + ".pages.deep.DeepPage", false);
- train_exists(source, APP_ROOT_PACKAGE + ".pages.lib.deep.DeepPage", false);
- train_exists(source, CORE_ROOT_PACKAGE + ".pages.lib.deep.DeepPage", false);
+ // Is this test even needed any more with the new algorithm?
replay();
- ComponentClassResolver resolver = create(
- source,
- new LibraryMapping("lib/deep", deepPackage),
- new LibraryMapping(LIB_PREFIX, LIB_ROOT_PACKAGE),
- new LibraryMapping(CORE_PREFIX, CORE_ROOT_PACKAGE));
+ ComponentClassResolver resolver = create(source, locator, new LibraryMapping("lib/deep",
+ deepPackage), new LibraryMapping(LIB_PREFIX, LIB_ROOT_PACKAGE), new LibraryMapping(
+ CORE_PREFIX, CORE_ROOT_PACKAGE));
try
{
@@ -363,39 +379,6 @@
verify();
}
- @Test
- public void prefix_page_totally_missing()
- {
- ComponentInstantiatorSource source = newComponentInstantiatorSource();
-
- train_for_packages(source, LIB_ROOT_PACKAGE);
- train_for_packages(source, CORE_ROOT_PACKAGE);
- train_for_app_packages(source);
-
- train_exists(source, LIB_ROOT_PACKAGE + ".pages.MissingPage", false);
- train_exists(source, APP_ROOT_PACKAGE + ".pages.lib.MissingPage", false);
- train_exists(source, CORE_ROOT_PACKAGE + ".pages.lib.MissingPage", false);
-
- replay();
-
- ComponentClassResolver resolver = create(source, new LibraryMapping(LIB_PREFIX,
- LIB_ROOT_PACKAGE), new LibraryMapping(CORE_PREFIX, CORE_ROOT_PACKAGE));
-
- try
- {
- resolver.resolvePageNameToClassName("lib/MissingPage");
- unreachable();
- }
- catch (IllegalArgumentException ex)
- {
- assertEquals(
- ex.getMessage(),
- "Unable to resolve page 'lib/MissingPage' to a component class name.");
- }
-
- verify();
- }
-
private void train_for_packages(ComponentInstantiatorSource source, String packageName)
{
source.addPackage(packageName + ".pages");
@@ -411,20 +394,20 @@
@Test
public void simple_component_type()
{
- String expectedClassName = APP_ROOT_PACKAGE + ".components.SimpleComponent";
+ String className = APP_ROOT_PACKAGE + ".components.SimpleComponent";
ComponentInstantiatorSource source = newComponentInstantiatorSource();
+ ComponentClassLocator locator = newComponentClassLocator();
train_for_app_packages(source);
- train_exists(source, expectedClassName, true);
+ train_locateComponentClassNames(locator, APP_ROOT_PACKAGE + ".components", className);
replay();
- ComponentClassResolver resolver = create(source);
+ ComponentClassResolver resolver = create(source, locator);
- assertEquals(resolver.resolveComponentTypeToClassName("SimpleComponent"), APP_ROOT_PACKAGE
- + ".components.SimpleComponent");
+ assertEquals(resolver.resolveComponentTypeToClassName("SimpleComponent"), className);
verify();
}
@@ -439,14 +422,15 @@
String expectedClassName = APP_ROOT_PACKAGE + ".mixins.SimpleMixin";
ComponentInstantiatorSource source = newComponentInstantiatorSource();
+ ComponentClassLocator locator = newComponentClassLocator();
train_for_app_packages(source);
- train_exists(source, expectedClassName, true);
+ train_locateComponentClassNames(locator, APP_ROOT_PACKAGE + ".mixins", expectedClassName);
replay();
- ComponentClassResolver resolver = create(source);
+ ComponentClassResolver resolver = create(source, locator);
assertEquals(resolver.resolveMixinTypeToClassName("SimpleMixin"), expectedClassName);
@@ -457,16 +441,14 @@
public void mixin_type_not_found()
{
ComponentInstantiatorSource source = newComponentInstantiatorSource();
+ ComponentClassLocator locator = newComponentClassLocator();
train_for_packages(source, CORE_ROOT_PACKAGE);
train_for_app_packages(source);
- train_exists(source, APP_ROOT_PACKAGE + ".mixins.SimpleMixin", false);
- train_exists(source, CORE_ROOT_PACKAGE + ".mixins.SimpleMixin", false);
-
replay();
- ComponentClassResolver resolver = create(source, new LibraryMapping(CORE_PREFIX,
+ ComponentClassResolver resolver = create(source, locator, new LibraryMapping(CORE_PREFIX,
CORE_ROOT_PACKAGE));
try
@@ -489,16 +471,14 @@
public void component_type_not_found()
{
ComponentInstantiatorSource source = newComponentInstantiatorSource();
+ ComponentClassLocator locator = newComponentClassLocator();
train_for_packages(source, CORE_ROOT_PACKAGE);
train_for_app_packages(source);
- train_exists(source, APP_ROOT_PACKAGE + ".components.SimpleComponent", false);
- train_exists(source, CORE_ROOT_PACKAGE + ".components.SimpleComponent", false);
-
replay();
- ComponentClassResolver resolver = create(source, new LibraryMapping(CORE_PREFIX,
+ ComponentClassResolver resolver = create(source, locator, new LibraryMapping(CORE_PREFIX,
CORE_ROOT_PACKAGE));
try
@@ -515,59 +495,6 @@
verify();
- }
-
- @Test
- public void component_types_are_cached()
- {
- ComponentInstantiatorSource source = newComponentInstantiatorSource();
-
- train_for_app_packages(source);
-
- String componentClassName = APP_ROOT_PACKAGE + ".components.SimpleComponent";
-
- train_exists(source, componentClassName, true);
-
- replay();
-
- ComponentClassResolverImpl resolver = create(source);
-
- assertEquals(
- resolver.resolveComponentTypeToClassName("SimpleComponent"),
- componentClassName);
-
- verify();
-
- // No training, its in the cache
-
- replay();
-
- assertEquals(
- resolver.resolveComponentTypeToClassName("SimpleComponent"),
- componentClassName);
-
- verify();
-
- // The cache is cleared, so the search will re-execute
-
- train_exists(source, componentClassName, true);
-
- replay();
-
- resolver.objectWasInvalidated();
-
- assertEquals(
- resolver.resolveComponentTypeToClassName("SimpleComponent"),
- componentClassName);
-
- verify();
-
- }
-
- protected final void train_exists(ComponentInstantiatorSource source, String className,
- boolean exists)
- {
- expect(source.exists(className)).andReturn(exists);
}
private void train_for_app_packages(ComponentInstantiatorSource source)