*added support for library files in user platforms (for example in dev and sys subdirectories)

*added user platform history in platform configs
*throwing 'include user platform directories' flags to compiler

*fixed bug in platform config viewer
*removed old custom class loader
This commit is contained in:
fros4943 2006-08-22 15:28:17 +00:00
parent e10f020fec
commit c8f379adf7
5 changed files with 229 additions and 247 deletions

View file

@ -1,143 +0,0 @@
/*
* Copyright (c) 2006, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: DirectoryClassLoader.java,v 1.1 2006/08/21 12:12:56 fros4943 Exp $
*/
package se.sics.cooja;
import java.io.*;
import org.apache.log4j.Logger;
/**
* Loads an external file from the given directory as a Java class.
*
* @author Fredrik Osterlind
*/
public class DirectoryClassLoader extends ClassLoader {
private static Logger logger = Logger.getLogger(DirectoryClassLoader.class);
private File directory;
/**
* Creates a new class loader reading from given directory.
*
* @param directory
* Directory
*/
public DirectoryClassLoader(File directory) {
super();
this.directory = directory;
}
/**
* Creates a new class loader reading from given directory, with the given
* class loader as parent class loader.
*
* @param parent
* Parent class loader
* @param directory
* Directory
*/
public DirectoryClassLoader(ClassLoader parent, File directory) {
super(parent);
this.directory = directory;
}
public Class<?> findClass(String name) throws ClassNotFoundException {
String fullFilePath = directory.getPath() + File.separatorChar + name
+ ".class";
// Read external file
//logger.info("Directory class loader reading file: " + fullFilePath);
byte[] classData = loadClassData(fullFilePath);
if (classData == null) {
throw new ClassNotFoundException();
}
// Create class
return defineClass(name, classData, 0, classData.length);
}
private byte[] loadClassData(String name) {
// Support for fill class names in configuration file
// TODO Quick-fix (may contain bugs)
name = name.replace('.', File.separatorChar);
name = name.replace(File.separatorChar + "class", ".class");
// Open file for read access
File classFile = new File(name);
InputStream inputStream = null;
if (!classFile.exists()) {
//logger.fatal("File " + classFile + " does not exist!");
return null;
}
try {
inputStream = new FileInputStream(classFile);
if (inputStream == null) {
logger.fatal("File input stream is null!");
return null;
}
} catch (FileNotFoundException e) {
logger.fatal("Could not open file (not found?)!");
return null;
}
long fileSize = classFile.length();
if (fileSize > Integer.MAX_VALUE) {
logger.fatal("Class file is too large");
return null;
}
// Read class data
byte[] classData = new byte[(int) fileSize];
int offset = 0;
int numRead = 0;
try {
while (offset < classData.length
&& (numRead = inputStream.read(classData, offset, classData.length
- offset)) >= 0) {
offset += numRead;
}
inputStream.close();
} catch (IOException e) {
logger.fatal("Error when reading class file");
return null;
}
// Ensure all the bytes have been read in
if (offset < classData.length) {
logger.fatal("Could not read entire class file");
return null;
}
return classData;
}
}

