Ok, now I know what is going on. UnifiedLoaderRepository and UnifiedLoaderRepository2 work with zip/jar files only and fail if deployment url points to a directory with classes. I wrote a patch (attached) that extands UnifiedLoaderRepository and UnifiedLoaderRepository2 to handle both jar/zip files and plain directories with classfiles. Any comments?
David Jencks wrote: > I'm not sure why what you are trying doesn't work. > > You might take a look at the ClassPathExtension mbean I wrote recently > which you can use to put anything in the classpath. > system/src/main/org/jboss/deployment/ClassPathExtension.java. > > Looks like right now it is only in Branch_3_0 > > david jencks > > On 2002.07.23 23:44:39 -0400 Igor Fedorenko wrote: > >>Hi, >> >>I am writing special deployer that needs to add some support jar files >>to a classpath of a module being deployed (almost like with manifest.mf >>but the list of jar files is kept in a different format). I checked how >>MainDeployer handles manifest.mf and tried to do similar thing - for >>each additional jar file I create/deploy sub-DeploymentInfo in >>deployer's init method. I'm getting following deployment structure >> >>DeploymentInfo d0 (url=file:///c:/ejb/classes/, deployer=JARDeployer) >>+ DeploymentInfo d1 (url=file:///c:/support1/classes /, >> deployer=JARDeployer) >> >>Although all these deployments are reported as deployed by MainDeployer >>mbean, my module does not see support classes. I have couple of question >>here. >> >>First of all - am I moving into right direction or it is not that easy >>to put jar files on a classpath? >> >>Second, what code is actually setting classpath of a deployment? I spent >>few hours hunting for it but still have no clue. >> >>Any help is appreciated. -- Igor Fedorenko Think smart. Think automated. Think Dynamics. www.thinkdynamics.comIndex: DirectoryIterator.java =================================================================== RCS file: DirectoryIterator.java diff -N DirectoryIterator.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ DirectoryIterator.java 25 Jul 2002 21:40:38 -0000 @@ -0,0 +1,94 @@ +package org.jboss.mx.loading; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; + +/** + * An iterator over all files/subdirectories of a given directory. + * + * @author Igor Fedorenko + */ +class DirectoryIterator implements Iterator { + final static String META_INF = "META-INF"; + static class Entry implements ZipOrDirEntry { + String root = null; + File file = null; + Entry(File root, File file) { + this.root = root.getPath(); + this.file = file; + } + public String getName() { + return removePrefix(file.getPath(), root); + } + public boolean isDirectory() { + return file.isDirectory(); + } + public InputStream getInputStream() throws IOException { + return new FileInputStream(file); + } + } + + File root = null; + Iterator entryIter = null; + DirectoryIterator(URL url) throws IOException { + root = new File(url.getFile()); + // get directory content + FileFilter filter = new FileFilter() { + public boolean accept(File pathname) { + return true; + } + }; + List entries = new DirectoryWalker(root.getAbsolutePath()) + .getFilesAndDirectories(filter); + entries.remove(0); // skip directory itself + // sort entries to move META-INF upfront + Collections.sort(entries, new Comparator() { + public int compare(Object o1, Object o2) { + String f1 = removePrefix(((File) o1).getPath(), root.getPath()); + String f2 = removePrefix(((File) o2).getPath(), root.getPath()); + if (f1.startsWith(META_INF)) { + return (f2.startsWith(META_INF))? f1.compareTo(f2): -1; + } else { + return (f2.startsWith(META_INF))? 1: f1.compareTo(f2); + } + } + }); + entryIter = entries.iterator(); + } + + // + // Iterator interface + // + + public boolean hasNext() { + return entryIter.hasNext(); + } + public Object next() { + return new Entry(root, (File) entryIter.next()); + } + public void remove() { + throw new UnsupportedOperationException("Not implemented"); + } + + + // + // Little helper. Is something similar available is standard lib? + // + static String removePrefix(String str, String prefix) { + if (str.startsWith(prefix)) { + return str.substring(prefix.length() + 1).replace('\\', '/'); // to look like ZipEntry; + } else { + throw new RuntimeException("Internal error in " + DirectoryIterator.class.getName()); + } + } +} Index: DirectoryWalker.java =================================================================== RCS file: DirectoryWalker.java diff -N DirectoryWalker.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ DirectoryWalker.java 25 Jul 2002 21:40:38 -0000 @@ -0,0 +1,161 @@ +/* + * Copyright (C) 1998, 2002 Gargoyle Software + * http://www.GargoyleSoftware.com + * + * This file is part of GSBase. + * + * GSBase is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GSBase is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License + * along with GSBase; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package org.jboss.mx.loading; + +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +/** + * A class to walk through the directory structure from a given starting point + * and return either files or directories or both.
+ * + * The following sample gets all java files. + *
+ * final FileFilter filter = new FileFilter() {
+ * public boolean accept( final File file ) {
+ * return file.getName().endsWith(".java");
+ * }
+ * };
+ *
+ * final DirectoryWalker directoryWalker = new DirectoryWalker(".");
+ * final List files = directoryWalker.getFiles(filter);
+ *
+ *
+ * @version $Revision: 1.6 $
+ * @author Mike Bowler
+ */
+public class DirectoryWalker {
+ private final File startingDirectory_;
+
+
+ /**
+ * Create an instance
+ *
+ * @param startingDirectory the directory to start in
+ */
+ public DirectoryWalker( final String startingDirectory ) {
+ if( startingDirectory == null ) {
+ throw new NullPointerException();
+ }
+ if( startingDirectory.length() == 0 ) {
+ throw new IllegalArgumentException( "startingDirectory is empty" );
+ }
+ startingDirectory_ = new File( startingDirectory );
+ if( startingDirectory_.exists() == false ) {
+ throw new IllegalArgumentException( "directory doesn't exist: " + startingDirectory );
+ }
+ if( startingDirectory_.isDirectory() == false ) {
+ throw new IllegalArgumentException( "Not a directory: " + startingDirectory );
+ }
+ }
+
+
+ /**
+ * Walk through the directory structure and return a list containing
+ * all those files for which the filter returns true
+ *
+ * @param filter An object to determine whether or not to include this file
+ * in the returned list
+ * @return A list of File objects
+ * @exception IOException If an error occurs
+ */
+ public List getFiles( final FileFilter filter )
+ throws IOException {
+
+ return walk( filter, true, false );
+ }
+
+
+ /**
+ * Walk through the directory structure and return a list containing
+ * all those directories for which the filter returns true
+ *
+ * @param filter An object to determine whether or not to include this
+ * directory in the returned list
+ * @return A list of File objects
+ * @exception IOException If an error occurs
+ */
+ public List getDirectories( final FileFilter filter )
+ throws IOException {
+ return walk( filter, false, true );
+ }
+
+
+ /**
+ * Walk through the directory structure and return a list containing
+ * all those files and directories for which the filter returns true
+ *
+ * @param filter An object to determine whether or not to include this
+ * file/directory in the returned list
+ * @return A list of File objects
+ * @exception IOException If an error occurs
+ */
+ public List getFilesAndDirectories( final FileFilter filter )
+ throws IOException {
+ return walk( filter, true, true );
+ }
+
+
+ private List walk(
+ final FileFilter filter,
+ final boolean includeFiles,
+ final boolean includeDirectories )
+ throws
+ IOException {
+
+ int i;
+ final List results = new ArrayList();
+ final List pendingDirectories = new LinkedList();
+ pendingDirectories.add( startingDirectory_ );
+
+ File dir;
+
+ if( includeDirectories && filter.accept( startingDirectory_ ) ) {
+ results.add( startingDirectory_ );
+ }
+
+ while( pendingDirectories.isEmpty() == false ) {
+ dir = (File)pendingDirectories.get( 0 );
+ pendingDirectories.remove( 0 );
+
+ final File[] files = dir.listFiles();
+ for( i = 0; i < files.length; i++ ) {
+ final File currentFile = files[i];
+ if( includeFiles && currentFile.isFile() && filter.accept( currentFile ) ) {
+ results.add( currentFile );
+ }
+ else if( currentFile.isDirectory() ) {
+ if( includeDirectories && filter.accept( currentFile ) ) {
+ results.add( currentFile );
+ }
+
+ pendingDirectories.add( currentFile );
+ }
+ }
+ }
+
+ return results;
+ }
+}
+
Index: UnifiedLoaderRepository.java
===================================================================
RCS file: /cvsroot/jboss/jmx/src/main/org/jboss/mx/loading/UnifiedLoaderRepository.java,v
retrieving revision 1.2.2.13
diff -u -r1.2.2.13 UnifiedLoaderRepository.java
--- UnifiedLoaderRepository.java 25 Jul 2002 21:20:26 -0000 1.2.2.13
+++ UnifiedLoaderRepository.java 25 Jul 2002 21:40:38 -0000
@@ -816,9 +816,14 @@
URL url = cl.getURL();
try
{
- InputStream is = url.openStream();
- ZipInputStream zis = new ZipInputStream(is);
- updatePackageMap(cl, zis);
+ if ("file".equals(url.getProtocol()) && url.getFile().endsWith("/")) {
+ DirectoryIterator dir = new DirectoryIterator(url);
+ updatePackageMap(cl, dir);
+ } else {
+ ZipfileIterator zip = new ZipfileIterator(url);
+ updatePackageMap(cl, zip);
+ zip.close();
+ }
}
catch(Exception e)
{
@@ -833,19 +838,19 @@
/** Given the ZipInputStream for the class jar determine what packages
it contains and create a mapping from the package names to the cl.
*/
- private void updatePackageMap(UnifiedClassLoader cl, ZipInputStream zis)
+ private void updatePackageMap(UnifiedClassLoader cl, Iterator entryIter)
throws Exception
{
boolean trace = log.isTraceEnabled();
HashSet pkgNameSet = new HashSet();
- ZipEntry entry;
- while( (entry = zis.getNextEntry()) != null )
+ while( entryIter.hasNext() )
{
+ ZipOrDirEntry entry = (ZipOrDirEntry) entryIter.next();
String name = entry.getName();
// First look for a META-INF/INDEX.LIST entry
if( name.equals("META-INF/INDEX.LIST") )
{
- readJarIndex(cl, zis, pkgNameSet);
+ readJarIndex(cl, entry.getInputStream(), pkgNameSet);
// We are done
break;
}
@@ -881,13 +886,12 @@
String[] pkgNames = new String[pkgNameSet.size()];
pkgNameSet.toArray(pkgNames);
loaderToPackagesMap.put(cl, pkgNames);
- zis.close();
}
/** Read the JDK 1.3+ META-INF/INDEX.LIST entry to obtain the package
names without having to iterate through all entries in the jar.
*/
- private void readJarIndex(UnifiedClassLoader cl, ZipInputStream zis, HashSet pkgNameSet)
+ private void readJarIndex(UnifiedClassLoader cl, InputStream zis, HashSet pkgNameSet)
throws Exception
{
boolean trace = log.isTraceEnabled();
Index: UnifiedLoaderRepository2.java
===================================================================
RCS file: /cvsroot/jboss/jmx/src/main/org/jboss/mx/loading/UnifiedLoaderRepository2.java,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 UnifiedLoaderRepository2.java
--- UnifiedLoaderRepository2.java 25 Jul 2002 21:20:26 -0000 1.1.2.3
+++ UnifiedLoaderRepository2.java 25 Jul 2002 21:40:38 -0000
@@ -496,9 +496,14 @@
URL url = cl.getURL();
try
{
- InputStream is = url.openStream();
- ZipInputStream zis = new ZipInputStream(is);
- updatePackageMap(cl, zis);
+ if ("file".equals(url.getProtocol()) && url.getFile().endsWith("/")) {
+ DirectoryIterator dir = new DirectoryIterator(url);
+ updatePackageMap(cl, dir);
+ } else {
+ ZipfileIterator zip = new ZipfileIterator(url);
+ updatePackageMap(cl, zip);
+ zip.close();
+ }
}
catch(Exception e)
{
@@ -513,19 +518,19 @@
/** Given the ZipInputStream for the class jar determine what packages
it contains and create a mapping from the package names to the cl.
*/
- private void updatePackageMap(UnifiedClassLoader cl, ZipInputStream zis)
+ private void updatePackageMap(UnifiedClassLoader cl, Iterator entryIter)
throws Exception
{
boolean trace = log.isTraceEnabled();
HashSet pkgNameSet = new HashSet();
- ZipEntry entry;
- while( (entry = zis.getNextEntry()) != null )
+ while( entryIter.hasNext() )
{
+ ZipOrDirEntry entry = (ZipOrDirEntry) entryIter.next();
String name = entry.getName();
// First look for a META-INF/INDEX.LIST entry
if( name.equals("META-INF/INDEX.LIST") )
{
- readJarIndex(cl, zis, pkgNameSet);
+ readJarIndex(cl, entry.getInputStream(), pkgNameSet);
// We are done
break;
}
@@ -561,13 +566,12 @@
String[] pkgNames = new String[pkgNameSet.size()];
pkgNameSet.toArray(pkgNames);
loaderToPackagesMap.put(cl, pkgNames);
- zis.close();
}
/** Read the JDK 1.3+ META-INF/INDEX.LIST entry to obtain the package
names without having to iterate through all entries in the jar.
*/
- private void readJarIndex(UnifiedClassLoader cl, ZipInputStream zis, HashSet pkgNameSet)
+ private void readJarIndex(UnifiedClassLoader cl, InputStream zis, HashSet pkgNameSet)
throws Exception
{
boolean trace = log.isTraceEnabled();
Index: ZipOrDirEntry.java
===================================================================
RCS file: ZipOrDirEntry.java
diff -N ZipOrDirEntry.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ZipOrDirEntry.java 25 Jul 2002 21:40:38 -0000
@@ -0,0 +1,15 @@
+package org.jboss.mx.loading;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * An entry of zip file or of a directory structure.
+ *
+ * @author Igor Fedorenko
+ */
+interface ZipOrDirEntry {
+ public String getName();
+ public boolean isDirectory();
+ public InputStream getInputStream() throws IOException;
+}
Index: ZipfileIterator.java
===================================================================
RCS file: ZipfileIterator.java
diff -N ZipfileIterator.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ZipfileIterator.java 25 Jul 2002 21:40:38 -0000
@@ -0,0 +1,64 @@
+package org.jboss.mx.loading;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+/**
+ * An iterator over all elements of a zip file.
+ *
+ * @author Igor Fedorenko
+ */
+class ZipfileIterator implements Iterator {
+ static class Entry implements ZipOrDirEntry {
+ ZipInputStream zis = null;
+ ZipEntry entry = null;
+ Entry(ZipInputStream zis, ZipEntry entry) {
+ this.zis = zis;
+ this.entry = entry;
+ }
+ public InputStream getInputStream() {
+ return zis;
+ }
+ public String getName() {
+ return entry.getName();
+ }
+ public boolean isDirectory() {
+ return entry.isDirectory();
+ }
+ }
+
+ ZipInputStream zis = null;
+ ZipEntry next = null;
+ ZipfileIterator(URL zipFile) throws IOException {
+ zis = new ZipInputStream(zipFile.openStream());
+ next = zis.getNextEntry();
+ }
+ void close() throws IOException {
+ zis.close();
+ }
+
+ //
+ // Iterator interface
+ //
+
+ public boolean hasNext() {
+ return next != null;
+ }
+ public Object next() {
+ Entry result = new Entry(zis, next);
+ try {
+ next = zis.getNextEntry();
+ } catch (IOException e) {
+ // too bad, lets rethrow
+ throw new RuntimeException(e.getMessage());
+ }
+ return result;
+ }
+ public void remove() {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+}
