Package de.metalcon.server.statusupdates

Source Code of de.metalcon.server.statusupdates.StatusUpdateManager

package de.metalcon.server.statusupdates;

import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Map;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import javax.xml.parsers.ParserConfigurationException;

import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Transaction;
import org.neo4j.kernel.AbstractGraphDatabase;
import org.xml.sax.SAXException;

import de.metalcon.server.exceptions.StatusUpdateInstantiationFailedException;
import de.metalcon.socialgraph.Configuration;
import de.metalcon.socialgraph.NeoUtils;
import de.metalcon.socialgraph.SocialGraphRelationshipType;
import de.metalcon.utils.FormItemList;

/**
* status update manager to load
*
* @author Sebastian Schlicht
*
*/
public class StatusUpdateManager {

  /**
   * status update templates loaded
   */
  private static Map<String, StatusUpdateTemplate> STATUS_UPDATE_TYPES = new HashMap<String, StatusUpdateTemplate>();

  /**
   * working directory for template generation
   */
  private static String WORKING_DIR;

  /**
   * load all XML files listed in the directory specified
   *
   * @param directory
   *            status update templates directory
   * @return array of status update templates (XML files)
   */
  private static File[] loadXmlFiles(final File directory) {
    return directory.listFiles(new FileFilter() {

      @Override
      public boolean accept(File file) {
        return file.getName().endsWith(".xml");
      }

    });
  }

  /**
   * generate a java class file for the template specified
   *
   * @param template
   *            status update template
   * @param workingPath
   *            working path including JAVA and/or CLASS-files
   * @throws FileNotFoundException
   */
  private static void generateJavaFiles(final StatusUpdateTemplate template,
      final String workingPath) throws FileNotFoundException {
    final String javaPath = WORKING_DIR + template.getName() + ".java";
    final File javaFile = new File(javaPath);
    final String[] optionsAndSources = { "-classpath", workingPath,
        "-proc:none", "-source", "1.7", "-target", "1.7", javaPath };

    // write java file
    final PrintWriter writer = new PrintWriter(javaFile);
    writer.write(template.getJavaCode());
    writer.flush();
    writer.close();

    // delete previous class file
    final File classFile = new File(WORKING_DIR + template.getName()
        + ".class");
    classFile.delete();

    // compile java file to class file
    final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    compiler.run(System.in, System.out, System.err, optionsAndSources);

    // delete java file
    javaFile.delete();
  }

  /**
   * store the status update template linking to the latest previous version
   *
   * @param graphDatabase
   *            social graph database to store the template in
   * @param template
   *            status update template
   * @param previousTemplateNode
   *            template node of the latest previous version
   */
  private static void storeStatusUpdateTemplate(
      final AbstractGraphDatabase graphDatabase,
      final StatusUpdateTemplate template, final Node previousTemplateNode) {
    final Transaction transaction = graphDatabase.beginTx();
    try {
      // create template node
      final Node templateNode = StatusUpdateTemplate.createTemplateNode(
          graphDatabase, template);

      // link to the latest previous version
      if (previousTemplateNode != null) {
        templateNode.createRelationshipTo(previousTemplateNode,
            SocialGraphRelationshipType.Templates.PREVIOUS);
      }

      // store the template node
      NeoUtils.storeStatusUpdateTemplateNode(graphDatabase,
          template.getName(), templateNode, previousTemplateNode);

      transaction.success();
    } finally {
      transaction.finish();
    }
  }

