/* * Copyright to the original author or authors. * * 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.rioproject.impl.event; import org.rioproject.event.EventDescriptor; import org.rioproject.loader.ClassAnnotator; import org.rioproject.loader.ServiceClassLoader; import org.rioproject.resolver.Artifact; import org.rioproject.resolver.ResolverException; import org.rioproject.resolver.ResolverHelper; import org.rioproject.url.artifact.ArtifactURLConfiguration; import org.rioproject.impl.util.StringUtil; import java.lang.reflect.Field; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.List; /** * Utility class to create {@code EventDescriptor}s from a classpath. * * @author Dennis Reedy */ public final class EventDescriptorFactory { private EventDescriptorFactory() { } /** * Create an {@code EventDescriptor} from a classpath. * * @param classpath The classpath to use. If {@code null}, the thread's context classloader will be used. * If not {@code null}, an {@link URLClassLoader} will be created using the provided classpath, * delegating to the thread's context classloader. * @param classNames A var-arg list of {@link org.rioproject.event.RemoteServiceEvent} class names. Must not be {@code null} * * @return A {@code List} of {@code EventDescriptor}s. * * @throws MalformedURLException if the classPath can not be used to create an {@link URL}. * @throws ResolverException if the classpath represents an artifact (groupId:artifactId:version), and a * {@code Resolver} can not be created. * @throws ClassNotFoundException If the {@link org.rioproject.event.RemoteServiceEvent} class can not be found. * @throws IllegalArgumentException if the {@code classNames} argument is {@code null}. * @throws URISyntaxException if the classpath is an artifact and the {@code URls} cannot be transformed to {@code URI}s */ public static List<EventDescriptor> createEventDescriptors(String classpath, String... classNames) throws MalformedURLException, ResolverException, ClassNotFoundException, URISyntaxException { if(classNames==null) throw new IllegalArgumentException("classNames must not be null"); if(classNames.length==0) throw new IllegalArgumentException("classNames must not be empty"); final List<EventDescriptor> eventDescriptors = new ArrayList<EventDescriptor>(); if (classpath != null) { ClassAnnotator annotator = null; String[] classPath; if (Artifact.isArtifact(classpath)) { ArtifactURLConfiguration artifactURLConfiguration = new ArtifactURLConfiguration(classpath); StringBuilder artifactBuilder = new StringBuilder(); artifactBuilder.append("artifact:").append(artifactURLConfiguration.getArtifact()); annotator = new ClassAnnotator(new URL[]{new URL(artifactBuilder.toString())}); String[] cp = ResolverHelper.getResolver().getClassPathFor(classpath); classPath = new String[cp.length]; for (int i = 0; i < classPath.length; i++) { String s = cp[i].startsWith("file:") ? cp[i] : "file:" + cp[i]; classPath[i] = ResolverHelper.handleWindows(s); } } else { classPath = StringUtil.toArray(classpath, " ,"); } URL[] urls = new URL[classPath.length]; for (int i = 0; i < classPath.length; i++) { urls[i] = new URL(classPath[i]); } URLClassLoader loader; if(annotator!=null) { loader = new ServiceClassLoader(ServiceClassLoader.getURIs(urls), annotator, Thread.currentThread().getContextClassLoader()); } else { loader = new URLClassLoader(urls, Thread.currentThread().getContextClassLoader()); } for (String className : classNames) { Class<?> cl = loader.loadClass(className); eventDescriptors.add(new EventDescriptor(cl, getID(cl))); } } else { for (String className : classNames) { Class<?> cl = Thread.currentThread().getContextClassLoader().loadClass(className); eventDescriptors.add(new EventDescriptor(cl, getID(cl))); } } return eventDescriptors; } private static Long getID(Class<?> eventClass) { Long id; try { Field field = eventClass.getField("ID"); id = (Long) field.get(null); } catch (Exception e) { id = null; } return id; } }