org.openremote.controller.service.impl.FileServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.openremote.controller.service.impl.FileServiceImpl.java

Source

/* OpenRemote, the Home of the Digital Home.
* Copyright 2008-2011, OpenRemote Inc.
*
* See the contributors.txt file in the distribution for a
* full listing of individual contributors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.openremote.controller.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.log4j.Logger;
import org.openremote.controller.ControllerConfiguration;
import org.openremote.controller.Constants;
import org.openremote.controller.exception.BeehiveNotAvailableException;
import org.openremote.controller.exception.ForbiddenException;
import org.openremote.controller.exception.ResourceNotFoundException;
import org.openremote.controller.service.FileService;
import org.openremote.controller.utils.PathUtil;
import org.openremote.controller.utils.ZipUtil;
import org.springframework.security.providers.encoding.Md5PasswordEncoder;

/**
 * The implementation for FileService interface.
 * 
 * @author Dan 2009-5-14
 */
public class FileServiceImpl implements FileService {

    /** The Constant logger. */
    private static final Logger logger = Logger.getLogger(FileServiceImpl.class);

    /** The configuration. */
    private ControllerConfiguration configuration;

    /**
     * {@inheritDoc}
     */
    public boolean unzip(InputStream inputStream, String targetDir) {
        return ZipUtil.unzip(inputStream, targetDir);
    }

    /**
     * {@inheritDoc}
     */
    public boolean uploadConfigZip(InputStream inputStream) {
        String resourcePath = configuration.getResourcePath();
        if (!unzip(inputStream, resourcePath)) {
            return false;
        }
        copyLircdConf(resourcePath);
        return true;
    }

    private void copyLircdConf(String resourcePath) {
        File lircdConfFile = new File(resourcePath + Constants.LIRCD_CONF);
        File lircdconfDir = new File(configuration.getLircdconfPath().replaceAll(Constants.LIRCD_CONF, ""));
        try {
            if (lircdconfDir.exists() && lircdConfFile.exists()) {
                // this needs root user to put lircd.conf into /etc.
                // because it's readonly, or it won't be modified.
                if (configuration.isCopyLircdconf()) {
                    FileUtils.copyFileToDirectory(lircdConfFile, lircdconfDir);
                    logger.info("copy lircd.conf to" + configuration.getLircdconfPath());
                }
            }
        } catch (IOException e) {
            logger.error("Can't copy lircd.conf to " + configuration.getLircdconfPath(), e);
        }
    }

    public boolean writeZipAndUnzip(InputStream inputStream) {
        String resourcePath = configuration.getResourcePath();
        File zip = new File(resourcePath, "openremote.zip");
        FileOutputStream fos = null;
        try {
            if (!zip.getParentFile().exists()) {
                FileUtils.forceMkdir(zip);
            }
            FileUtils.forceDeleteOnExit(zip);
            fos = new FileOutputStream(zip);
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inputStream.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
            if (!ZipUtil.unzip(zip, resourcePath)) {
                return false;
            }
            logger.info("unzip " + zip.getAbsolutePath() + " success.");
            FileUtils.forceDeleteOnExit(zip);
        } catch (IOException e) {
            logger.error("Can't write openremote.zip to " + resourcePath, e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    logger.debug("failed to  close input stream of " + zip.getAbsolutePath());
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    logger.debug("failed to  close file output stream of " + zip.getAbsolutePath());
                }
            }
        }

        copyLircdConf(resourcePath);
        return true;
    }

    /**
     * {@inheritDoc}
     */
    public InputStream findResource(String relativePath) {
        File file = new File(PathUtil.removeSlashSuffix(configuration.getResourcePath()) + relativePath);
        if (file.exists() && file.isFile()) {
            try {
                return new FileInputStream(file);
            } catch (FileNotFoundException e) {
                return null;
            }
        }
        return null;
    }

    /**
     * {@inheritDoc}
     */
    public boolean syncConfigurationWithModeler(String username, String password) {
        return downloadOpenremoteZipFromBeehiveAndUnzip(username, password);
    }

    private boolean downloadOpenremoteZipFromBeehiveAndUnzip(String username, String password) {
        HttpClient httpClient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(PathUtil.addSlashSuffix(configuration.getBeehiveRESTRootUrl()) + "user/"
                + username + "/openremote.zip");

        httpGet.setHeader(Constants.HTTP_AUTHORIZATION_HEADER,
                Constants.HTTP_BASIC_AUTHORIZATION + encode(username, password));
        InputStream inputStream = null;
        try {
            HttpResponse response = httpClient.execute(httpGet);
            if (200 == response.getStatusLine().getStatusCode()) {
                logger.info(httpGet.getURI() + " is available.");
                inputStream = response.getEntity().getContent();
                return writeZipAndUnzip(inputStream);
            } else if (401 == response.getStatusLine().getStatusCode()) {
                throw new ForbiddenException();
            } else if (404 == response.getStatusLine().getStatusCode()) {
                throw new ResourceNotFoundException();
            } else {
                throw new BeehiveNotAvailableException(
                        "failed to download resources for template, The status code is: "
                                + response.getStatusLine().getStatusCode());
            }
        } catch (IOException e) {
            logger.error("failed to connect to Beehive.");
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    logger.error("failed to close input stream while downloading " + httpGet.getURI());
                }
            }
        }
        return false;

    }

    // TODO: The encoding below is very unsafe and can be easily cracked via brute-force and/or rainbow table, please use SHA-512 hash algorithm
    private String encode(String username, String password) {
        Md5PasswordEncoder encoder = new Md5PasswordEncoder();
        String encodedPwd = encoder.encodePassword(password, username);
        if (username == null || encodedPwd == null) {
            return null;
        }
        return new String(Base64.encodeBase64((username + ":" + encodedPwd).getBytes()));
    }

    public void setConfiguration(ControllerConfiguration configuration) {
        this.configuration = configuration;
    }

}