org.n52.wps.webadmin.ConfigUploadBean.java Source code

Java tutorial

Introduction

Here is the source code for org.n52.wps.webadmin.ConfigUploadBean.java

Source

/**
 * Copyright (C) 2007 - 2014 52North Initiative for Geospatial Open Source
 * Software GmbH
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 *
 * If the program is linked with libraries which are licensed under one of
 * the following licenses, the combination of the program with the linked
 * library is not considered a "derivative work" of the program:
 *
 *        Apache License, version 2.0
 *        Apache Software License, version 1.0
 *        GNU Lesser General Public License, version 3
 *        Mozilla Public License, versions 1.0, 1.1 and 2.0
 *        Common Development and Distribution License (CDDL), version 1.0
 *
 * Therefore the distribution of the program linked with libraries licensed
 * under the aforementioned licenses, is permitted by the copyright holders
 * if the distribution is compliant with both the GNU General Public
 * License version 2 and the aforementioned licenses.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 * Public License for more details.
 */
package org.n52.wps.webadmin;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

import org.apache.commons.lang.SystemUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.n52.wps.PropertyDocument.Property;
import org.n52.wps.commons.WPSConfig;

/**
 * This Bean handles the fileupload of the xml configuration file
 * 
 * @author Florian van Keulen
 */
public class ConfigUploadBean {
    private static transient Logger LOGGER = LoggerFactory.getLogger(ConfigUploadBean.class);

    private String savePath, filepath, filename, xmlFilepath, xmlFilename, realSavePath, boundary;

    private final String filenamePrefix = "userConf_";

    private int i, boundaryLength;

    private byte[] line;

    public String getFilenamePrefix() {
        return filenamePrefix;
    }

    private void setFilename(String s) {
        if (s == null) {
            return;
        }

        int pos = s.indexOf("filename=\"");
        if (pos != -1) {
            filepath = s.substring(pos + 10, s.length() - 1);
            // Windows browsers include the full path on the client
            // But Linux/Unix and Mac browsers only send the filename
            // test if this is from a Windows browser
            pos = filepath.lastIndexOf("\\");
            if (pos != -1) {
                filename = filepath.substring(pos + 1);
            } else {
                filename = filepath;
            }
        }
    }

    private void setXMLFilename(String s) {
        if (s == null) {
            return;
        }

        int pos = s.indexOf("filename=\"");
        if (pos != -1) {
            xmlFilepath = s.substring(pos + 10, s.length() - 1);
            // Windows browsers include the full path on the client
            // But Linux/Unix and Mac browsers only send the filename
            // test if this is from a Windows browser
            pos = xmlFilepath.lastIndexOf("\\");
            if (pos != -1) {
                xmlFilename = xmlFilepath.substring(pos + 1);
            } else {
                xmlFilename = xmlFilepath;
            }
        }
    }

