/* * Copyright 2000-2010 JetBrains s.r.o. * * 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.napile.idea.thermit; import java.lang.ref.SoftReference; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.concurrent.locks.ReentrantLock; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.util.Pair; /** * @author Eugene Zhuravlev * Date: Apr 9, 2010 */ public final class ReflectedProject { private static final Logger LOG = Logger.getInstance("#org.napile.idea.thermit.ReflectedProject"); @NonNls private static final String INIT_METHOD_NAME = "init"; @NonNls private static final String GET_TASK_DEFINITIONS_METHOD_NAME = "getTaskDefinitions"; @NonNls private static final String GET_DATA_TYPE_DEFINITIONS_METHOD_NAME = "getDataTypeDefinitions"; @NonNls private static final String GET_PROPERTIES_METHOD_NAME = "getProperties"; private static final List<SoftReference<Pair<ReflectedProject, ClassLoader>>> ourProjects = new ArrayList<SoftReference<Pair<ReflectedProject, ClassLoader>>>(); private static final ReentrantLock ourProjectsLock = new ReentrantLock(); private final Object myProject; private Hashtable myTaskDefinitions; private Hashtable myDataTypeDefinitions; private Hashtable myProperties; private Class myTargetClass; public static ReflectedProject getProject(final ClassLoader classLoader) { ourProjectsLock.lock(); try { for(Iterator<SoftReference<Pair<ReflectedProject, ClassLoader>>> iterator = ourProjects.iterator(); iterator.hasNext(); ) { final SoftReference<Pair<ReflectedProject, ClassLoader>> ref = iterator.next(); final Pair<ReflectedProject, ClassLoader> pair = ref.get(); if(pair == null) { iterator.remove(); } else { if(pair.second == classLoader) { return pair.first; } } } } finally { ourProjectsLock.unlock(); } final ReflectedProject reflectedProj = new ReflectedProject(classLoader); ourProjectsLock.lock(); try { ourProjects.add(new SoftReference<Pair<ReflectedProject, ClassLoader>>(new Pair<ReflectedProject, ClassLoader>(reflectedProj, classLoader))); } finally { ourProjectsLock.unlock(); } return reflectedProj; } ReflectedProject(final ClassLoader classLoader) { Object project = null; try { final Class projectClass = classLoader.loadClass("org.napile.thermit.Project"); if(projectClass != null) { project = projectClass.newInstance(); Method method = projectClass.getMethod(INIT_METHOD_NAME); method.invoke(project); method = getMethod(projectClass, GET_TASK_DEFINITIONS_METHOD_NAME); myTaskDefinitions = (Hashtable) method.invoke(project); method = getMethod(projectClass, GET_DATA_TYPE_DEFINITIONS_METHOD_NAME); myDataTypeDefinitions = (Hashtable) method.invoke(project); method = getMethod(projectClass, GET_PROPERTIES_METHOD_NAME); myProperties = (Hashtable) method.invoke(project); myTargetClass = classLoader.loadClass("org.napile.thermit.Target"); } } catch(ProcessCanceledException e) { throw e; } catch(ExceptionInInitializerError e) { final Throwable cause = e.getCause(); if(cause instanceof ProcessCanceledException) { throw (ProcessCanceledException) cause; } else { LOG.info(e); project = null; } } catch(InvocationTargetException e) { final Throwable cause = e.getCause(); if(cause instanceof ProcessCanceledException) { throw (ProcessCanceledException) cause; } else { LOG.info(e); project = null; } } catch(Throwable e) { LOG.info(e); project = null; } myProject = project; } private static Method getMethod(final Class introspectionHelperClass, final String name) throws NoSuchMethodException { final Method method; method = introspectionHelperClass.getMethod(name); if(!method.isAccessible()) { method.setAccessible(true); } return method; } @Nullable public Hashtable<String, Class> getTaskDefinitions() { return myTaskDefinitions; } @Nullable public Hashtable<String, Class> getDataTypeDefinitions() { return myDataTypeDefinitions; } public Hashtable getProperties() { return myProperties; } public Class getTargetClass() { return myTargetClass; } @Nullable public Object getProject() { return myProject; } }