/*******************************************************************************
* Copyright (c) 2008, 2011 Thomas Holland (thomas@innot.de) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Thomas Holland - initial API and implementation
*******************************************************************************/
package de.innot.avreclipse.core.paths.win32;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import de.innot.avreclipse.AVRPlugin;
import de.innot.avreclipse.core.paths.AVRPath;
import de.innot.avreclipse.core.paths.SystemPathHelper;
/**
* Gets the actual system paths to the winAVR and AVR Tools applications.
* <p>
* Unlike the Posix variant of this class, which actually looks through the (almost) complete
* filesystem, this class will retrieve the paths from the Windows registry. But even this has a bit
* of overhead, so the {@link SystemPathHelper}, which uses this class, should cache the results.
* </p>
*
* @author Thomas Holland
* @since 2.1
*/
public class SystemPathsWin32 {
private static IPath fWinAVRPath = null;
private static IPath fAVRToolsPath = null;
private final static IPath fEmptyPath = new Path("");
private SystemPathsWin32() {
// prevent instantiation
}
/**
* Find the system path for the given {@link AVRPath} enum value.
*
* @param avrpath
* @return a valid path or <code>null</code> if no path could be found.
*/
public static IPath getSystemPath(AVRPath avrpath) {
switch (avrpath) {
case AVRGCC:
return getWinAVRPath("bin");
case AVRINCLUDE:
return getWinAVRPath("avr/include");
case AVRDUDE:
return getWinAVRPath("bin");
case MAKE:
return getWinAVRPath("utils/bin");
case PDFPATH:
IPath basepath = getAVRToolsPath();
if (basepath.isEmpty()) {
return basepath;
}
return basepath.append("Partdescriptionfiles");
default:
// If we end up here the AVRPath Enum has new entries not yet covered.
// Log this as an internal error and ignore otherwise
IStatus status = new Status(
IStatus.WARNING,
AVRPlugin.PLUGIN_ID,
"Internal problem! AVRPath with value ["
+ avrpath.toString()
+ "] is not covered. Please report to the AVR Eclipse plugin maintainer.",
null);
AVRPlugin.getDefault().log(status);
return null;
}
}
private static IPath getWinAVRPath(String append) {
IPath basepath = getWinAVRBasePath();
if (basepath.isEmpty()) {
return basepath;
}
return basepath.append(append);
}
/**
* Get the path to the winAVR base directory from the Windows registry.
*
* @return IPath with the current path to the winAVR base directory
*/
private static IPath getWinAVRBasePath() {
if (fWinAVRPath != null) {
return fWinAVRPath;
}
MyWindowsRegistry registry = MyWindowsRegistry.getRegistry();
if (registry == null) {
// Fix for Bug 2872447
// can't access the registry. Fail gracefully by returning an empty String.
// This will cause errors pointing the user to set the paths manually.
fWinAVRPath = fEmptyPath;
return fEmptyPath;
}
// get the newest installed version of winAVR.
// There may be multiple versions of winAVR installed.
// Grab all versions and sort them alphabetically go find the
// most recent version
int i = 0;
List<String> winavrkeys = new ArrayList<String>();
String nextkey = null;
do {
nextkey = registry.getKeyName("HKLM\\SOFTWARE\\WinAVR", i);
if (nextkey != null) {
winavrkeys.add(nextkey);
i++;
}
} while (nextkey != null);
if (winavrkeys.size() > 0) {
Collections.sort(winavrkeys);
String winavrkey = winavrkeys.get(winavrkeys.size() - 1);
String winavr = registry.getKeyValue("HKLM\\SOFTWARE\\WinAVR", winavrkey);
if (winavr != null) {
fWinAVRPath = new Path(winavr);
return fWinAVRPath;
}
}
// No "HKLM\Software\WinAVR" key in the registry
// Lets try another location: "HKLM\Software\Free Software Foundation\WinAVR-xxxxx"
//
List<String> allkeys = registry
.getSubkeys("HKLM\\SOFTWARE\\Free Software Foundation");
winavrkeys.clear();
for (String key : allkeys) {
if (key.contains("WinAVR")) {
winavrkeys.add(key);
}
}
if (winavrkeys.size() > 0) {
Collections.sort(winavrkeys);
String winavrkey = winavrkeys.get(winavrkeys.size() - 1);
String winavr = registry.getKeyValue(winavrkey, "GCC");
if (winavr != null) {
fWinAVRPath = new Path(winavr);
return fWinAVRPath;
}
}
// Couldn't find anything, so just return an empty path.
// This will cause errors pointing the user to set the paths manually.
fWinAVRPath = fEmptyPath;
return fWinAVRPath;
}
/**
* Get the path to the Atmel AVR Tools base directory from the Windows registry.
*
* @return IPath with the current path to the AVR Tools base directory
*/
private static IPath getAVRToolsPath() {
if (fAVRToolsPath != null) {
return fAVRToolsPath;
}
MyWindowsRegistry registry = MyWindowsRegistry.getRegistry();
if (registry == null) {
// can't access the registry. Fail gracefully by returning an empty String.
// This will cause errors pointing the user to set the paths manually.
fAVRToolsPath = fEmptyPath;
return fEmptyPath;
}
fAVRToolsPath = fEmptyPath;
String avrtools = registry.getKeyValue(
"HKLM\\SOFTWARE\\Atmel\\AVRTools", "AVRToolsPath");
if (avrtools != null) {
fAVRToolsPath = new Path(avrtools);
}
return fAVRToolsPath;
}
}