package net.jangaroo.ide.idea;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkType;
import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.LocalFileSystem;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
/**
* Created by IntelliJ IDEA. User: fwienber Date: 27.11.11 Time: 23:49 To change this template use File | Settings |
* File Templates.
*/
public class JangarooSdkUtils {
@Nullable
public static Sdk createOrGetSdk(SdkType sdkType, String sdkHomePath) {
if (sdkHomePath == null || LocalFileSystem.getInstance().refreshAndFindFileByPath(sdkHomePath) == null) {
return null;
}
String sdkHomePathNormalized = sdkHomePath.replace('\\', '/');
for (Sdk sdk : getSdksOfType(sdkType)) {
String homePath = sdk.getHomePath();
if (homePath != null && homePath.replace('\\', '/').equals(sdkHomePathNormalized)) {
if (sdkType instanceof JangarooSdkType) {
sdkType.setupSdkPaths(sdk);
}
return sdk;
}
}
return createSdk(sdkType, sdkHomePath);
}
private static Sdk createSdk(final SdkType sdkType, @NotNull final String sdkHomePath) {
if ((ApplicationManager.getApplication().isDispatchThread()) || (ApplicationManager.getApplication().isUnitTestMode())) {
return doCreateSdk(sdkType, sdkHomePath);
}
final Ref<Sdk> sdkRef = new Ref<Sdk>();
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
public void run() {
sdkRef.set(doCreateSdk(sdkType, sdkHomePath));
}
}, ModalityState.defaultModalityState());
return sdkRef.get();
}
private static Sdk doCreateSdk(final SdkType sdkType, @NotNull final String sdkHomePath) {
return ApplicationManager.getApplication().runWriteAction(new Computable<Sdk>() {
public Sdk compute() {
Sdk sdk = createProjectJdk(sdkType.suggestSdkName(null, sdkHomePath), "", sdkHomePath, sdkType);
sdkType.setupSdkPaths(sdk);
ProjectJdkTable projectJdkTable = ProjectJdkTable.getInstance();
projectJdkTable.addJdk(sdk);
return sdk;
}
});
}
private static Sdk createProjectJdk(final String name, final String version, final String homePath, final SdkType sdkType) {
final ProjectJdkImpl projectJdk = new ProjectJdkImpl(name, sdkType);
projectJdk.setHomePath(homePath);
projectJdk.setVersionString(version);
return projectJdk;
}
/**
* Invoke Sdk#getSdkType() by reflection because of binary incompatibility between IDEA 11 and 12.
*/
public static SdkType getSdkType(Sdk sdk) {
return (SdkType)invoke(sdk, "getSdkType", new Class[0], new Object[0]);
}
/**
* Invoke ProjectJskTable#getSdksOfType() by reflection because of binary incompatibility between IDEA 11 and 12.
*/
@SuppressWarnings("unchecked")
private static List<Sdk> getSdksOfType(SdkType sdkType) {
Class<?> sdkTypeClass;
try {
sdkTypeClass = Class.forName("com.intellij.openapi.projectRoots.SdkTypeId");
} catch (ClassNotFoundException e) {
sdkTypeClass = SdkType.class;
}
return (List<Sdk>)invoke(ProjectJdkTable.getInstance(), "getSdksOfType", new Class[]{ sdkTypeClass }, new Object[]{ sdkType });
}
private static Object invoke(Object object, String methodName, Class[] argTypes, Object[] args) {
Object result;
try {
result = object.getClass().getMethod(methodName, argTypes).invoke(object, args);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
} catch (InvocationTargetException e) {
Throwable targetException = e.getTargetException();
if (targetException instanceof RuntimeException) {
throw (RuntimeException)targetException;
} else if (targetException instanceof Error) {
throw (Error)targetException;
}
else throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
return result;
}
}