com.frostwire.gui.library.Device.java Source code

Java tutorial

Introduction

Here is the source code for com.frostwire.gui.library.Device.java

Source

/*
 * Created by Angel Leon (@gubatron), Alden Torres (aldenml)
 * Copyright (c) 2011, 2012, FrostWire(TM). All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.frostwire.gui.library;

import java.io.File;
import java.net.InetAddress;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutorService;

import javax.swing.JOptionPane;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.limewire.concurrent.ExecutorsHelper;
import org.limewire.util.NetworkUtils;

import com.frostwire.HttpFetcher;
import com.frostwire.HttpFetcherListener;
import com.frostwire.JsonEngine;
import com.frostwire.core.FileDescriptor;
import com.frostwire.gui.library.ProgressFileEntity.ProgressFileEntityListener;
import com.frostwire.gui.upnp.PingInfo;
import com.frostwire.gui.upnp.UPnPManager;
import com.limegroup.gnutella.gui.GUIMediator;
import com.limegroup.gnutella.gui.I18n;
import com.limegroup.gnutella.util.EncodingUtils;

/**
 * @author gubatron
 * @author aldenml
 * 
 */
public class Device {

    private static final Log LOG = LogFactory.getLog(Device.class);

    private static final ExecutorService executor;

    static {
        //upload files to 3 different devices at the same time.
        executor = ExecutorsHelper.newFixedSizeThreadPool(3, "UploadToDeviceExecutor");
    }

    public static int ACTION_BROWSE = 0;
    public static int ACTION_DOWNLOAD = 1;
    public static int ACTION_UPLOAD = 2;

    private static JsonEngine JSON_ENGINE = new JsonEngine();

    private final String udn;
    private InetAddress _address;
    private int _port;
    private Finger finger;
    private boolean _tokenAuthorized;
    private OnActionFailedListener _listener;
    private long timestamp;

    private PingInfo pingInfo;

    private boolean local;

    public Device(String udn, InetAddress address, int port, Finger finger, PingInfo pinfo) {
        this.udn = udn;
        this._address = address;
        this._port = port;
        this.finger = finger;
        this.pingInfo = pinfo;
        this.local = udn
                .equals(UPnPManager.instance().getLocalDevice().getIdentity().getUdn().getIdentifierString());
    }

    /**
     * aka isMe()
     */
    public boolean isLocal() {
        return local;
    }

    public String getUdn() {
        return udn;
    }

    public InetAddress getAddress() {
        return _address;
    }

    public void setAddress(InetAddress address) {
        _address = address;
    }

    public int getPort() {
        return _port;
    }

    public void setPort(int port) {
        _port = port;
    }

    public Finger getFinger() {
        return finger;
    }