View file

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: GUI.java,v 1.3 2006/08/22 12:25:24 nifi Exp $
* $Id: GUI.java,v 1.4 2006/08/22 15:28:17 fros4943 Exp $
*/
package se.sics.cooja;
@ -560,24 +560,15 @@ public class GUI extends JDesktopPane {
unregisterPositioners();
unregisterRadioMediums();
// Read default configuration
platformConfig = new PlatformConfig();
// logger.info("Loading default platform configuration: " +
// PLATFORM_DEFAULT_CONFIG_FILENAME);
try {
InputStream input =
GUI.class.getResourceAsStream(PLATFORM_DEFAULT_CONFIG_FILENAME);
if (input != null) {
try {
platformConfig.appendConfig(input);
} finally {
input.close();
}
} else {
logger.fatal("Could not find default platform config file: "
+ PLATFORM_DEFAULT_CONFIG_FILENAME);
return false;
}
// Read default configuration
platformConfig = new PlatformConfig(true);
// logger.info("Loading default platform configuration: " +
// PLATFORM_DEFAULT_CONFIG_FILENAME);
} catch (FileNotFoundException e) {
logger.fatal("Could not find default platform config file: "
+ PLATFORM_DEFAULT_CONFIG_FILENAME);
return false;
} catch (IOException e) {
logger.fatal("Error when reading default platform config file: "
+ PLATFORM_DEFAULT_CONFIG_FILENAME);
@ -586,20 +577,18 @@ public class GUI extends JDesktopPane {
// Append user platform configurations
for (File userPlatform : currentUserPlatforms) {
File userPlatformConfig = new File(userPlatform.getPath()
+ File.separatorChar + PLATFORM_CONFIG_FILENAME);
// logger.info("Loading platform configuration: " + userPlatformConfig);
try {
// Append config to general config
platformConfig.appendConfig(userPlatformConfig);
// logger.info("Appending user platform configuration: " + userPlatform);
platformConfig.appendUserPlatform(userPlatform);
} catch (FileNotFoundException e) {
logger.fatal("Could not find platform config file: "
+ userPlatformConfig);
+ userPlatform);
return false;
} catch (IOException e) {
logger.fatal("Error when reading platform config file: "
+ userPlatformConfig);
+ userPlatform);
return false;
}
}
@ -1556,45 +1545,43 @@ public class GUI extends JDesktopPane {
}
private ClassLoader createClassLoader(ClassLoader parent,
Vector<File> platformsList) {
Vector<File> platformsList) {
if (platformsList == null || platformsList.isEmpty()) {
return parent;
}
// Combine class loader from all user platforms (including any
// specified JAR files)
ArrayList<URL> urls = new ArrayList<URL>();
for (int j = platformsList.size() - 1; j >= 0; j--) {
File userPlatform = platformsList.get(j);
try {
urls.add((new File(userPlatform, "java")).toURL());
// Read configuration to check if any JAR files should be loaded
File userPlatformConfigFile =
new File(userPlatform, PLATFORM_CONFIG_FILENAME);
PlatformConfig userPlatformConfig = new PlatformConfig();
userPlatformConfig.appendConfig(userPlatformConfigFile);
urls.add((new File(userPlatform, "java")).toURL());
// Read configuration to check if any JAR files should be loaded
PlatformConfig userPlatformConfig = new PlatformConfig(false);
userPlatformConfig.appendUserPlatform(userPlatform);
String[] platformJarFiles = userPlatformConfig.getStringArrayValue(
GUI.class, "JARFILES");
if (platformJarFiles != null && platformJarFiles.length > 0) {
for (String jarfile : platformJarFiles) {
for (String jarfile : platformJarFiles) {
File jarpath = findJarFile(userPlatform, jarfile);
if (jarpath == null) {
throw new FileNotFoundException(jarfile);
}
urls.add(jarpath.toURL());
if (jarpath == null) {
throw new FileNotFoundException(jarfile);
}
urls.add(jarpath.toURL());
}
}
} catch (Exception e) {
logger.fatal("Error when trying to read JAR-file in " + userPlatform
+ ": " + e);
}
}
return new URLClassLoader((URL[]) urls.toArray(new URL[urls.size()]),
userPlatformClassLoader);
userPlatformClassLoader);
}
/**
* Help method that returns the description for given object. This method
* reads from the object's class annotations if existing. Otherwise it returns

View file

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: PlatformConfig.java,v 1.1 2006/08/21 12:12:56 fros4943 Exp $
* $Id: PlatformConfig.java,v 1.2 2006/08/22 15:28:17 fros4943 Exp $
*/
package se.sics.cooja;
@ -86,13 +86,124 @@ import org.apache.log4j.Logger;
public class PlatformConfig {
private static Logger logger = Logger.getLogger(PlatformConfig.class);
private Properties myConfig = new Properties();
private Properties myConfig = null;
private Vector<File> myUserPlatformHistory = null;
/**
* Creates a new empty platform configuration.
* Creates new platform configuration.
*
* @param useDefault
* If true the default configuration will be loaded
* @throws FileNotFoundException
* If file was not found
* @throws IOException
* Stream read error
*/
public PlatformConfig() {
public PlatformConfig(boolean useDefault) throws IOException,
FileNotFoundException {
// Create empty configuration
myConfig = new Properties();
myUserPlatformHistory = new Vector<File>();
if (useDefault) {
InputStream input = GUI.class
.getResourceAsStream(GUI.PLATFORM_DEFAULT_CONFIG_FILENAME);
if (input != null) {
try {
appendConfigStream(input);
} finally {
input.close();
}
} else {
throw new FileNotFoundException(GUI.PLATFORM_DEFAULT_CONFIG_FILENAME);
}
}
}
/**
* Appends the given user platform's config file. Thus method also saved a
* local history of which user platforms has been loaded.
*
* @param userPlatform
* User platform
* @return True if loaded OK
* @throws FileNotFoundException
* If file was not found
* @throws IOException
* Stream read error
*/
public boolean appendUserPlatform(File userPlatform)
throws FileNotFoundException, IOException {
File userPlatformConfig = new File(userPlatform.getPath()
+ File.separatorChar + GUI.PLATFORM_CONFIG_FILENAME);
myUserPlatformHistory.add(userPlatform);
return appendConfigFile(userPlatformConfig);
}
/**
* Returns the user platform earlier appended to this configuration that
* defined the given key. If the key is of an array format and the given array
* element is non-null, then the user platform that added this element will be
* returned instead. If no such user platform can be found null is returned
* instead.
*
* @param callingClass
* Class which value belongs to
* @param key
* Key
* @param value
* Element of array
* @return User platform
*/
public File getUserPlatformDefining(Class callingClass, String key, String arrayElement) {
// Check that key really exists in current config
if (getStringValue(callingClass, key, null) == null) {
return null;
}
// Check that element really exists, if any
if (arrayElement != null) {
String[] array = getStringArrayValue(callingClass, key);
boolean foundValue = false;
for (int c=0; c < array.length; c++) {
if (array[c].equals(arrayElement))
foundValue = true;
}
if (!foundValue) {
return null;
}
}
// Search in all user platform in reversed order
try {
PlatformConfig remadeConfig = new PlatformConfig(false);
for (int i=myUserPlatformHistory.size()-1; i >= 0; i--) {
remadeConfig.appendUserPlatform(myUserPlatformHistory.get(i));
if (arrayElement != null) {
// Look for array
String[] array = remadeConfig.getStringArrayValue(callingClass, key);
for (int c=0; c < array.length; c++) {
if (array[c].equals(arrayElement))
return myUserPlatformHistory.get(i);
}
} else {
// Look for key
if (remadeConfig.getStringValue(callingClass, key, null) != null) {
return myUserPlatformHistory.get(i);
}
}
}
} catch (Exception e) {
logger.fatal("Exception when searching in user platform history: " + e);
return null;
}
return null;
}
/**
@ -100,6 +211,9 @@ public class PlatformConfig {
* If a property already exists it will be overwritten, unless the new value
* begins with a '+' in which case the old value will be extended.
*
* WARNING! The user platform history will not be saved if this method is
* called, instead the appendUserPlatform method should be used.
*
* @param propertyFile
* Property file to read
* @return True if file was read ok, false otherwise
@ -108,35 +222,33 @@ public class PlatformConfig {
* @throws IOException
* Stream read error
*/
public boolean appendConfig(File propertyFile) throws FileNotFoundException,
IOException {
return appendConfig(myConfig, propertyFile);
}
private static boolean appendConfig(Properties currentValues,
File propertyFile) throws FileNotFoundException, IOException {
// Open file
public boolean appendConfigFile(File propertyFile)
throws FileNotFoundException, IOException {
FileInputStream in = new FileInputStream(propertyFile);
return appendConfig(currentValues, in);
return appendConfigStream(myConfig, in);
}
/**
* Reads propertues from the given stream and appends them to the current
* Reads properties from the given stream and appends them to the current
* configuration. If a property already exists it will be overwritten, unless
* the new value begins with a '+' in which case the old value will be
* extended.
*
* WARNING! The user platform history will not be saved if this method is
* called, instead the appendUserPlatform method should be used.
*
* @param configFileStream
* Stream to read from
* @return True if stream was read ok, false otherwise
* @throws IOException
* Stream read error
*/
public boolean appendConfig(InputStream configFileStream) throws IOException {
return appendConfig(myConfig, configFileStream);
public boolean appendConfigStream(InputStream configFileStream)
throws IOException {
return appendConfigStream(myConfig, configFileStream);
}
private static boolean appendConfig(Properties currentValues,
private static boolean appendConfigStream(Properties currentValues,
InputStream configFileStream) throws IOException {
// Read from stream
@ -151,7 +263,8 @@ public class PlatformConfig {
String property = newProps.getProperty(key);
if (property.startsWith("+ ")) {
if (currentValues.getProperty(key) != null)
currentValues.setProperty(key, currentValues.getProperty(key) + " " + property.substring(1).trim());
currentValues.setProperty(key, currentValues.getProperty(key) + " "
+ property.substring(1).trim());
else
currentValues.setProperty(key, property.substring(1).trim());
} else
@ -189,7 +302,8 @@ public class PlatformConfig {
String val = currentValues.getProperty(callingClass.getName() + "." + id);
if (val == null) {
logger.warn("Could not find key named '" + callingClass.getName() + "." + id + "'");
logger.warn("Could not find key named '" + callingClass.getName() + "."
+ id + "'");
return defaultValue;
}
@ -253,6 +367,21 @@ public class PlatformConfig {
return getStringValue(callingClass, id);
}
/**
* Get string array value with given id.
*
* @param id
* Id of value to return
* @return Value or null if id wasn't found
*/
public String[] getStringArrayValue(String id) {
String stringVal = getStringValue(id);
if (stringVal == null)
return new String[0];
return getStringValue(id).split(" ");
}
/**
* Get integer value with given id.
*
@ -352,8 +481,13 @@ public class PlatformConfig {
}
public PlatformConfig clone() {
PlatformConfig clone = new PlatformConfig();
clone.myConfig = (Properties) this.myConfig.clone();
return clone;
try {
PlatformConfig clone = new PlatformConfig(false);
clone.myConfig = (Properties) this.myConfig.clone();
clone.myUserPlatformHistory = (Vector<File>) this.myUserPlatformHistory.clone();
return clone;
} catch (Exception e) {
return null;
}
}
}

View file

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ContikiMoteTypeDialog.java,v 1.3 2006/08/22 12:26:36 nifi Exp $
* $Id: ContikiMoteTypeDialog.java,v 1.4 2006/08/22 15:28:18 fros4943 Exp $
*/
package se.sics.cooja.contikimote;
@ -898,8 +898,19 @@ public class ContikiMoteTypeDialog extends JDialog {
String[] projectSourceFiles = newMoteTypeConfig.getStringArrayValue(
ContikiMoteType.class, "C_SOURCES");
for (String projectSourceFile : projectSourceFiles) {
if (!projectSourceFile.trim().equals("")) {
filesToCompile.add(new File(projectSourceFile));
if (!projectSourceFile.equals("")) {
File file = new File(projectSourceFile);
if (file.getParent() != null) {
// Find which user platform added this file
File userPlatform = newMoteTypeConfig.getUserPlatformDefining(
ContikiMoteType.class, "C_SOURCES", projectSourceFile);
if (userPlatform != null) {
// We found a user platform - Add directory
filesToCompile.add(new File(userPlatform.getPath(),
file.getParent()));
}
}
filesToCompile.add(new File(file.getName()));
}
}
@ -1165,16 +1176,20 @@ public class ContikiMoteTypeDialog extends JDialog {
String sourceDirs = System.getProperty("PROJECTDIRS", "");
String sourceFileNames = "";
String ccFlags = GUI.getExternalToolsSetting("COMPILER_ARGS", "");
for (File sourceFile : sourceFiles) {
if (sourceFile.isDirectory()) {
// Add directory to search path
sourceDirs += " "
+ sourceFile.getPath().replace(File.separatorChar, '/');
ccFlags += " -I" + sourceFile.getPath().replace(File.separatorChar, '/');
} else if (sourceFile.isFile()) {
// Add both file name and directory
sourceDirs += " " +
sourceFile.getParent().replace(File.separatorChar, '/');
if (sourceFile.getParent() != null) {
sourceDirs += " " +
sourceFile.getParent().replace(File.separatorChar, '/');
}
sourceFileNames += " " + sourceFile.getName();
} else {
// Add filename and hope Contiki knows where to find it...
@ -1182,12 +1197,16 @@ public class ContikiMoteTypeDialog extends JDialog {
}
}
logger.info("Project dirs: " + sourceDirs);
logger.info("Project sources: " + sourceFileNames);
logger.info("Compiler flags: " + ccFlags);
String[] env = new String[]{
"CONTIKI=" + contikiDir.getPath().replace(File.separatorChar, '/'),
"TARGET=cooja", "TYPEID=" + identifier,
"LD_ARGS_1=" + GUI.getExternalToolsSetting("LINKER_ARGS_1", ""),
"LD_ARGS_2=" + GUI.getExternalToolsSetting("LINKER_ARGS_2", ""),
"EXTRA_CC_ARGS=" + GUI.getExternalToolsSetting("COMPILER_ARGS", ""),
"EXTRA_CC_ARGS=" + ccFlags,
"CC=" + GUI.getExternalToolsSetting("PATH_C_COMPILER"),
"LD=" + GUI.getExternalToolsSetting("PATH_LINKER"), "COMPILE_MAIN=1",
"PROJECTDIRS=" + sourceDirs,
@ -2008,18 +2027,12 @@ public class ContikiMoteTypeDialog extends JDialog {
// Merge with all user platform configs (if any)
for (File userPlatform : moteTypeUserPlatforms) {
File userPlatformConfig = new File(userPlatform.getPath()
+ File.separatorChar + GUI.PLATFORM_CONFIG_FILENAME);
if (userPlatformConfig.exists()) {
try {
newMoteTypeConfig.appendConfig(userPlatformConfig);
} catch (Exception ex) {
logger.fatal("Error when parsing user platform config: " + ex);
return;
}
} else
logger.fatal("Could not find user platform config file: "
+ userPlatformConfig);
try {
newMoteTypeConfig.appendUserPlatform(userPlatform);
} catch (Exception ex) {
logger.fatal("Error when parsing user platform config: " + ex);
return;
}
}
// Get all mote interfaces available from config

View file

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: UserPlatformsDialog.java,v 1.2 2006/08/22 08:56:08 nifi Exp $
* $Id: UserPlatformsDialog.java,v 1.3 2006/08/22 15:28:18 fros4943 Exp $
*/
package se.sics.cooja.dialogs;
@ -220,22 +220,14 @@ public class UserPlatformsDialog extends JDialog {
button = new JButton("View resulting config");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Create default configuration
PlatformConfig config = new PlatformConfig();
PlatformConfig config;
try {
InputStream input =
GUI.class.getResourceAsStream(GUI.PLATFORM_DEFAULT_CONFIG_FILENAME);
if (input != null) {
try {
config.appendConfig(input);
} finally {
input.close();
}
} else {
logger.fatal("Could not find default platform config file1: "
+ GUI.PLATFORM_DEFAULT_CONFIG_FILENAME);
return;
}
// Create default configuration
config = new PlatformConfig(true);
} catch (FileNotFoundException ex) {
logger.fatal("Could not find default platform config file: "
+ GUI.PLATFORM_DEFAULT_CONFIG_FILENAME);
return;
} catch (IOException ex) {
logger.fatal("Error when reading default platform config file: "
+ GUI.PLATFORM_DEFAULT_CONFIG_FILENAME);
@ -245,10 +237,8 @@ public class UserPlatformsDialog extends JDialog {
// Add the fixed platform configurations
if (fixedPlatformsList != null) {
for (String userPlatform : fixedPlatformsList.getItems()) {
File userPlatformConfig = new File(userPlatform + File.separatorChar
+ GUI.PLATFORM_CONFIG_FILENAME);
try {
config.appendConfig(userPlatformConfig);
config.appendUserPlatform(new File(userPlatform));
} catch (Exception ex) {
logger.fatal("Error when merging configurations: " + ex);
return;
@ -258,10 +248,8 @@ public class UserPlatformsDialog extends JDialog {
// Add the user platform configurations
for (String userPlatform : changablePlatformsList.getItems()) {
File userPlatformConfig = new File(userPlatform + File.separatorChar
+ GUI.PLATFORM_CONFIG_FILENAME);
try {
config.appendConfig(userPlatformConfig);
config.appendUserPlatform(new File(userPlatform));
} catch (Exception ex) {
logger.fatal("Error when merging configurations: " + ex);
return;
@ -422,7 +410,10 @@ class ConfigViewer extends JDialog {
String propertyName = allPropertyNames.nextElement();
keyPane.add(new JLabel(propertyName));
valuePane.add(new JLabel(config.getStringValue(propertyName)));
if (config.getStringValue(propertyName).equals(""))
valuePane.add(new JLabel(" "));
else
valuePane.add(new JLabel(config.getStringValue(propertyName)));
}
// Add components