com.sun.enterprise.util.cluster.windows.io.WindowsRemoteFile Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of payara-micro Show documentation
Show all versions of payara-micro Show documentation
Micro Distribution of the Payara Project
/*
* 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;
}
}