    public void doUpload(HttpServletRequest request) throws IOException {
        savePath = WPSConfig.getConfigPath();
        // get rid of the filename
        // How is the path on a windows machine? may be better using:
        // savePath = savePath.substring(0, savePath.length() -
        // "wps_config.xml".length());
        savePath = savePath.substring(0, savePath.lastIndexOf(File.separator) + 1);
        ServletInputStream in = request.getInputStream();

        line = new byte[128];
        i = in.readLine(line, 0, 128);
        if (i < 3) {
            return;
        }
        boundaryLength = i - 2;

        int classnameupcoming = 4;

        boundary = new String(line, 0, boundaryLength); // -2 discards
        // the newline
        // character

        /*
         * the type of the uploaded file until now only processes (.java/.zip)
         * or R scripts are supported
         */
        String type = "";

        String realSavePath = "";
        while (i != -1) {
            String newLine = new String(line, 0, i);
            System.out.println(newLine);
            if (newLine.contains("processName")) {
                type = "javaProcess";
                // we set a flag to know that the next string is the fully
                // qualified classname
                classnameupcoming--;
            } else if (newLine.contains("rProcessName")) {
                type = "rScript";
                // we set a flag to know that the next string is the fully
                // qualified classname
                classnameupcoming--;

            }
            if (classnameupcoming < 4) {
                classnameupcoming--;
            }
            if (classnameupcoming == 0) {
                // // then parse classname
                // String classname = newLine;
                // String[] classnameArr = classname.replace(".",
                // ",").split(",");
                // String classdir = new String();
                // for (int c = 0; c < classnameArr.length - 1; c++) {
                // if (c == 0) {
                // classdir = classdir + classnameArr[c];
                // } else {
                // classdir = classdir + File.separator + classnameArr[c];
                // }
                //
                // }
                // realSavePath = new File(savePath).getParentFile()
                // + "/WEB-INF/classes/";
                // realSavePath = realSavePath + classdir + File.separator;
                // new File(realSavePath).mkdirs();

                try {
                    handleUpload(in, type, newLine);
                    break;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            if (newLine.startsWith("Content-Disposition: form-data; name=\"")) {
                if (newLine.contains("processDescriptionFile")) {
                    if (newLine.indexOf("filename=\"") != -1) {
                        setXMLFilename(new String(line, 0, i - 2));
                        if (xmlFilename == null) {
                            return;
                        }

                        if (!xmlFilename.equals("")) {

                            // this is the file content
                            i = in.readLine(line, 0, 128);
                            // next line
                            i = in.readLine(line, 0, 128);
                            // blank line
                            i = in.readLine(line, 0, 128);
                            newLine = new String(line, 0, i);
                            // add the prefix to the filename

                            PrintWriter pw = null;
                            if (realSavePath.length() > 0) {
                                pw = new PrintWriter(new BufferedWriter(
                                        new FileWriter((realSavePath == null ? "" : realSavePath) + xmlFilename)));
                            } else {
                                xmlFilename = filenamePrefix + xmlFilename;
                                pw = new PrintWriter(new BufferedWriter(
                                        new FileWriter((savePath == null ? "" : savePath) + filename)));
                            }

                            while (i != -1 && !newLine.startsWith(boundary)) {
                                // the problem is the last line of the file
                                // content
                                // contains the new line character.
                                // So, we need to check if the current line is
                                // the last line.
                                i = in.readLine(line, 0, 128);
                                if ((i == boundaryLength + 2 || i == boundaryLength + 4) // +
                                        // 4
                                        // is
                                        // eof
                                        && (new String(line, 0, i).startsWith(boundary))) {

                                    pw.print(newLine.substring(0, newLine.length() - 2));
                                } else {
                                    pw.print(newLine);
                                }

                                newLine = new String(line, 0, i);
                            }
                            pw.close();
                        }

                    }

                }

                if (newLine.contains("processFile")) {
                    // we upload files not config docuemnts. Therefore store is
                    // somewhere else.
                    // realSavePath = new
                    // File(savePath).getParentFile().getAbsolutePath()+"/WEB-INF/classes/";

                    /**
                     * TODO: dir structure according to fully qual classname
                     */

                    if (newLine.indexOf("filename=\"") != -1) {
                        setFilename(new String(line, 0, i - 2));
                        if (filename == null) {
                            return;
                        }

                        // this is the file content
                        i = in.readLine(line, 0, 128);
                        // next line
                        i = in.readLine(line, 0, 128);
                        // blank line
                        i = in.readLine(line, 0, 128);
                        newLine = new String(line, 0, i);
                        // add the prefix to the filename

                        PrintWriter pw = null;
                        if (realSavePath.length() > 0) {
                            pw = new PrintWriter(new BufferedWriter(
                                    new FileWriter((realSavePath == null ? "" : realSavePath) + filename)));
                        } else {
                            filename = filenamePrefix + filename;
                            pw = new PrintWriter(new BufferedWriter(
                                    new FileWriter((savePath == null ? "" : savePath) + filename)));
                        }

                        while (i != -1 && !newLine.startsWith(boundary)) {
                            // the problem is the last line of the file content
                            // contains the new line character.
                            // So, we need to check if the current line is
                            // the last line.
                            i = in.readLine(line, 0, 128);
                            if ((i == boundaryLength + 2 || i == boundaryLength + 4) // +
                                    // 4
                                    // is
                                    // eof
                                    && (new String(line, 0, i).startsWith(boundary))) {

                                pw.print(newLine.substring(0, newLine.length() - 2));
                            } else {
                                pw.print(newLine);
                            }

                            newLine = new String(line, 0, i);
                        }
                        pw.close();

                    }

                }

            }

            i = in.readLine(line, 0, 128);
        } // end while
          // if (realSavePath.length() > 0) {
          // LOGGER.info("User Configuration file received and saved at: "
          // + realSavePath + filename);
          // } else {
          // LOGGER.info("User Configuration file received and saved at: "
          // + savePath + filename);
          // }
    }

    private void handleUpload(ServletInputStream in, String type, String newLine) throws Exception {

        if (type.equals("javaProcess")) {

            // then parse classname
            String classname = newLine;
            String[] classnameArr = classname.replace(".", ",").split(",");
            String classdir = new String();
            for (int c = 0; c < classnameArr.length - 1; c++) {
                if (c == 0) {
                    classdir = classdir + classnameArr[c];
                } else {
                    classdir = classdir + File.separator + classnameArr[c];
                }

            }
            realSavePath = new File(savePath).getParentFile() + "/WEB-INF/classes/";
            realSavePath = realSavePath + classdir + File.separator;
            new File(realSavePath).mkdirs();

            while (i != -1) {

                newLine = new String(line, 0, i);
                System.out.println(newLine);

                if (newLine.startsWith("Content-Disposition: form-data; name=\"")) {
                    if (newLine.contains("processFile")) {
                        // we upload files not config docuements. Therefore
                        // store is
                        // somewhere else.
                        // realSavePath = new
                        // File(savePath).getParentFile().getAbsolutePath()+"/WEB-INF/classes/";

                        /**
                         * TODO: dir structure according to fully qual classname
                         */

                        if (newLine.indexOf("filename=\"") != -1) {
                            setFilename(new String(line, 0, i - 2));
                            if (filename == null) {
                                return;
                            }

                            // this is the file content
                            i = in.readLine(line, 0, 128);
                            // next line
                            i = in.readLine(line, 0, 128);
                            // blank line
                            i = in.readLine(line, 0, 128);
                            newLine = new String(line, 0, i);
                            // add the prefix to the filename

                            PrintWriter pw = null;
                            if (realSavePath.length() > 0) {
                                pw = new PrintWriter(new BufferedWriter(
                                        new FileWriter((realSavePath == null ? "" : realSavePath) + filename)));
                            } else {
                                filename = filenamePrefix + filename;
                                pw = new PrintWriter(new BufferedWriter(
                                        new FileWriter((savePath == null ? "" : savePath) + filename)));
                            }

                            while (i != -1 && !newLine.startsWith(boundary)) {
                                // the problem is the last line of the file
                                // content
                                // contains the new line character.
                                // So, we need to check if the current line is
                                // the last line.
                                i = in.readLine(line, 0, 128);
                                if ((i == boundaryLength + 2 || i == boundaryLength + 4) // +
                                        // 4
                                        // is
                                        // eof
                                        && (new String(line, 0, i).startsWith(boundary))) {

                                    pw.print(newLine.substring(0, newLine.length() - 2));
                                } else {
                                    pw.print(newLine);
                                }

                                newLine = new String(line, 0, i);
                            }
                            pw.close();
                        }

                    }

                }

                i = in.readLine(line, 0, 128);
            } // end while
            if (realSavePath.length() > 0) {
                LOGGER.info("User Configuration file received and saved at: " + realSavePath + filename);
            } else {
                LOGGER.info("User Configuration file received and saved at: " + savePath + filename);
            }
            if (realSavePath.length() > 0) {
                compile(realSavePath + filename);
            }

        } else if (type.equals("rScript")) {
            // if processName the filename is used as ID, otherwise the script will be
            // renamed because r process IDs are derived from the filenames
            String processName = newLine.trim();

            /*
             * FIXME This is very dirty. Changed from staticly referencing the
             * 52n-wps-r module (!!) to generic string property resolving.
             * Nevertheless, this is sort of hard-coded. The webadmin module
             * should be completely separated from others.
             */
            String scriptDir = "";
            Property[] rConfig = WPSConfig.getInstance()
                    .getPropertiesForRepositoryClass("org.n52.wps.server.r.LocalRAlgorithmRepository");
            for (Property property : rConfig) {
                if (property.getName().equalsIgnoreCase("R_scriptDirectory")) {
                    scriptDir = property.getStringValue();
                }
            }

            File basedir = new File(savePath).getParentFile();
            realSavePath = new File(basedir, scriptDir).getAbsolutePath() + File.separator;
            new File(realSavePath).mkdirs();

            while (i != -1) {

                newLine = new String(line, 0, i);
                System.out.println(newLine);

                if (newLine.startsWith("Content-Disposition: form-data; name=\"")) {
                    if (newLine.contains("rProcessFile")) {

                        if (newLine.indexOf("filename=\"") != -1) {

                            // filename is either the process name or the
                            // original file name
                            if (processName != null && !processName.isEmpty()) {
                                filename = processName + ".R";
                            } else
                                setFilename(new String(line, 0, i - 2));

                            if (filename == null) {
                                return;
                            }

                            // this is the file content
                            i = in.readLine(line, 0, 128);
                            // next line
                            i = in.readLine(line, 0, 128);
                            // blank line
                            i = in.readLine(line, 0, 128);
                            newLine = new String(line, 0, i);
                            // add the prefix to the filename

                            PrintWriter pw = null;
                            File destFile = null;
                            if (realSavePath.length() > 0) {
                                destFile = new File((realSavePath == null ? "" : realSavePath) + filename);
                                pw = new PrintWriter(new BufferedWriter(new FileWriter(destFile)));
                            } else {
                                filename = filenamePrefix + filename;
                                destFile = new File((savePath == null ? "" : savePath) + filename);
                                pw = new PrintWriter(new BufferedWriter(new FileWriter(destFile)));
                            }

                            while (i != -1 && !newLine.startsWith(boundary)) {
                                // the problem is the last line of the file
                                // content
                                // contains the new line character.
                                // So, we need to check if the current line is
                                // the last line.
                                i = in.readLine(line, 0, 128);
                                if ((i == boundaryLength + 2 || i == boundaryLength + 4) // +
                                        // 4
                                        // is
                                        // eof
                                        && (new String(line, 0, i).startsWith(boundary))) {

                                    pw.print(newLine.substring(0, newLine.length() - 2));
                                } else {
                                    pw.print(newLine);
                                }

                                newLine = new String(line, 0, i);
                            }
                            pw.close();

                        }

                        /*
                         * FIXME This is very dirty. The webadmin module should
                         * be completely separated from others. This one points
                         * out the need for a generic
                         * "reload your configuration" convenience method.
                         * Changed to java Reflections to remove the static
                         * 52n-wps-r module reference (though, very hardcoded).
                         */
                        {
                            LOGGER.info("R script uploaded, call to RPropertyChangeManager");
                            Class<?> clazz = Class.forName("org.n52.wps.server.r.RPropertyChangeManager");
                            Method method = clazz.getMethod("getInstance", null);
                            Object instance = method.invoke(null, null);
                            Method method2 = instance.getClass().getMethod("updateRepositoryConfiguration", null);
                            method2.invoke(instance, null);
                            // RPropertyChangeManager rmanager =
                            // RPropertyChangeManager.getInstance();
                            // LOGGER.info("R script uploaded, call to RPropertyChangeManager");
                            // rmanager.addUnregisteredScripts();
                        }

                    }

                }

                i = in.readLine(line, 0, 128);
            } // end while
            if (realSavePath.length() > 0) {
                LOGGER.info("User Configuration file received and saved at: " + realSavePath + filename);
            } else {
                LOGGER.info("User Configuration file received and saved at: " + savePath + filename);
            }
            if (realSavePath.length() > 0) {
            }
        }

    }

    public void compile(String fileName) {
        ClassLoader cl = this.getClass().getClassLoader();
        List<URL> classpath = new ArrayList<URL>();
        if (cl instanceof URLClassLoader) {
            URLClassLoader cl2 = (URLClassLoader) cl;
            for (URL jar : cl2.getURLs()) {
                classpath.add(jar);
            }
        }
        String classPath = System.getProperty("java.class.path");
        for (String path : classPath.split(File.pathSeparator)) {
            try {
                classpath.add(new URL("file:" + path));
            } catch (MalformedURLException e) {
                System.err.println("Wrong url: " + e.getMessage());
                e.printStackTrace();
            }
        }

        StringBuffer sb = new StringBuffer();
        for (URL jar : classpath) {
            if (SystemUtils.IS_OS_WINDOWS == false) {
                sb.append(jar.getPath());
                sb.append(File.pathSeparatorChar);
            } else {
                sb.append(jar.getPath().substring(1));
                sb.append(File.pathSeparatorChar);
            }
        }
        String ops[] = new String[] { "-classpath", sb.toString() };

        List<String> opsIter = new ArrayList<String>();
        try {
            for (String s : ops) {
                // XXX test usage, removed use of deprecated method
                // ((ArrayList) opsIter).add(URLDecoder.decode(s));
                ((ArrayList) opsIter).add(URLDecoder.decode(s, Charset.forName("UTF-8").toString()));
            }
        } catch (UnsupportedEncodingException e) {
            LOGGER.warn(e.getMessage(), e);
        }

        File[] files1 = new File[1];
        files1[0] = new File(fileName);

        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);

        Iterable<? extends JavaFileObject> compilationUnits1 = fileManager
                .getJavaFileObjectsFromFiles(Arrays.asList(files1));

        compiler.getTask(null, fileManager, null, opsIter, null, compilationUnits1).call();

        try {
            fileManager.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}