123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- package de.tu_darmstadt.tk.SmartHomeNetworkSim.control;
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.FileReader;
- import java.io.IOException;
- import java.net.MalformedURLException;
- import java.net.URL;
- import java.net.URLClassLoader;
- import java.util.LinkedList;
- import javax.tools.JavaCompiler;
- import javax.tools.ToolProvider;
- import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Link;
- import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Model;
- import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Connection;
- import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.ProbabilityDistributionHandler;
- import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.Protocol;
- import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.SmartDevice;
- import de.tu_darmstadt.tk.SmartHomeNetworkSim.core.configuration.ImportConfiguration;
- /**
- * Controller which manages Imported Classes of the framework
- *
- * @author Andreas T. Meyer-Berg
- */
- public class ImportController {
- Model model;
- Controller controller;
- ImportConfiguration importConf;
- /**
- * Creates a new ImportController
- *
- * @param model
- * model to be edited
- * @param controller
- * parent controller
- */
- public ImportController(Model model, Controller controller) {
- this.model = model;
- this.controller = controller;
- this.importConf = controller.getSettingsController().getConfigurationManager().getImportConfiguration();
- }
- /**
- * Adds new Link to the model
- *
- * @param Link
- * Link to be added
- * @return true if it was added
- */
- public boolean addLink(Class<? extends Link> Link) {
- if (isValidLink(Link))
- importConf.addLinkClass(Link);
- else
- return false;
- return true;
- }
- /**
- * Removes Link from the model
- *
- * @param Link
- * Link to be removed
- */
- public void removeLink(Class<? extends Link> Link) {
- importConf.removeLinkClass(Link);
- }
-
- /**
- * Returns the available Links of the model
- *
- * @return available links
- */
- public LinkedList<Class<? extends Link>> getLinks() {
- return importConf.getLinkClasses();
- }
-
- /**
- * Returns true if it is a Valid Link, false if not
- *
- * @param link
- * Link to be checked
- * @return true if it is a valid Link
- */
- public boolean isValidLink(Class<? extends Link> link) {
- try {
- /**
- * Link to be tested
- */
- Link l = link.newInstance();
- // Empty constructor required, to create new instance
- if (l == null)
- throw new Exception("Link required an empty constructor");
- // Name shall not be null or empty string
- if (l.getName() == null || l.getName() == "")
- throw new Exception(
- "Link name shall not be null or empty string.");
- } catch (Exception e) {
- return false;
- }
- return true;
- }
-
- /**
- * Adds new Protocol to the model
- *
- * @param protocol
- * protocol to be added
- * @return true if it was added
- */
- public boolean addProtocol(Class<? extends Protocol> protocol) {
- if (isValidProtocol(protocol))
- importConf.addProtocolClass(protocol);
- else
- return false;
- return true;
-
- }
-
- /**
- * Removes protocol from the model
- *
- * @param protocol
- * protocol to be removed
- */
- public void removeProtocol(Class<? extends Protocol> protocol) {
- importConf.removeProtocolClass(protocol);
- }
-
- /**
- * Returns the available Protocols of the model
- *
- * @return available protocols
- */
- public LinkedList<Class<? extends Protocol>> getProtocols() {
- return importConf.getProtocolClasses();
- }
-
- /**
- * Returns true if it is a Valid Protocol, false if not
- *
- * @param protocol
- * protocol to be checked
- * @return true if it is a valid protocol
- */
- public boolean isValidProtocol(Class<? extends Protocol> protocol) {
- try {
- /**
- * Protocol to be tested
- */
- Protocol p = protocol.newInstance();
- // Empty constructor required, to create new instance
- if (p == null)
- throw new Exception("Protocol required an empty constructor");
- // Name shall not be null or empty string
- if (p.getName() == null || p.getName() == "")
- throw new Exception(
- "Protocol name shall not be null or empty string.");
- if (p.getRoles() == null || p.getRoles().length == 0)
- throw new Exception("Roles shall not be null or empty");
- // Number of roles have to match
- if (p.getNumberOfRoles() != p.getRoles().length)
- throw new Exception(
- "getNumberOfRoles() does not match getRoles().length");
- } catch (Exception e) {
- return false;
- }
- return true;
- }
- /**
- * Adds new Connection to the model
- *
- * @param connection
- * Connection to be added
- * @return true if it was added
- */
- public boolean addConnection(Class<? extends Connection> connection) {
- if (isValidConnection(connection))
- importConf.addConnectionClass(connection);
- else
- return false;
- return true;
-
- }
-
- /**
- * Removes Connection from the model
- *
- * @param connection
- * Connection to be removed
- */
- public void removeConnection(Class<? extends Connection> connection) {
- importConf.removeConnectionClass(connection);
- }
-
- /**
- * Returns the available Connections of the model
- *
- * @return available Connections
- */
- public LinkedList<Class<? extends Connection>> getConnections() {
- return importConf.getConnectionClasses();
- }
-
- /**
- * Returns true if it is a Valid Connection, false if not
- *
- * @param connection
- * Connection to be checked
- * @return true if it is a valid Connection
- */
- public boolean isValidConnection(Class<? extends Connection> connection) {
- try {
- /**
- * Connection to be tested
- */
- Connection p = connection.newInstance();
- // Empty constructor required, to create new instance
- if (p == null)
- throw new Exception("Connection required an empty constructor");
- // Name shall not be null or empty string
- if (p.getName() == null || p.getName() == "")
- throw new Exception(
- "Connection name shall not be null or empty string.");
- } catch (Exception e) {
- return false;
- }
- return true;
- }
-
- /**
- * Adds new SmartDevice to the model
- *
- * @param smartDevice
- * SmartDevice to be added
- * @return true if it was added
- */
- public boolean addSmartDevice(Class<? extends SmartDevice> smartDevice) {
- if (isValidSmartDevice(smartDevice))
- importConf.addSmartDeviceClass(smartDevice);
- else
- return false;
- return true;
-
- }
-
- /**
- * Removes SmartDevice from the model
- *
- * @param smartDevice
- * SmartDevice to be removed
- */
- public void removeSmartDevice(Class<? extends SmartDevice> smartDevice) {
- importConf.removeSmartDeviceClass(smartDevice);
- }
-
- /**
- * Returns the available SmartDevices of the model
- *
- * @return available SmartDevices
- */
- public LinkedList<Class<? extends SmartDevice>> getSmartDevices() {
- return importConf.getSmartDeviceClasses();
- }
-
- /**
- * Returns true if it is a Valid SmartDevice, false if not
- *
- * @param smartDevice
- * SmartDevice to be checked
- * @return true if it is a valid SmartDevice
- */
- public boolean isValidSmartDevice(Class<? extends SmartDevice> smartDevice) {
- try {
- /**
- * SmartDevice to be tested
- */
- SmartDevice p = smartDevice.newInstance();
- // Empty constructor required, to create new instance
- if (p == null)
- throw new Exception("SmartDevice required an empty constructor");
- // Name shall not be null or empty string
- if (p.getName() == null || p.getName() == "")
- throw new Exception(
- "SmartDevice name shall not be null or empty string.");
- } catch (Exception e) {
- return false;
- }
- return true;
- }
-
- /**
- * Adds new DistributionHandler to the model
- *
- * @param distributionHandler DistributionHandler to be added
- * @return true if it was added
- */
- public boolean addDistributionHandler(Class<? extends ProbabilityDistributionHandler> distributionHandler) {
- if (isValidDistributionHandler(distributionHandler))
- importConf.addDistributionHandlerClass(distributionHandler);
- else
- return false;
- return true;
-
- }
-
- /**
- * Removes DistributionHandler from the model
- *
- * @param distributionHandler
- * DistributionHandler to be removed
- */
- public void removeDistributionHandler(Class<? extends ProbabilityDistributionHandler> distributionHandler) {
- importConf.removeDistributionHandlerClass(distributionHandler);
- }
-
- /**
- * Returns the available DistributionHandler of the model
- *
- * @return available DistributionHandler
- */
- public LinkedList<Class<? extends ProbabilityDistributionHandler>> getDistributionHandlers() {
- return importConf.getDistributionHandlerClasses();
- }
-
- /**
- * Returns true if it is a Valid DistributionHandler, false if not
- *
- * @param distributionHandler
- * DistributionHandler to be checked
- * @return true if it is a valid DistributionHandler
- */
- public boolean isValidDistributionHandler(Class<? extends ProbabilityDistributionHandler> distributionHandler) {
- try {
- /**
- * SmartDevice to be tested
- */
- ProbabilityDistributionHandler p = distributionHandler.newInstance();
- // Empty constructor required, to create new instance
- if (p == null)
- throw new Exception("DistributionHandler required an empty constructor");
- // Name shall not be null or empty string
- if (p.getSimpleDescription() == null || p.getSimpleDescription() == "")
- throw new Exception(
- "DistributionHandler name shall not be null or empty string.");
- } catch (Exception e) {
- return false;
- }
- return true;
- }
-
- /**
- * Imports the given .java File, compiles it and returns the compiled class
- *
- * @param javaFile File(path)
- * @return Class which was compiled
- * @throws ClassImportException if an problem occurred during import
- */
- public static Class<?> importJavaClass(File javaFile) throws ClassImportException{
- /**
- * Package name
- */
- String packageName = getJavaPackageName(javaFile);
- if (packageName == null) {
- // if package null - try default package
- packageName = "";
- }
-
- /**
- * Name of the Class. File name "ClassName.java"
- */
- String className = javaFile.getName().substring(0,
- javaFile.getName().lastIndexOf('.'));
-
- /**
- * Compiler, to compile the File
- */
- JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
- compiler.run(null, null, null, javaFile.getPath());
-
- /**
- * Root File of the imported Protocol (if the Java File is inside a package)
- */
- File root = javaFile.getParentFile();
- if(!packageName.isEmpty()){
- /**
- * Array of all parent package names e.g. "pack1.pack2.pack3" -> {"pack1","pack2","pack3"}
- */
- String[] packageFolders = packageName.split("\\.");
- if(packageFolders.length<2){
- //A single level
- if(root.getName().compareTo(packageName)!=0){
- throw new ClassImportException("Invalid ParentFolderName: Expected \""+packageName+"\" but was \""+root.getName()+"\"");
- }
- root = root.getParentFile();
- }else{
- for(int i = packageFolders.length-1;i>=0;i--){
- if(root.getName().compareTo(packageFolders[i])!=0){
- throw new ClassImportException("Invalid ParentFolderName at level "+i+": Expected \""+packageFolders[i]+"\" but was \""+root.getName()+"\"");
- }
- root = root.getParentFile();
- }
- }
- }
-
- /**
- * ClassLoader to load the compiled class, given it's root
- */
- URLClassLoader classLoader;
- try {
- classLoader = URLClassLoader
- .newInstance(new URL[] { root.toURI().toURL() });
- } catch (MalformedURLException e1) {
- throw new ClassImportException("Invalid URL/File at the root of the imported Class");
- }
- // If packageName is not empty, and dot is required: e.g. "packagePath.ClassName"
- if (!packageName.isEmpty())
- packageName += ".";
-
- /**
- * Imported Class
- */
- Class<?> cls = null;
- try{
- cls = Class.forName(packageName + className, true, classLoader);
- }catch(ClassNotFoundException e){
- try{
- //Second try to load class
- cls = classLoader.loadClass(packageName + className);
- }catch(ClassNotFoundException e2){
- throw new ClassImportException("Class not found: "+packageName+className);
- }
- }
- return cls;
- }
-
- /**
- * Returns the package path of a given Java File. Returns null if the
- * exception occurred and returns an empty string if no package declaration
- * was found. Package declaration should be in a single line.
- *
- * @param javaFile
- * File to be searched for the package path
- * @return PackagePath of the JavaFile, EmptyString, if no declaration was
- * found, null on errors
- */
- public static String getJavaPackageName(File javaFile) {
- /**
- * If javaFile null / non existent -> return null
- */
- if(javaFile==null||!javaFile.exists())
- return null;
-
- /**
- * Package name
- */
- String packageName = "";
-
- /**
- * Reader to read the java File
- */
- BufferedReader reader = null;
- try {
- reader = new BufferedReader(new FileReader(javaFile.getPath()));
- /**
- * Current Line which is investigated
- */
- String currentLine = reader.readLine();
- // Search each line until a valid package is found
- while (currentLine != null) {
- currentLine = currentLine.trim();
- if (!currentLine.isEmpty()) {
- //Check if line begins with package
- if (currentLine.length() >= 7 && currentLine.startsWith("package")) {
- packageName = currentLine.substring(8, currentLine.length() - 1);
- }
- }
- if (packageName.isEmpty()) {
- currentLine = reader.readLine();
- } else {
- currentLine = null;
- }
- }
- } catch (Exception e) {
- return null;
- } finally {
- try {
- if(reader != null)
- reader.close();
- } catch (IOException e) {
- }
- }
- // Remove whitespace in cases like "import test.package ;"
- packageName = packageName.trim();
- return packageName;
- }
-
- }
|