    public void setFinger(Finger finger) {
        this.finger = finger;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(long timestamp) {
        this.timestamp = timestamp;
    }

    public String getName() {
        return finger.nickname;
    }

    public int getTotalShared() {
        return finger.numSharedApplicationFiles + finger.numSharedDocumentFiles + finger.numSharedPictureFiles
                + finger.numSharedVideoFiles + finger.numSharedRingtoneFiles + finger.numSharedAudioFiles;
    }

    public boolean isTokenAuthorized() {
        return _tokenAuthorized;
    }

    public void setTokenAuthorized(boolean authorized) {
        _tokenAuthorized = authorized;
    }

    public OnActionFailedListener getOnActionFailedListener() {
        return _listener;
    }

    public void setOnActionFailedListener(OnActionFailedListener listener) {
        _listener = listener;
    }

    public List<FileDescriptor> browse(byte fileType) {

        try {

            URI uri = new URI("http://" + _address.getHostAddress() + ":" + _port + "/browse?type=" + fileType);

            HttpFetcher fetcher = new HttpFetcher(uri, 10000); // 10 seconds http timeout

            byte[] jsonBytes = (byte[]) fetcher.fetch(true)[0];

            if (jsonBytes == null) {
                notifyOnActionFailed(ACTION_BROWSE, null);
                return new ArrayList<FileDescriptor>();
            }

            setTimestamp(System.currentTimeMillis());

            String json = new String(jsonBytes, "UTF-8");

            FileDescriptorList list = JSON_ENGINE.toObject(json, FileDescriptorList.class);

            return list.files;

        } catch (Exception e) {
            notifyOnActionFailed(ACTION_BROWSE, e);
        }

        return new ArrayList<FileDescriptor>();
    }

    public URL getDownloadURL(int type, int id) {
        try {

            String ip = _address.getHostAddress();

            if (ip.equals("0.0.0.0")) {
                // we need to replace with a real nic address
                ip = NetworkUtils.getLocalAddress().getHostAddress();
            }

            return new URL("http://" + ip + ":" + _port + "/download?type=" + type + "&id=" + id);

        } catch (Exception e) {
            notifyOnActionFailed(ACTION_DOWNLOAD, e);
        }

        return null;
    }

    public String getDownloadURL(FileDescriptor fd) {
        return getDownloadURL(fd.fileType, fd.id).toString();
    }

    public int getDeviceType() {
        return pingInfo.deviceMajorType;
    }

    public byte[] download(int type, int id) {

        try {

            URI uri = getDownloadURL(type, id).toURI();

            HttpFetcher fetcher = new HttpFetcher(uri);

            byte[] data = fetcher.fetch();

            if (data == null) {
                notifyOnActionFailed(ACTION_DOWNLOAD, null);
                return null;
            }

            setTimestamp(System.currentTimeMillis());

            return data;

        } catch (Exception e) {
            notifyOnActionFailed(ACTION_DOWNLOAD, e);
        }

        return null;
    }

    public void upload(File[] files) {
        try {
            final DesktopUploadRequest dur = new DesktopUploadRequest();

            dur.address = NetworkUtils.getLocalAddress().getHostAddress();
            dur.computerName = NetworkUtils.getLocalAddress().getHostName();
            dur.files = new ArrayList<FileDescriptor>();

            for (File f : flatFiles(files)) {
                for (File cf : getFiles(f, 3)) {
                    FileDescriptor fd = new FileDescriptor();
                    fd.filePath = cf.getAbsolutePath();
                    fd.fileSize = cf.length();

                    dur.files.add(fd);
                }
            }

            HttpFetcher fetcher = new HttpFetcher(
                    "http://" + _address.getHostAddress() + ":" + _port + "/dekstop-upload-request", 60000);

            String json = new JsonEngine().toJson(dur);

            final DeviceUploadDialog dlg = new DeviceUploadDialog(GUIMediator.getAppFrame());

            fetcher.asyncPostJSON(json, new HttpFetcherListener() {

                @Override
                public void onSuccess(final byte[] body) {
                    GUIMediator.safeInvokeAndWait(new Runnable() {
                        @Override
                        public void run() {
                            if (dlg.isVisible()) {
                                dlg.setVisible(false);
                                try {
                                    String token = new String(body, "UTF-8");

                                    executor.execute(new DeviceUploadTask(Device.this,
                                            dur.files.toArray(new FileDescriptor[0]), token));
                                } catch (Throwable e) {
                                    LOG.error("Error uploading files to device", e);
                                }
                            }
                        }
                    });
                }

                @Override
                public void onError(Throwable e) {
                    GUIMediator.safeInvokeLater(new Runnable() {
                        @Override
                        public void run() {
                            if (dlg.isVisible()) {
                                dlg.setVisible(false);
                                JOptionPane.showMessageDialog(GUIMediator.getAppFrame(), I18n.tr(
                                        "The device is busy with another transfer or did not authorize your request"),
                                        I18n.tr("Transfer failed"), JOptionPane.INFORMATION_MESSAGE);
                            }
                        }
                    });
                }
            });

            dlg.setVisible(true);

        } catch (Throwable e) {
            LOG.error("Error uploading files to device", e);
        }
    }

    public void upload(File file, String token, ProgressFileEntityListener listener) {

        URI uri = null;

        try {
            uri = new URI("http://" + _address.getHostAddress() + ":" + _port + "/desktop-upload?filePath="
                    + EncodingUtils.encode(file.getAbsolutePath()) + "&token=" + EncodingUtils.encode(token));

            HttpFetcher fetcher = new HttpFetcher(uri);

            ProgressFileEntity fileEntity = new ProgressFileEntity(file);
            fileEntity.setProgressFileEntityListener(listener);

            fetcher.post(fileEntity);

        } catch (Exception e) {
            notifyOnActionFailed(ACTION_UPLOAD, e);
            throw new RuntimeException(e);
        }
    }

    @Override
    public int hashCode() {
        return udn.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null || !(obj instanceof Device)) {
            return false;
        }

        return hashCode() == ((Device) obj).hashCode();
    }

    @Override
    public String toString() {
        return _address + ":" + _port + ", " + finger;
    }

    protected void notifyOnActionFailed(int action, Exception e) {
        if (_listener != null) {
            _listener.onActionFailed(this, action, e);
        }
    }

    public interface OnActionFailedListener {
        public void onActionFailed(Device device, int action, Exception e);
    }

    private static List<File> flatFiles(File[] files) {
        Set<File> set = new HashSet<File>();
        for (File f : files) {
            for (File cf : getFiles(f, 3)) {
                if (!set.contains(cf)) {
                    set.add(cf);
                }
            }
        }

        return new ArrayList<File>(set);
    }

    private static List<File> getFiles(File file, int depth) {
        List<File> files = new ArrayList<File>();

        if (file == null) {
            return files;
        }

        if (!file.isDirectory()) {
            files.add(file);
            return files;
        }

        for (File childFile : file.listFiles()) {
            if (!childFile.isDirectory()) {
                files.add(childFile);
            } else {
                if (depth > 0) {
                    files.addAll(getFiles(childFile, depth - 1));
                }
            }
        }

        return files;
    }
}