2015-03-27 4 views
2

Метод, приведенный ниже, должен читать классы/файлы из определенного каталога. Он отлично работает при отладке метода в eclipse. Но после его создания с помощью ant scannedDir больше не является каталогом. Кто-нибудь знает, как изменить его, чтобы он по-прежнему работал после развертывания? Заранее спасибо!Каталог превращается в файл после сборки ant. Как с этим справиться?

private static List<Class<?>> find(String scannedPackage) { 

    logger.trace("Scanned package='{}'", scannedPackage); 
    String scannedPath = scannedPackage.replace(DOT, SLASH); 
    logger.trace("Scanned path='{}'", scannedPath); 
    URL scannedUrl = Thread.currentThread().getContextClassLoader().getResource(scannedPath); 
    logger.trace("Scanned url='{}'", scannedUrl); 

    if (scannedUrl == null) { 
     throw new IllegalArgumentException(String.format(BAD_PACKAGE_ERROR, scannedPath, scannedPackage)); 
    } 

    File scannedDir = new File(scannedUrl.getFile()); 
    logger.trace("scannedDir.isDirecory='{}'", scannedDir.isDirectory()); 
    List<Class<?>> classes = new ArrayList<Class<?>>(); 

    for (File file : scannedDir.listFiles()) { 
     logger.trace("currentFile='{}'", file.getAbsolutePath()); 
     classes.addAll(find(file, scannedPackage)); 
    } 

    return classes; 
} 

Так подробно: Когда я запускаю его с помощью режима отладки затмения scannedDir.isDirectory=true. Но после его строительства scannedDir.isDirectory=false

Приветствия!

EDIT:

scannedDir.getAbsolutePath() возвращает jar:file:/C:/Users/xxx.xxx/AppData/Local/XBRLGEN/app/xbrl_s2.jar!/eu/europa/eiopa/xbrl/s2c/dict/dom

+0

Вы распечатали «URL»? Если вы создали файл 'jar',' URL' не будет иметь протокол 'file:' и не может быть преобразован в объект 'File'. – Holger

+0

Его файл в банке! Добавил вывод на мой пост! – nouseforaname

ответ

0

Вы не можете обработать записи в баночке файл как File с, что никогда не будет работать. Вы также неправильно истолковываете проблему. Просто потому, что File говорит, что это не каталог, не означает, что это обычный файл, он просто не существует, поскольку вы извлекли часть URL-адреса jar: и интерпретировали как обычный файл.

Вот решение вашей задачи работает на абстракции, который не требует обычных файлов:

private static Set<Class<?>> getClasses(String pkg) 
    throws IOException, URISyntaxException { 
    ClassLoader cll = Thread.currentThread().getContextClassLoader(); 

    URI clURI = cll.getResource(pkg.replace('.', '/')).toURI(); 
    if(!clURI.getScheme().equals("file")) try { 
     FileSystems.getFileSystem(clURI); 
    } catch(FileSystemNotFoundException ex) { 
     FileSystems.newFileSystem(clURI, Collections.emptyMap()); 
    } 
    return Files.list(Paths.get(clURI)) 
     .map(p->p.getFileName().toString()) 
     .filter(s->s.endsWith(".class")) 
     .map(s->s.substring(0, s.length()-6)) 
     .map(s-> { try { 
      return cll.loadClass(pkg+'.'+s); 
      } catch(ClassNotFoundException ex) { return null; } }) 
     .filter(Objects::nonNull) 
     .collect(Collectors.toSet()); 
} 

но ненадежный jar файлы не должны иметь записи для каталогов на всех. В случае отсутствующих записей каталоги существуют только из-за того, что существует запись обычного файла внутри этого каталога, например. запись foo/bar подразумевает, что существует каталог foo. В этом случае ошибки getResource для каталога не удастся.

Самый безопасный способ запроса пакета - выбрать один класс внутри этого пакета и выполнить поиск по нему, поскольку определенный ресурс определенно существует. Затем вы можете пересечь родителя, даже если его существование подразумевается только:

private static Set<Class<?>> getClasses(Class<?> context) 
    throws IOException, URISyntaxException { 

    ClassLoader cll = context.getClassLoader(); 

    URI clURI = context.getResource(context.getSimpleName()+".class").toURI(); 
    if(!clURI.getScheme().equals("file")) try { 
     FileSystems.getFileSystem(clURI); 
    } catch(FileSystemNotFoundException ex) { 
     FileSystems.newFileSystem(clURI, Collections.emptyMap()); 
    } 
    String pkg=context.getPackage().getName(); 
    return Files.list(Paths.get(clURI).getParent()) 
     .map(p->p.getFileName().toString()) 
     .filter(s->s.endsWith(".class")) 
     .map(s->s.substring(0, s.length()-6)) 
     .map(s-> { try { 
      return Class.forName(pkg+'.'+s, false, cll); 
      } catch(ClassNotFoundException ex) { return null; } }) 
     .filter(Objects::nonNull) 
     .collect(Collectors.toSet()); 
} 
+0

Спасибо большое! Это в основном работает! Мне нужно только изменить его так, чтобы он сканировал рекурсивно через подпапки. – nouseforaname