You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2007/04/17 02:27:33 UTC
svn commit: r529455 -
/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ClassNameLocatorImpl.java
Author: hlship
Date: Mon Apr 16 17:27:32 2007
New Revision: 529455
URL: http://svn.apache.org/viewvc?view=rev&rev=529455
Log:
TAPESTRY-1333: Cannot bundle component classes & templates in WEB-INF/classes when deploying to Tomcat (& JBoss)
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ClassNameLocatorImpl.java
Modified: tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ClassNameLocatorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ClassNameLocatorImpl.java?view=diff&rev=529455&r1=529454&r2=529455
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ClassNameLocatorImpl.java (original)
+++ tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ClassNameLocatorImpl.java Mon Apr 16 17:27:32 2007
@@ -15,6 +15,7 @@
package org.apache.tapestry.internal.services;
import java.io.BufferedInputStream;
+import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
@@ -27,6 +28,7 @@
import java.util.Collection;
import java.util.Enumeration;
import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
import org.apache.tapestry.internal.TapestryInternalUtils;
import org.apache.tapestry.ioc.internal.util.CollectionFactory;
@@ -93,30 +95,78 @@
{
URLConnection connection = url.openConnection();
+ JarFile jarFile;
+
if (connection instanceof JarURLConnection)
{
- scanJarConnection(packagePath, componentClassNames, (JarURLConnection) connection);
- return;
+ jarFile = ((JarURLConnection) connection).getJarFile();
+ }
+ else
+ {
+ jarFile = getAlternativeJarFile(url);
}
- // Otherwise, we're forced to assume that it is a file: URL for files in the user's
- // workspace.
+ if (jarFile != null)
+ {
+ scanJarFile(packagePath, componentClassNames, jarFile);
+ }
+ else if (supportsDirStream(url))
+ {
+ Stack<Queued> queue = CollectionFactory.newStack();
- Stack<Queued> queue = CollectionFactory.newStack();
+ queue.push(new Queued(url, packagePath));
- queue.push(new Queued(url, packagePath));
+ while (!queue.isEmpty())
+ {
+ Queued queued = queue.pop();
- while (!queue.isEmpty())
+ scanDirStream(queued._packagePath, queued._packageURL, componentClassNames, queue);
+ }
+ }
+ else
{
- Queued queued = queue.pop();
-
- scan(queued._packagePath, queued._packageURL, componentClassNames, queue);
+ // Try scanning file system.
+ String packageName = packagePath.replace("/", ".");
+ if (packageName.endsWith("."))
+ {
+ packageName = packageName.substring(0, packageName.length() - 1);
+ }
+ scanDir(packageName, new File(url.getFile()), componentClassNames);
}
}
- private void scan(String packagePath, URL packageURL, Collection<String> componentClassNames,
- Stack<Queued> queue) throws IOException
+ /**
+ * Check whether container supports opening a stream on a dir/package to get a list of its
+ * contents.
+ *
+ * @param packageURL
+ * @return
+ */
+ private boolean supportsDirStream(URL packageURL)
+ {
+ InputStream is = null;
+ try
+ {
+ is = packageURL.openStream();
+ return true;
+ }
+ catch (FileNotFoundException ex)
+ {
+ return false;
+ }
+ catch (IOException e)
+ {
+ return false;
+ }
+ finally
+ {
+ TapestryInternalUtils.close(is);
+ }
+ }
+
+ private void scanDirStream(String packagePath, URL packageURL,
+ Collection<String> componentClassNames, Stack<Queued> queue) throws IOException
{
InputStream is = null;
@@ -184,10 +234,10 @@
}
- private void scanJarConnection(String packagePath, Collection<String> componentClassNames,
- JarURLConnection connection) throws IOException
+ private void scanJarFile(String packagePath, Collection<String> componentClassNames,
+ JarFile jarFile) throws IOException
{
- Enumeration<JarEntry> e = connection.getJarFile().entries();
+ Enumeration<JarEntry> e = jarFile.entries();
while (e.hasMoreElements())
{
@@ -207,6 +257,74 @@
componentClassNames.add(className);
}
+ }
+
+ /**
+ * Scan a dir for classes. Will recursively look in the supplied directory and all sub
+ * directories.
+ *
+ * @param packageName
+ * Name of package that this directory corresponds to.
+ * @param dir
+ * Dir to scan for clases.
+ * @param componentClassNames
+ * List of class names that have been found.
+ */
+ private void scanDir(String packageName, File dir, Collection<String> componentClassNames)
+ {
+ if (dir.exists() && dir.isDirectory())
+ {
+ for (File file : dir.listFiles())
+ {
+ String fileName = file.getName();
+ if (file.isDirectory())
+ {
+ scanDir(packageName + "." + fileName, file, componentClassNames);
+ }
+ else if (fileName.endsWith(CLASS_SUFFIX))
+ {
+ String className = packageName + "."
+ + fileName.substring(0, fileName.length() - CLASS_SUFFIX.length());
+ componentClassNames.add(className);
+ }
+ }
+ }
+ }
+
+ /**
+ * For URLs to JARs that do not use JarURLConnection - allowed by the servlet spec - attempt to
+ * produce a JarFile object all the same. Known servlet engines that function like this include
+ * Weblogic and OC4J. This is not a full solution, since an unpacked WAR or EAR will not have
+ * JAR "files" as such.
+ *
+ * @param url
+ * URL of jar
+ * @return JarFile or null
+ * @throws java.io.IOException
+ * If error occurs creating jar file
+ */
+ private JarFile getAlternativeJarFile(URL url) throws IOException
+ {
+ String urlFile = url.getFile();
+ // Trim off any suffix - which is prefixed by "!/" on Weblogic
+ int separatorIndex = urlFile.indexOf("!/");
+
+ // OK, didn't find that. Try the less safe "!", used on OC4J
+ if (separatorIndex == -1)
+ {
+ separatorIndex = urlFile.indexOf('!');
+ }
+ if (separatorIndex != -1)
+ {
+ String jarFileUrl = urlFile.substring(0, separatorIndex);
+ // And trim off any "file:" prefix.
+ if (jarFileUrl.startsWith("file:"))
+ {
+ jarFileUrl = jarFileUrl.substring("file:".length());
+ }
+ return new JarFile(jarFileUrl);
+ }
+ return null;
}
}