  /**
   * load the status update allowed
   *
   * @param rootDir
   *            classes directory parent
   * @param config
   *            Graphity configuration
   * @param graphDatabase
   *            graph database to store status update version control
   * @throws IOException
   *             - IO error
   * @throws SAXException
   *             - parse error
   * @throws ParserConfigurationException
   *             - DocumentBuilder cannot match the current configuration
   */
  public static void loadStatusUpdateTemplates(final String rootDir,
      final Configuration config,
      final AbstractGraphDatabase graphDatabase)
      throws ParserConfigurationException, SAXException, IOException {
    // set working directory
    final String workingPath = rootDir + "classes/";
    final String targetPackage = StatusUpdate.class.getPackage().getName()
        + ".templates.";
    WORKING_DIR = workingPath + targetPackage.replace(".", "/");
    final File dirWorking = new File(WORKING_DIR);
    if (!dirWorking.exists()) {
      dirWorking.mkdir();
    }
    System.out.println("WORKING_DIR:" + WORKING_DIR);

    // create class loader
    final ClassLoader classLoader = StatusUpdate.class.getClassLoader();
    final URLClassLoader loader = new URLClassLoader(new URL[] { new File(
        workingPath).toURI().toURL() }, classLoader);

    // crawl XML files
    StatusUpdateTemplate template, previousTemplate;
    final File templatesDir = new File(config.getTemplatesPath());
    if (!templatesDir.exists()) {
      templatesDir.mkdir();
    }
    File[] xmlFiles = loadXmlFiles(templatesDir);

    // create basic status update template
    if (xmlFiles.length == 0) {
      final File plainTemplate = new File(config.getTemplatesPath()
          + "Plain.xml");
      final PrintWriter writer = new PrintWriter(plainTemplate);
      writer.println("<class name=\"Plain\" version=\"1.0\">");
      writer.println("<param name=\"message\" type=\"String\" />");
      writer.println("</class>");
      writer.flush();
      writer.close();
      xmlFiles = loadXmlFiles(new File(config.getTemplatesPath()));
    }

    System.out.println("TEMPLATES:" + xmlFiles.length);
    for (File xmlFile : xmlFiles) {
      template = new StatusUpdateTemplate(xmlFile);
      final Node previousTemplateNode = NeoUtils
          .getStatusUpdateTemplateByIdentifier(template.getName());

      if (previousTemplateNode != null) {
        previousTemplate = new StatusUpdateTemplate(
            previousTemplateNode);
      } else {
        previousTemplate = null;
      }

      // check for previous template versions
      if (previousTemplate != null) {
        if (!template.getVersion()
            .equals(previousTemplate.getVersion())) {
          // TODO: ask which template shall be used, for the moment
          // overwrite previous versions
        }
      }

      // store the new template
      storeStatusUpdateTemplate(graphDatabase, template,
          previousTemplateNode);

      // generate class file
      generateJavaFiles(template, workingPath);

      // register the new template
      try {
        template.setInstantiationClass(loader.loadClass(targetPackage
            + template.getName()));
        STATUS_UPDATE_TYPES.put(template.getName(), template);
      } catch (final ClassNotFoundException e) {
        e.printStackTrace();
      }
    }

    loader.close();
  }

  /**
   * get the status update template with the name passed
   *
   * @param templateName
   *            name of status update template being searched
   * @return status update template<br>
   *         <b>null</b> if there is no template with such name
   */
  public static StatusUpdateTemplate getStatusUpdateTemplate(
      final String templateName) {
    return STATUS_UPDATE_TYPES.get(templateName);
  }

  /**
   * instantiate a status update
   *
   * @param typeIdentifier
   *            status update type identifier
   * @param values
   *            form item list containing all status update items necessary
   * @return status update instance of type specified
   * @throws StatusUpdateInstantiationFailedException
   *             if the status update could not be instantiated with the
   *             parameters passed
   * @throws IllegalArgumentException
   *             if template internal errors occur
   */
  public static StatusUpdate instantiateStatusUpdate(
      final String typeIdentifier, final FormItemList values)
      throws StatusUpdateInstantiationFailedException {
    final StatusUpdateTemplate template = getStatusUpdateTemplate(typeIdentifier);
    final Class<?> templateInstantiationClass = template
        .getInstantiationClass();

    try {
      // instantiate status update
      final StatusUpdate statusUpdate = (StatusUpdate) templateInstantiationClass
          .newInstance();

      // set status update fields
      String value;
      try {
        for (String fieldName : template.getFields().keySet()) {
          try {
            value = values.getField(fieldName);
          } catch (final IllegalArgumentException e) {
            throw new StatusUpdateInstantiationFailedException(
                e.getMessage());
          }
          templateInstantiationClass.getField(fieldName).set(
              statusUpdate, value);
        }

        // set status update file paths
        for (String fileName : template.getFiles().keySet()) {
          try {
            value = values.getFile(fileName).getAbsoluteFilePath();
          } catch (final IllegalArgumentException e) {
            throw new StatusUpdateInstantiationFailedException(
                e.getMessage());
          }
          templateInstantiationClass.getField(fileName).set(
              statusUpdate, value);
        }
      } catch (final IllegalArgumentException e) {
        throw new StatusUpdateInstantiationFailedException(
            "The types of the parameters passed do not match the status update template.");
      }

      return statusUpdate;
    } catch (final SecurityException e) {
      throw new IllegalArgumentException(
          "failed to load the status update type specified, SecurityException occurred!");
    } catch (final InstantiationException e) {
      throw new IllegalArgumentException(
          "failed to load the status update type specified, InstantiationException occurred!");
    } catch (final IllegalAccessException e) {
      throw new IllegalArgumentException(
          "failed to load the status update type specified, IllegalAccessException occurred!");
    } catch (final NoSuchFieldException e) {
      throw new IllegalArgumentException(
          "failed to load the status update type specified, NoSuchFieldException occurred!");
    }
  }

}
TOP

Related Classes of de.metalcon.server.statusupdates.StatusUpdateManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.