All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.enterprise.util.cluster.windows.io.WindowsRemoteFile Maven / Gradle / Ivy

There is a newer version: 7.2024.1.Alpha1
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
package com.sun.enterprise.util.cluster.windows.io;

import com.sun.enterprise.util.cluster.windows.process.WindowsCredentials;
import com.sun.enterprise.util.cluster.windows.process.WindowsException;
import java.io.*;
import java.io.FileOutputStream;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import jcifs.smb.SmbFile;

/**
 * @author Byron Nevins
 */
public final class WindowsRemoteFile {
    private SmbFile smbFile;
    private WindowsRemoteFileSystem wrfs;
    private String smbPath;

    public WindowsRemoteFile(WindowsRemoteFile parent, String path)
            throws WindowsException {
        try {
            wrfs = parent.wrfs;
            smbPath = parent.smbPath + removeLeadingAndTrailingSlashes(path) + "/";
            smbFile = new SmbFile(smbPath, wrfs.getAuthorization());
        }
        catch (Exception e) {
            throw new WindowsException(e);
        }
    }

    public WindowsRemoteFile(WindowsCredentials bonafides, String path)
            throws WindowsException {
        this(new WindowsRemoteFileSystem(bonafides), path);
    }

    public WindowsRemoteFile(WindowsRemoteFileSystem wrfs, String path)
            throws WindowsException {
        try {
            if (wrfs == null || path == null || path.isEmpty())
                throw new NullPointerException();

            if (path.indexOf(":") < 0)
                throw new IllegalArgumentException("Non-absolute path.  No colon in the path");

            this.wrfs = wrfs;
            //  this.isDir = isDir;

            // replace backslashes with forward slashes
            // replace drive designator(e:) with the default admin share for the drive (e$)

            path = path.replace('\\', '/').replace(':', '$');

            StringBuilder sb = new StringBuilder("smb://");
            sb.append(wrfs.getHost()).append("/").append(path);

            if (!path.endsWith("/"))
                sb.append('/');

            smbPath = sb.toString();
            //SmbFile remoteRoot = new SmbFile("smb://" + name + "/" + path.replace('\\', '/').replace(':', '$')+"/",createSmbAuth());

            smbFile = new SmbFile(smbPath, wrfs.getAuthorization());
        }
        catch (Exception e) {
            throw new WindowsException(e);
        }
    }

    /**
     * THis returns 3 states:
     * 1. FIle system can't be accessed or found
     * 2. it exists
     * 3. it doesn't exist
     * @return
     * @throws WindowsException
     */
    public final boolean exists() throws WindowsException {
        try {
            return smbFile.exists();
        }
        catch (Exception se) {
            throw new WindowsException(se);
        }
    }

    public final String[] list() throws WindowsException {
        try {
            return smbFile.list();
        }
        catch (Exception se) {
            throw new WindowsException(se);
        }
    }

    public final void createNewFile() throws WindowsException {
        try {
            smbFile.createNewFile();
        }
        catch (Exception se) {
            throw new WindowsException(se);
        }
    }

    public final void copyTo(WindowsRemoteFile wf) throws WindowsException {
        try {
            smbFile.copyTo(wf.smbFile);
        }
        catch (Exception se) {
            throw new WindowsException(se);
        }
    }

    /**
     * Copy the remote Windows file to the given File
     *
     * @param f The File that will be created or overwritten with the contents of
     * this Windows Remote File.
     * @throws WindowsException
     * @since 3.1.2
     */
    public final void copyTo(final File file) throws WindowsException {
        copyTo(file, null);
    }

