Решение на C++ для Windows
Определить версию USB можно с помощью Setup API и запросов DeviceIoControl
. Нас интересуют запросы:
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX — возвращает сведения о фактически используемой в данный момент версии USB
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 — возвращает сведения о поддерживаемых версиях USB
Алгоритм следующий:
-
Функцией
SetupDiEnumDeviceInterfaces
найти все интерфейсы USB-концентраторов. -
Для каждого концентратора функцией
SetupDiGetDeviceInterfaceDetail
получить путь к устройству — строку, которую можно скармливать функцииCreateFile
вместо пути к файлу, для отправки IOCTL. -
Через
IOCTL_USB_GET_HUB_INFORMATION_EX
получить число портов на концентраторе. -
Для каждого порта отправкой
IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX
и/илиIOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2
получить сведения о порте. -
Пользуясь полями полученной структуры
USB_DEVICE_DESCRIPTOR
, можно определить VID и PID, и далее с помощью них другие необходимые параметры для идентификации устройства (Friendly Name, Service и т.п.)
Пример кода на c++ для вывода названия, идентификатора, версий USB-протокола и текущей скорости для всех запоминающих USB-устройств, основан на коде из ответа MrMoDoJoJr на stackoverflow.com:
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <Setupapi.h>
#include <winusb.h>
#undef LowSpeed
#include <Usbioctl.h>
#include <stdlib.h>
#include <Devpkey.h>
#include <iostream>
#include <string>
#include <memory>
#include <strsafe.h>
#pragma comment(lib,"Setupapi.lib")
void ErrorMes(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
wprintf(L"%s failed with error %d: %s",
lpszFunction, dw, lpMsgBuf);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
typedef struct {
wchar_t name[1024];//friendly name
wchar_t id[1024];//instance id
} USB_DEVICE_PARAMS;
/*Получение имени устройства с указанным InstanceID*/
BOOL GetDevice(wchar_t* id,wchar_t* output)
{
unsigned index;
HDEVINFO hDevInfo;
SP_DEVINFO_DATA DeviceInfoData;
TCHAR id_upper[1024]=L"";
TCHAR buf[1024]=L"";
TCHAR match[1024];
DEVPROPTYPE dpt=0;
for(int i=0;i<wcslen(id);i++){
id_upper[i]=toupper(id[i]);//преобразование в заглавные буквы
}
// List all connected devices
hDevInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
for (index = 0; ; index++) {
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
if (!SetupDiEnumDeviceInfo(hDevInfo, index, &DeviceInfoData)) {
return FALSE; // no match
}
BOOL res=SetupDiGetDeviceProperty(hDevInfo,&DeviceInfoData,
&DEVPKEY_Device_InstanceId,&dpt,(PBYTE)buf,1000,NULL,0);
if(res==FALSE)continue;
if(wcscmp(buf,id_upper)==0){
//устройство найдено
res=SetupDiGetDeviceProperty(hDevInfo,&DeviceInfoData,
&DEVPKEY_Device_FriendlyName,&dpt,(PBYTE)buf,1000,NULL,0);
wcscpy(output,buf);//возврат имени
return TRUE;
}
}
return FALSE;//устройство не найдено
}
/*Получение USB Mass Storage Device по указанным VID и PID*/
BOOL GetMassStorageDevice(int vid,int pid,USB_DEVICE_PARAMS* output)
{
unsigned index;
HDEVINFO hDevInfo;
SP_DEVINFO_DATA DeviceInfoData;
TCHAR HardwareID[1024];
TCHAR buf[1024];
TCHAR match[1024];
DEVPROPTYPE dpt=0;
BOOL res;
//формируем строку для поиска
StringCchPrintf(match,1024,L"VID_%04X&PID_%04X",vid,pid);
// List all connected USB devices
hDevInfo = SetupDiGetClassDevs(NULL, TEXT("USB"), NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES);
for (index = 0; ; index++) {
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
if (!SetupDiEnumDeviceInfo(hDevInfo, index, &DeviceInfoData)) {
return FALSE; // no match
}
res=SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_HARDWAREID, NULL,
(BYTE*)HardwareID, sizeof(HardwareID), NULL);
if(res==FALSE)continue;
if (_tcsstr(HardwareID, match)) {//найдено устройство, проверяем его тип
res=SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_SERVICE, NULL,
(BYTE*)buf, sizeof(buf), NULL);
if(res==FALSE)continue;
if(wcscmp(buf,L"USBSTOR")==0){//устройство является Mass Storage
res=SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_DEVICEDESC, NULL,
(BYTE*)buf, sizeof(buf), NULL);
if(res==FALSE)continue;
//получаем дочернее устройство
res=SetupDiGetDeviceProperty(hDevInfo,&DeviceInfoData,
&DEVPKEY_Device_Children,&dpt,(PBYTE)buf,1000,NULL,0);
if(res==FALSE)continue;//нет дочерних устройств
wcscpy(output->id,buf);//возврат ID
GetDevice(buf,output->name);//возврат имени устройства
return TRUE; // найдено
}
}
}
return FALSE;//не найдено
}
int main()
{
setlocale(LC_ALL,"Russian");
GUID guid;
/*USB HUB Interface class GUID*/
HRESULT hr = CLSIDFromString(L"{F18A0E88-C30C-11D0-8815-00A0C906BED8}", (LPCLSID)&guid);
HDEVINFO deviceInfoHandle = SetupDiGetClassDevs(&guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (deviceInfoHandle != INVALID_HANDLE_VALUE)
{
int deviceIndex = 0;
while (true)
{
SP_DEVICE_INTERFACE_DATA deviceInterface = { 0 };
deviceInterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
//получение всех USB-концентраторов
if (SetupDiEnumDeviceInterfaces(deviceInfoHandle, 0, &guid, deviceIndex, &deviceInterface))
{
DWORD cbRequired = 0;
SetupDiGetDeviceInterfaceDetail(deviceInfoHandle, &deviceInterface, 0, 0, &cbRequired, 0);
if (ERROR_INSUFFICIENT_BUFFER == GetLastError())
{
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetail =
(PSP_DEVICE_INTERFACE_DETAIL_DATA)(new char[cbRequired]);
memset(deviceInterfaceDetail, 0, cbRequired);
deviceInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(deviceInfoHandle, &deviceInterface,
deviceInterfaceDetail, cbRequired, &cbRequired, 0))
{
deviceIndex++;
continue;
}
// Initialize the structure before using it.
memset(deviceInterfaceDetail, 0, cbRequired);
deviceInterfaceDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
// Call the API a second time to retrieve the actual
// device path string.
BOOL status = SetupDiGetDeviceInterfaceDetail(
deviceInfoHandle, // Handle to device information set
&deviceInterface, // Pointer to current node in devinfo set
deviceInterfaceDetail, // Pointer to buffer to receive device path
cbRequired, // Length of user-allocated buffer
&cbRequired, // Pointer to arg to receive required buffer length
NULL); // Not interested in additional data
BOOL res;
/*Открываем устройство для отправки IOCTL*/
HANDLE handle = CreateFile(deviceInterfaceDetail->DevicePath, GENERIC_WRITE, FILE_SHARE_WRITE,
0, OPEN_EXISTING, 0, 0);
if(handle!=INVALID_HANDLE_VALUE) {
//получаем число портов на концентраторе
DWORD bytes_read=0;
USB_HUB_INFORMATION_EX hubinfo;
hubinfo.HighestPortNumber=0;
res=DeviceIoControl(handle,IOCTL_USB_GET_HUB_INFORMATION_EX ,
&hubinfo,sizeof(hubinfo),&hubinfo,sizeof(hubinfo),&bytes_read,0);
if(res==FALSE)ErrorMes(L"DeviceIoControl");
USB_NODE_CONNECTION_INFORMATION_EX coninfo={0};//get conn info
USB_NODE_CONNECTION_INFORMATION_EX_V2 con2={0};
for(int j=1;j<=(int)hubinfo.HighestPortNumber;j++){
coninfo.ConnectionIndex=j;
//получаем инфу о порте
res=DeviceIoControl(handle,IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX ,
&coninfo,sizeof(coninfo),&coninfo,sizeof(coninfo),&bytes_read,0);
if(res==FALSE){ErrorMes(L"DeviceIoControl");continue;}
if(coninfo.ConnectionStatus==0)continue;
USB_DEVICE_PARAMS usbdev={0};
//если на порте запоминающее устройство, вывести его данные
if(GetMassStorageDevice(coninfo.DeviceDescriptor.idVendor,
coninfo.DeviceDescriptor.idProduct,&usbdev)!=FALSE)
{
printf("n- Hub %2d, Port %2d: USB v%x devicen",deviceIndex,
j,(int)coninfo.DeviceDescriptor.bcdUSB);
printf("VID_%04X PID_%04Xn",(int)coninfo.DeviceDescriptor.idVendor
,(int)coninfo.DeviceDescriptor.idProduct);
wprintf(L"Device ID: %sn",usbdev.id);
wprintf(L"Device name: %sn",usbdev.name);
printf("Speed: %d",(int)coninfo.Speed);
switch((int)coninfo.Speed){
case UsbLowSpeed:printf(" (low)n");break;
case UsbFullSpeed:printf(" (full)n");break;
case UsbHighSpeed:printf(" (high)n");break;
case UsbSuperSpeed:printf(" (super)n");break;
default:printf("n");break;
}
//получение поддерживаемых протоколов
con2.ConnectionIndex=j;
con2.Length=sizeof(USB_NODE_CONNECTION_INFORMATION_EX_V2 );
con2.SupportedUsbProtocols.Usb300=1;
res=DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 ,
&con2,sizeof(con2),&con2,sizeof(con2),&bytes_read,0);
if(res==FALSE){ErrorMes(L"DeviceIoControl");continue;}
printf("Supported protocols: ");
if(con2.SupportedUsbProtocols.Usb110)printf("USB 1.1; ");
if(con2.SupportedUsbProtocols.Usb200)printf("USB 2.0; ");
if(con2.SupportedUsbProtocols.Usb300)printf("USB 3.0; ");
printf("n");
}
}//end for
CloseHandle(handle);
}else{
ErrorMes(L"CreateFile");//failed to open device
}//endif
delete[] deviceInterfaceDetail;
}
}
else
{
break;
}
++deviceIndex;
}
SetupDiDestroyDeviceInfoList(deviceInfoHandle);
}
system("PAUSE");
return 0;
}
Так выглядит результат:
Примечание. Информация выше относится к Windows 8-10. В более ранних ОС запросы на получение версии не поддерживаются, но можно получить признак поддержки High Speed:
DWORD bytes_read=0;
USB_HUB_CAPABILITIES_EX hubinfo={0};
res=DeviceIoControl(handle, IOCTL_USB_GET_HUB_CAPABILITIES ,
&hubinfo,sizeof(hubinfo),&hubinfo,sizeof(hubinfo),&bytes_read,0);
if(res==FALSE)ErrorMes(L"DeviceIoControl");
printf("Supports High speed: %dn",hubinfo.CapabilityFlags.HubIsHighSpeedCapable);
|
|||
ares
18.06.07 — 18:20 |
Получить его можно так : А установить его как ? |
||
asady
1 — 18.06.07 — 18:28 |
(0) |
||
ares
2 — 18.06.07 — 18:37 |
Если ПользователиИнформационнойБазы.ТекущийПользователь().Имя= «Иванов И.И.» Тогда Чего то не пашет, может я туплю ! |
||
asady
3 — 18.06.07 — 18:39 |
(2) не не тупишь — просто читать не умеешь….:))) |
||
ares
4 — 18.06.07 — 18:40 |
Тут присвоение не может быть помоему, т.е. так нельзя писать ПользователиИнформационнойБазы.ТекущийПользователь().ОсновнойИнтерфейс = … ,но как тогда переключить интрефейс программно, т.к. так тоже нельзя Интерфейсы.ПереключитьИнтерфейс(«Интерфейс1»); — Переменная Интерфейс не определена — и он прав. |
||
ares
5 — 18.06.07 — 18:41 |
(3)Слушай конец рабочего дня, у меня на редкость тяжелый день выдался,и завтра будет не лучше, если можешь просто напиши строку с кодом, буду очень признателен, ну очень признателен. |
||
ares
6 — 18.06.07 — 18:44 |
Писал так : ПользователиИнформационнойБазы.ТекущийПользователь().ОсновнойИнтерфейс.ПереключитьИнтерфейс(«Интерфейс1»); Пишет — Метод не обнаружен |
||
asady
7 — 18.06.07 — 18:44 |
(4) СП нужно читать — неужели мне придется весь СП скопи-пастить
Глобальный контекст |
||
ares 8 — 18.06.07 — 18:49 |
Ответ : Спасибо Asady , я все пыталяс прицепить его к пользователю, а он от текущего пляшет. Еще раз спасибо, я никакой сегодня, хоть выжимай. |
TurboConf — расширение возможностей Конфигуратора 1С
Интерфейсы
Определение интерфейсов
Последнее обновление: 01.01.2022
Интерфейс представляет ссылочный тип, который может определять некоторый функционал — набор методов и свойств без реализации.
Затем этот функционал реализуют классы и структуры, которые применяют данные интерфейсы.
Определение интерфейса
Для определения интерфейса используется ключевое слово interface. Как правило, названия интерфейсов в C# начинаются с заглавной буквы
I, например, IComparable, IEnumerable (так называемая венгерская нотация), однако это не обязательное требование, а больше стиль программирования.
Что может определять интерфейс? В целом интерфейсы могут определять следующие сущности:
-
Методы
-
Свойства
-
Индексаторы
-
События
-
Статические поля и константы (начиная с версии C# 8.0)
Однако интерфейсы не могут определять нестатические переменные. Например, простейший интерфейс, который определяет все эти компоненты:
interface IMovable { // константа const int minSpeed = 0; // минимальная скорость // статическая переменная static int maxSpeed = 60; // максимальная скорость // метод void Move(); // движение // свойство string Name { get; set; } // название delegate void MoveHandler(string message); // определение делегата для события // событие event MoveHandler MoveEvent; // событие движения }
В данном случае определен интерфейс IMovable, который представляет некоторый движущийся объект. Данный интерфейс содержит различные компоненты,
которые описывают возможности движущегося объекта. То есть интерфейс описывает некоторый функционал, который должен быть у движущегося объекта.
Методы и свойства интерфейса могут не иметь реализации, в этом они сближаются с абстрактными методами и свойствами абстрактных классов.
В данном случае интерфейс определяет метод Move, который будет представлять некоторое передвижение. Он не имеет реализации, не принимает никаких параметров и ничего не возвращает.
То же самое в данном случае касается свойства Name. На первый взгляд оно похоже на автоматическое свойство. Но в реальности это определение свойства в интерфейсе, которое не имеет реализации, а не автосвойство.
Модификаторы доступа
Еще один момент в объявлении интерфейса: если его члены — методы и свойства не имеют модификаторов доступа, то фактически по умолчанию доступ
public, так как цель интерфейса — определение функционала для реализации его классом. Это касается также и констант и
статических переменных, которые в классах и структурах по умолчанию имееют модификатор private. В интерфейсах же они имеют по умолчанию модификатор
public. И например, мы могли бы обратиться к константе minSpeed и переменной maxSpeed интерфейса IMovable:
Console.WriteLine(IMovable.maxSpeed); // 60 Console.WriteLine(IMovable.minSpeed); // 0
Но также, начиная с версии C# 8.0, мы можем явно указывать модификаторы доступа у компонентов интерфейса:
interface IMovable { public const int minSpeed = 0; // минимальная скорость private static int maxSpeed = 60; // максимальная скорость public void Move(); protected internal string Name { get; set; } // название public delegate void MoveHandler(string message); // определение делегата для события public event MoveHandler MoveEvent; // событие движения }
Как и классы, интерфейсы по умолчанию имеют уровень доступа internal, то есть такой интерфейс доступен только
в рамках текущего проекта. Но с помощью модификатора public мы можем сделать интерфейс общедоступным:
public interface IMovable { void Move(); }
Реализация по умолчанию
Также начиная с версии C# 8.0 интерфейсы поддерживают реализацию методов и свойств по умолчанию. Это значит, что мы можем определить в интерфейсах полноценные методы и свойства, которые
имеют реализацию как в обычных классах и структурах. Например, определим реализацию метода Move по умолчанию:
interface IMovable { // реализация метода по умолчанию void Move() { Console.WriteLine("Walking"); } }
С реализацией свойств по умолчанию в интерфейсах дело обстоит несколько сложнее, поскольку мы не можем определять в интерфейсах нестатические
переменные, соответственно в свойствах интерфейса мы не можем манипулировать состоянием объекта. Тем не менее реализацию по умолчанию для свойств мы тоже можем определять:
interface IMovable { // реализация метода по умолчанию void Move() => Console.WriteLine("Walking"); // реализация свойства по умолчанию // свойство только для чтения int MaxSpeed { get { return 0; } } }
Стоит отметить, что если интерфейс имеет приватные методы и свойства (то есть с модификатором private), то они должны иметь реализацию по умолчанию.
То же самое относится к статическим методам (не обязательно приватным):
Console.WriteLine(IMovable.MaxSpeed); // 60 IMovable.MaxSpeed = 65; Console.WriteLine(IMovable.MaxSpeed); // 65 double time = IMovable.GetTime(500, 10); Console.WriteLine(time); // 50 interface IMovable { public const int minSpeed = 0; // минимальная скорость private static int maxSpeed = 60; // максимальная скорость // находим время, за которое надо пройти расстояние distance со скоростью speed static double GetTime(double distance, double speed) => distance / speed; static int MaxSpeed { get => maxSpeed; set { if (value > 0) maxSpeed = value; } } }
Добавление интерфейса
Стоит отметить, что в Visual Studio есть специальный компонент для добавления нового интерфейса в отдельном файле.
Для добавления интерфейса в проект можно нажать правой кнопкой мыши на проект и в появившемся контекстном меню выбрать Add->
New Item… и в диалоговом окне добавления нового компонента выбрать пункт Interface:
Хотя мы также может добавить стандартный файл класса или любой другой файл кода C# и в нем определить интерфейс.
COM-подключение к базе 7.7 из 8.2 1С 6
Если код выполняется на стороне клиента, то необходимо наличие базы 7.7 на локальной машине.
Пример (На форме объекта присутствует реквизит Таблица(ТаблицаЗначений)):
НаКлиенте
Процедура Загрузки()
ПутьКБазе=» D:ВашаБаза1с77″ ;
Пользователь=
Cодержимое указанного ниже веб-сайта в этом приложении блокируется… Aboutsecurity_1cv8c.exe 1
Проблема: После обновления на 1С:Бухгалтерию предприятия 3-й версии, при нажатии на закладку командного интерфейса 1С:предприятие, выскакивает ошибка: Aboutsecurity_1cv8c.exe или Aboutsecurity_1cv8.exe «Содержимое указанного ниже веб-узла в э
Excel файл как Внешний источник данных 16
Подключимся и загрузим из файла Excel данные в таблицу значений 1С. Сделать теперь это очень просто.
1. В конфигурации добавляет новый объект метаданных типа » Внешние источники данных» и назовем его просто » Excel» .
https://helpf.pro/uploads/img
Google maps : вывод точек на карту и режим панорамы 8
В отличие от яндекс карт в GMaps можно использовать панорамы — за что им большой плюс! Надеюсь в яндексе прочитают этот пост и тоже когда-нибудь это сделают! Для клиента нужно было сделать вывод объектов на карту С возможностью просмотра панора
Битая ссылка, <Объект не найден>, Уникальный Идентификатор, GUID 74
Когда кто-то удаляет данные из базы без проверки ссылок на эти объекты, то везде где этот объект использовался появляется сообщение вида: Объект не найден (84:bf5600145e3710ab11dda4c605dbe824) .
https://helpf.pro/uploads/img/_1-46z7I4U7Ww.png
В
Посмотреть все результаты поиска похожих
Some time ago, I came across a piece of code, that used some piece of standard Java functionality to locate the classes that implemented a given interface. I know the functions were hidden in some non-logical place, but they could be used for other classes as the package name implied. Back then I did not need it, so I forgot about it, but now I do, and I can’t seem to find the functions again. Where can these functions be found?
Edit: I’m not looking for any IDE functions or anything, but rather something that can be executed within the Java application.
asked Jan 12, 2009 at 16:05
3
Awhile ago, I put together a package for doing what you want, and more. (I needed it for a utility I was writing). It uses the ASM library. You can use reflection, but ASM turned out to perform better.
I put my package in an open source library I have on my web site. The library is here: http://software.clapper.org/javautil/. You want to start with the with ClassFinder class.
The utility I wrote it for is an RSS reader that I still use every day, so the code does tend to get exercised. I use ClassFinder to support a plug-in API in the RSS reader; on startup, it looks in a couple directory trees for jars and class files containing classes that implement a certain interface. It’s a lot faster than you might expect.
The library is BSD-licensed, so you can safely bundle it with your code. Source is available.
If that’s useful to you, help yourself.
Update: If you’re using Scala, you might find this library to be more Scala-friendly.
answered Jan 12, 2009 at 16:16
Brian ClapperBrian Clapper
25.5k7 gold badges65 silver badges65 bronze badges
13
Spring can do this for you…
BeanDefinitionRegistry bdr = new SimpleBeanDefinitionRegistry();
ClassPathBeanDefinitionScanner s = new ClassPathBeanDefinitionScanner(bdr);
TypeFilter tf = new AssignableTypeFilter(CLASS_YOU_WANT.class);
s.addIncludeFilter(tf);
s.scan("package.you.want1", "package.you.want2");
String[] beans = bdr.getBeanDefinitionNames();
N.B. The TypeFilter is important if you want the correct results!
You can also use exclusion filters here instead.
The Scanner can be found in the spring-context jar, the registry in spring-beans, the type filter is in spring-core.
answered Nov 17, 2011 at 12:19
Nick RobsonNick Robson
6515 silver badges2 bronze badges
7
I really like the reflections library for doing this.
It provides a lot of different types of scanners (getTypesAnnotatedWith
, getSubTypesOf
, etc), and it is dead simple to write or extend your own.
Manius
3,5743 gold badges34 silver badges44 bronze badges
answered Mar 27, 2012 at 14:14
2
The code you are talking about sounds like ServiceLoader
, which was introduced in Java 6 to support a feature that has been defined since Java 1.3 or earlier. For performance reasons, this is the recommended approach to find interface implementations at runtime; if you need support for this in an older version of Java, I hope that you’ll find my implementation helpful.
There are a couple of implementations of this in earlier versions of Java, but in the Sun packages, not in the core API (I think there are some classes internal to ImageIO that do this). As the code is simple, I’d recommend providing your own implementation rather than relying on non-standard Sun code which is subject to change.
answered Jan 12, 2009 at 17:21
ericksonerickson
264k58 gold badges392 silver badges491 bronze badges
8
Package Level Annotations
I know this question has already been answered a long time ago but another solution to this problem is to use Package Level Annotations.
While its pretty hard to go find all the classes in the JVM its actually pretty easy to browse the package hierarchy.
Package[] ps = Package.getPackages();
for (Package p : ps) {
MyAno a = p.getAnnotation(MyAno.class)
// Recursively descend
}
Then just make your annotation have an argument of an array of Class.
Then in your package-info.java for a particular package put the MyAno.
I’ll add more details (code) if people are interested but most probably get the idea.
MetaInf Service Loader
To add to @erickson answer you can also use the service loader approach. Kohsuke has an awesome way of generating the the required META-INF stuff you need for the service loader approach:
http://weblogs.java.net/blog/kohsuke/archive/2009/03/my_project_of_t.html
answered Apr 29, 2011 at 12:08
Adam GentAdam Gent
47.6k22 gold badges153 silver badges202 bronze badges
3
You could also use the Extensible Component Scanner (extcos: http://sf.net/projects/extcos) and search all classes implementing an interface like so:
Set<Class<? extends MyInterface>> classes = new HashSet<Class<? extends MyInterface>>();
ComponentScanner scanner = new ComponentScanner();
scanner.getClasses(new ComponentQuery() {
@Override
protected void query() {
select().
from("my.package1", "my.package2").
andStore(thoseImplementing(MyInterface.class).into(classes)).
returning(none());
}
});
This works for classes on the file system, within jars and even for those on the JBoss virtual file system. It’s further designed to work within standalone applications as well as within any web or application container.
answered Apr 12, 2012 at 14:13
5
In full generality, this functionality is impossible. The Java ClassLoader mechanism guarantees only the ability to ask for a class with a specific name (including package), and the ClassLoader can supply a class, or it can state that it does not know that class.
Classes can be (and frequently are) loaded from remote servers, and they can even be constructed on the fly; it is not difficult at all to write a ClassLoader that returns a valid class that implements a given interface for any name you ask from it; a List of the classes that implement that interface would then be infinite in length.
In practice, the most common case is an URLClassLoader
that looks for classes in a list of filesystem directories and JAR files. So what you need is to get the URLClassLoader
, then iterate through those directories and archives, and for each class file you find in them, request the corresponding Class
object and look through the return of its getInterfaces()
method.
Frankie
24.5k10 gold badges78 silver badges121 bronze badges
answered Jan 12, 2009 at 16:24
Michael BorgwardtMichael Borgwardt
341k78 gold badges481 silver badges718 bronze badges
5
Obviously, Class.isAssignableFrom() tells you whether an individual class implements the given interface. So then the problem is getting the list of classes to test.
As far as I’m aware, there’s no direct way from Java to ask the class loader for «the list of classes that you could potentially load». So you’ll have to do this yourself by iterating through the visible jars, calling Class.forName() to load the class, then testing it.
However, it’s a little easier if you just want to know classes implementing the given interface from those that have actually been loaded:
- via the Java Instrumentation framework, you can call Instrumentation.getAllLoadedClasses()
- via reflection, you can query the ClassLoader.classes field of a given ClassLoader.
If you use the instrumentation technique, then (as explained in the link) what happens is that your «agent» class is called essentially when the JVM starts up, and passed an Instrumentation object. At that point, you probably want to «save it for later» in a static field, and then have your main application code call it later on to get the list of loaded classes.
answered Jan 12, 2009 at 17:17
Neil CoffeyNeil Coffey
21.6k7 gold badges62 silver badges83 bronze badges
2
If you were asking from the perspective of working this out with a running program then you need to look to the java.lang.* package. If you get a Class object, you can use the isAssignableFrom method to check if it is an interface of another Class.
There isn’t a simple built in way of searching for these, tools like Eclipse build an index of this information.
If you don’t have a specific list of Class objects to test you can look to the ClassLoader object, use the getPackages() method and build your own package hierarchy iterator.
Just a warning though that these methods and classes can be quite slow.
answered Jan 12, 2009 at 16:23
Matt LargeMatt Large
3991 gold badge4 silver badges9 bronze badges