    /**
     * Copy the remote Windows file to the given File
     *
     * @param f The File that will be created or overwritten with the contents of
     * this Windows Remote File.
     * @param progress The optional callback object that gets called for each
     * chunk of data that gets copied over the wire.  Setting it to null is OK.
     * @throws WindowsException
     * @since 3.1.2
     */
    public final void copyTo(final File file, final RemoteFileCopyProgress progress) throws WindowsException {
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            final long filelength = smbFile.length();
            bis = new BufferedInputStream(smbFile.getInputStream());
            bos = new BufferedOutputStream(new FileOutputStream(file));

            byte[] buf = new byte[getChunkSize(progress, filelength)];
            int numBytes = 0;
            long totalBytesCopied = 0;

            while ((numBytes = bis.read(buf)) >= 0) {
                bos.write(buf, 0, numBytes);
                totalBytesCopied += numBytes;

                // It's OK to send in a null Progress object
                if (progress != null)
                    progress.callback(totalBytesCopied, filelength);
            }
        }
        catch (Exception se) {
            throw new WindowsException(se);
        }
        finally {
            if (bis != null)
                try {
                    bis.close();
                }
                catch (Exception e) {
                    // this is SO messy!
                }
            if (bos != null)
                try {
                    bos.close();
                }
                catch (Exception e) {
                    // this is SO messy!
                }
        }
    }

    public final void delete() throws WindowsException {
        try {
            smbFile.delete();
        }
        catch (Exception se) {
            throw new WindowsException(se);
        }
    }

    public final void mkdirs() throws WindowsException {
        mkdirs(false);
    }

    public final void mkdirs(boolean force) throws WindowsException {
        try {
            if (exists()) {
                if (force)
                    delete();
                else
                    throw new WindowsException(Strings.get("dir.already.exists", getPath()));
            }
            smbFile.mkdirs();
        }
        catch (WindowsException we) {
            throw we;
        }
        catch (Exception se) {
            throw new WindowsException(se);
        }
    }

    /**
     * Copies from sin to this WindowsRemoteFile
     * @param sin the opened stream.  It will automatically be closed here.
     * @throws WindowsException if any errors.
     */
    public final void copyFrom(final BufferedInputStream sin) throws WindowsException {
        copyFrom(sin, null, -1);
    }

    /**
     * If desired -- make this public sometime in the future.  For now there is no
     * reason to clog up the public namespace with it...
     */
    private final void copyFrom(final BufferedInputStream sin,
            final RemoteFileCopyProgress progress, final long filelength)
            throws WindowsException {
        OutputStream sout = null;

        if (sin == null)
            throw new NullPointerException("copyFrom stream arg is null");

        try {
            if (!exists())
                createNewFile();

            sout = new BufferedOutputStream(smbFile.getOutputStream());
            byte[] buf = new byte[getChunkSize(progress, filelength)];
            int numBytes = 0;
            long totalBytesCopied = 0;

            while ((numBytes = sin.read(buf)) >= 0) {
                sout.write(buf, 0, numBytes);
                totalBytesCopied += numBytes;

                // It's OK to send in a null Progress object
                if (progress != null)
                    progress.callback(totalBytesCopied, filelength);
            }
        }
        catch (Exception e) {
            throw new WindowsException(e);
        }
        finally {
            try {
                sin.close();
            }
            catch (Exception e) {
                // nothing can be done!
            }
            try {
                sout.close();
            }
            catch (Exception e) {
                // nothing can be done!
            }
        }
    }

    public final void copyFrom(File from, RemoteFileCopyProgress progress)
            throws WindowsException {

        try {
            if (from == null || !from.isFile())
                throw new IllegalArgumentException("copyFrom file arg is bad: " + from);

            long filesize = from.length();
            BufferedInputStream sin = new BufferedInputStream(new FileInputStream(from));
            copyFrom(sin, progress, filesize);
        }
        catch (WindowsException e) {
            throw e;
        }
        catch (Exception e) {
            throw new WindowsException(e);
        }
    }

    /*
     * Use this for tiny files -- like scripts that are created on-the-fly from a String
     */
    public final void copyFrom(Collection from) throws WindowsException {
        if (from == null || from.isEmpty())
            throw new IllegalArgumentException("copyFrom String-array arg is empty");

        StringBuilder sb = new StringBuilder();

        for (String s : from) {
            // since we will write with a writer -- the \n will get translated correctly
            sb.append(s).append('\n');
        }
        copyFrom(sb.toString());
    }
    /*
     * Use this for tiny files -- like scripts that are created on-the-fly from a String
     */

    public final void copyFrom(String from) throws WindowsException {
        try {
            if (from == null || from.isEmpty())
                throw new IllegalArgumentException("copyFrom String arg is empty");

            if (!exists())
                createNewFile();

            PrintWriter pw = new PrintWriter(new BufferedOutputStream(smbFile.getOutputStream()));
            pw.print(from);

            try {
                pw.close();
            }
            catch (Exception e) {
                // nothing can be done!
            }
        }
        catch (Exception e) {
            throw new WindowsException(e);
        }
    }

    public final void setLastModified(long when) throws WindowsException {
        // time is the usual -- msec from 1/1/1970
        // Shows you just how huge a long is.  THe number of milliseconds from (probably)
        // before you were born fits easily into a long!
        try {
            smbFile.setLastModified(when);
        }
        catch (Exception se) {
            throw new WindowsException(se);
        }

    }
    // note that the path is ALWAYS appended with one and only one slash!!
    // THis is important for smb calls...

    public final String getPath() {
        return smbPath;
    }

    private String removeLeadingAndTrailingSlashes(String path) {
        while (path.startsWith("/") || path.startsWith("\\"))
            path = path.substring(1);

        while (path.endsWith("/") || path.endsWith("\\"))
            path = path.substring(0, path.length() - 1);

        return path;
    }

    private int getChunkSize(RemoteFileCopyProgress progress, long filelength) {
        int chunksize = progress == null ? 1048576 : progress.getChunkSize();

        // be careful!  filelength is a long!!!
        if(filelength < Integer.MAX_VALUE && chunksize > (int)filelength && filelength > 0)
            return (int)filelength;

        return chunksize;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy