You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by gn...@apache.org on 2013/07/22 20:37:01 UTC
[4/9] git commit: Move filesystem abstraction from server to common
Move filesystem abstraction from server to common
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/c91e7de3
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/c91e7de3
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/c91e7de3
Branch: refs/heads/master
Commit: c91e7de313b03c354257214b34e5147038317fb0
Parents: 494f2f1
Author: Guillaume Nodet <gn...@apache.org>
Authored: Sun Jul 21 21:48:59 2013 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Sun Jul 21 21:48:59 2013 +0200
----------------------------------------------------------------------
.../main/java/org/apache/sshd/SshClient.java | 2 +
.../main/java/org/apache/sshd/SshServer.java | 13 +-
.../sshd/common/AbstractFactoryManager.java | 11 +
.../org/apache/sshd/common/FactoryManager.java | 10 +
.../sshd/common/file/FileSystemAware.java | 32 +
.../sshd/common/file/FileSystemFactory.java | 41 ++
.../apache/sshd/common/file/FileSystemView.java | 44 ++
.../org/apache/sshd/common/file/SshFile.java | 184 ++++++
.../file/nativefs/NameEqualsFileFilter.java | 61 ++
.../file/nativefs/NativeFileSystemFactory.java | 101 ++++
.../file/nativefs/NativeFileSystemView.java | 119 ++++
.../common/file/nativefs/NativeSshFile.java | 594 +++++++++++++++++++
.../org/apache/sshd/server/FileSystemAware.java | 32 -
.../apache/sshd/server/FileSystemFactory.java | 41 --
.../org/apache/sshd/server/FileSystemView.java | 44 --
.../sshd/server/ServerFactoryManager.java | 9 +-
.../java/org/apache/sshd/server/SshFile.java | 184 ------
.../sshd/server/channel/ChannelSession.java | 4 +-
.../apache/sshd/server/command/ScpCommand.java | 6 +-
.../server/filesystem/NameEqualsFileFilter.java | 61 --
.../filesystem/NativeFileSystemFactory.java | 101 ----
.../server/filesystem/NativeFileSystemView.java | 119 ----
.../sshd/server/filesystem/NativeSshFile.java | 594 -------------------
.../apache/sshd/server/sftp/SftpSubsystem.java | 7 +-
.../main/java/org/apache/sshd/sftp/Handle.java | 3 +-
.../java/org/apache/sshd/sftp/SftpSession.java | 2 +-
.../apache/sshd/sftp/reply/FileAttributes.java | 2 +-
.../sshd/sftp/reply/SshFxpAttrsReply.java | 1 -
.../apache/sshd/sftp/reply/SshFxpNameReply.java | 2 +-
.../apache/sshd/sftp/subsystem/BaseHandle.java | 2 +-
.../sshd/sftp/subsystem/DirectoryHandle.java | 2 +-
.../apache/sshd/sftp/subsystem/FileHandle.java | 2 +-
.../apache/sshd/sftp/subsystem/Serializer.java | 5 +-
.../sshd/sftp/subsystem/SftpSubsystem.java | 3 +
34 files changed, 1221 insertions(+), 1217 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/SshClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshClient.java b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
index 515a866..5682aca 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
@@ -70,6 +70,7 @@ import org.apache.sshd.common.cipher.ARCFOUR256;
import org.apache.sshd.common.cipher.BlowfishCBC;
import org.apache.sshd.common.cipher.TripleDESCBC;
import org.apache.sshd.common.compression.CompressionNone;
+import org.apache.sshd.common.file.nativefs.NativeFileSystemFactory;
import org.apache.sshd.common.forward.DefaultForwardingAcceptorFactory;
import org.apache.sshd.common.forward.DefaultTcpipForwarderFactory;
import org.apache.sshd.common.forward.TcpipServerChannel;
@@ -305,6 +306,7 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
TcpipForwarderFactory tcpipForwarderFactory = new DefaultTcpipForwarderFactory();
client.setTcpipForwarderFactory(tcpipForwarderFactory);
client.setServerKeyVerifier(AcceptAllServerKeyVerifier.INSTANCE);
+ client.setFileSystemFactory(new NativeFileSystemFactory());
return client;
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/SshServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshServer.java b/sshd-core/src/main/java/org/apache/sshd/SshServer.java
index 495cd64..4edab9b 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshServer.java
@@ -79,7 +79,7 @@ import org.apache.sshd.common.util.OsUtils;
import org.apache.sshd.common.util.SecurityUtils;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.CommandFactory;
-import org.apache.sshd.server.FileSystemFactory;
+import org.apache.sshd.common.file.FileSystemFactory;
import org.apache.sshd.server.PasswordAuthenticator;
import org.apache.sshd.server.PublickeyAuthenticator;
import org.apache.sshd.server.ServerFactoryManager;
@@ -90,7 +90,7 @@ import org.apache.sshd.server.auth.UserAuthPublicKey;
import org.apache.sshd.server.auth.gss.GSSAuthenticator;
import org.apache.sshd.server.auth.gss.UserAuthGSS;
import org.apache.sshd.server.channel.ChannelSession;
-import org.apache.sshd.server.filesystem.NativeFileSystemFactory;
+import org.apache.sshd.common.file.nativefs.NativeFileSystemFactory;
import org.apache.sshd.server.kex.DHG1;
import org.apache.sshd.server.kex.DHG14;
import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider;
@@ -138,7 +138,6 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
protected Factory<Command> shellFactory;
protected SessionFactory sessionFactory;
protected CommandFactory commandFactory;
- protected FileSystemFactory fileSystemFactory;
protected List<NamedFactory<Command>> subsystemFactories;
protected PasswordAuthenticator passwordAuthenticator;
protected PublickeyAuthenticator publickeyAuthenticator;
@@ -225,14 +224,6 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
this.commandFactory = commandFactory;
}
- public FileSystemFactory getFileSystemFactory() {
- return fileSystemFactory;
- }
-
- public void setFileSystemFactory(FileSystemFactory fileSystemFactory) {
- this.fileSystemFactory = fileSystemFactory;
- }
-
public List<NamedFactory<Command>> getSubsystemFactories() {
return subsystemFactories;
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
index 4832abb..5a69865 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
@@ -26,6 +26,7 @@ import java.util.Properties;
import java.util.concurrent.ScheduledExecutorService;
import org.apache.sshd.agent.SshAgentFactory;
+import org.apache.sshd.common.file.FileSystemFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -54,6 +55,7 @@ public abstract class AbstractFactoryManager implements FactoryManager {
protected TcpipForwarderFactory tcpipForwarderFactory;
protected ForwardingAcceptorFactory tcpipForwardingAcceptorFactory;
protected ForwardingFilter tcpipForwardingFilter;
+ protected FileSystemFactory fileSystemFactory;
protected AbstractFactoryManager() {
loadVersion();
@@ -214,4 +216,13 @@ public abstract class AbstractFactoryManager implements FactoryManager {
public void setTcpipForwardingFilter(ForwardingFilter tcpipForwardingFilter) {
this.tcpipForwardingFilter = tcpipForwardingFilter;
}
+
+ public FileSystemFactory getFileSystemFactory() {
+ return fileSystemFactory;
+ }
+
+ public void setFileSystemFactory(FileSystemFactory fileSystemFactory) {
+ this.fileSystemFactory = fileSystemFactory;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
index 212a2c8..84886a6 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
@@ -23,6 +23,7 @@ import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import org.apache.sshd.agent.SshAgentFactory;
+import org.apache.sshd.common.file.FileSystemFactory;
/**
* This interface allows retrieving all the <code>NamedFactory</code> used
@@ -170,4 +171,13 @@ public interface FactoryManager {
* @return the <code>TcpipForwarderFactory</code>
*/
TcpipForwarderFactory getTcpipForwarderFactory();
+
+ /**
+ * Retrieve the <code>FileSystemFactory</code> to be used to traverse the file system.
+ *
+ * @return a valid <code>FileSystemFactory</code> object or <code>null</code> if commands
+ * are not supported on this server
+ */
+ FileSystemFactory getFileSystemFactory();
+
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemAware.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemAware.java b/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemAware.java
new file mode 100644
index 0000000..ae0d66b
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemAware.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common.file;
+
+/**
+ * Interface that can be implemented by a command to be able to access the
+ * file system in which this command will be used.
+ */
+public interface FileSystemAware {
+ /**
+ * Set the file system in which this shell will be executed.
+ *
+ * @param view
+ */
+ void setFileSystemView(FileSystemView view);
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemFactory.java
new file mode 100644
index 0000000..6acc99c
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemFactory.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.file;
+
+import java.io.IOException;
+
+import org.apache.sshd.common.Session;
+
+/**
+ * Factory for file system implementations - it returns the file system view for user.
+ *
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+public interface FileSystemFactory {
+
+ /**
+ * Create user specific file system view.
+ * @param session The session created for the user
+ * @return The current {@link FileSystemView} for the provided session
+ * @throws IOException when the filesystem view can not be created
+ */
+ FileSystemView createFileSystemView(Session session) throws IOException;
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemView.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemView.java b/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemView.java
new file mode 100644
index 0000000..0730341
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/file/FileSystemView.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.file;
+
+/**
+ * This is an abstraction over the user file system view.
+ *
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+public interface FileSystemView {
+
+ /**
+ * Get file object.
+ * @param file The path to the file to get
+ * @return The {@link SshFile} for the provided path
+ */
+ SshFile getFile(String file);
+
+ /**
+ * Get file object.
+ * @param baseDir The reference towards which the file should be resolved
+ * @param file The path to the file to get
+ * @return The {@link SshFile} for the provided path
+ */
+ SshFile getFile(SshFile baseDir, String file);
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/common/file/SshFile.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/SshFile.java b/sshd-core/src/main/java/org/apache/sshd/common/file/SshFile.java
new file mode 100644
index 0000000..511fe4c
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/file/SshFile.java
@@ -0,0 +1,184 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.file;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+
+/**
+ * This is the file abstraction used by the server.
+ *
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+public interface SshFile {
+
+ /**
+ * Get the full path from the base directory of the FileSystemView.
+ * @return a path where the path separator is '/' (even if the operating system
+ * uses another character as path separator).
+ */
+ String getAbsolutePath();
+
+ /**
+ * Get the file name of the file
+ * @return the last part of the file path (the part after the last '/').
+ */
+ String getName();
+
+ /**
+ * Get the owner name of the file
+ * @return the name of the owner.
+ */
+ String getOwner();
+
+ /**
+ * Is it a directory?
+ * @return true if the {@link SshFile} is a directory
+ */
+ boolean isDirectory();
+
+ /**
+ * Is it a file?
+ * @return true if the {@link SshFile} is a file, false if it is a directory
+ */
+ boolean isFile();
+
+ /**
+ * Does this file exists?
+ * @return true if the {@link SshFile} exists
+ */
+ boolean doesExist();
+
+ /**
+ * Has read permission?
+ * @return true if the {@link SshFile} is readable by the user
+ */
+ boolean isReadable();
+
+ /**
+ * Has write permission?
+ * @return true if the {@link SshFile} is writable by the user
+ */
+ boolean isWritable();
+
+ /**
+ * Has exec permission?
+ * @return true if the {@link SshFile} is executable by the user
+ */
+ boolean isExecutable();
+
+ /**
+ * Has delete permission?
+ * @return true if the {@link SshFile} is removable by the user
+ */
+ boolean isRemovable();
+
+ /**
+ * Get the immediate parent. Returns the root directory if the current file is the root.
+ * @return
+ */
+ SshFile getParentFile();
+
+ /**
+ * Get last modified time in UTC.
+ * @return The timestamp of the last modified time for the {@link SshFile}
+ */
+ long getLastModified();
+
+ /**
+ * Set the last modified time stamp of a file
+ * @param time The last modified time, in milliseconds since the epoch. See {@link java.io.File#setLastModified(long)}.
+ */
+ boolean setLastModified(long time);
+
+ /**
+ * Get file size.
+ * @return The size of the {@link SshFile} in bytes
+ */
+ long getSize();
+
+ /**
+ * Create directory.
+ * @return true if the operation was successful
+ */
+ boolean mkdir();
+
+ /**
+ * Delete file.
+ * @return true if the operation was successful
+ */
+ boolean delete();
+
+ /**
+ * Create the file.
+ * @return true if the file has been created and false if it already exist
+ * @throws java.io.IOException if something wrong happen
+ */
+ boolean create() throws IOException;
+
+ /**
+ * Truncate the file to length 0.
+ * @throws java.io.IOException if something wrong happen
+ */
+ void truncate() throws IOException;
+
+ /**
+ * Move file.
+ * @param destination The target {@link SshFile} to move the current {@link SshFile} to
+ * @return true if the operation was successful
+ */
+ boolean move(SshFile destination);
+
+ /**
+ * List file objects. If not a directory or does not exist, null will be
+ * returned. Files must be returned in alphabetical order.
+ * List must be immutable.
+ * @return The {@link java.util.List} of {@link SshFile}s
+ */
+ List<SshFile> listSshFiles();
+
+ /**
+ * Create output stream for writing.
+ * @param offset The number of bytes at where to start writing.
+ * If the file is not random accessible,
+ * any offset other than zero will throw an exception.
+ * @return An {@link java.io.OutputStream} used to write to the {@link SshFile}
+ * @throws java.io.IOException
+ */
+ OutputStream createOutputStream(long offset) throws IOException;
+
+ /**
+ * Create input stream for reading.
+ * @param offset The number of bytes of where to start reading.
+ * If the file is not random accessible,
+ * any offset other than zero will throw an exception.
+ * @return An {@link java.io.InputStream} used to read the {@link SshFile}
+ * @throws java.io.IOException
+ */
+ InputStream createInputStream(long offset) throws IOException;
+
+ /**
+ * Handle post-handle-close functionality.
+ * @throws IOException
+ */
+ void handleClose() throws IOException;
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NameEqualsFileFilter.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NameEqualsFileFilter.java b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NameEqualsFileFilter.java
new file mode 100644
index 0000000..65693fb
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NameEqualsFileFilter.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.file.nativefs;
+
+import java.io.File;
+import java.io.FileFilter;
+
+/**
+ * <strong>Internal class, do not use directly.</strong>
+ *
+ * FileFilter used for simple file name matching
+ *
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+public class NameEqualsFileFilter implements FileFilter {
+
+ private String nameToMatch;
+
+ private boolean caseInsensitive = false;
+
+ /**
+ * Constructor
+ *
+ * @param nameToMatch
+ * The exact file name to match
+ * @param caseInsensitive
+ * Wether that match should be case insensitive
+ */
+ public NameEqualsFileFilter(final String nameToMatch,
+ final boolean caseInsensitive) {
+ this.nameToMatch = nameToMatch;
+ this.caseInsensitive = caseInsensitive;
+ }
+
+ public boolean accept(final File file) {
+
+ if (caseInsensitive) {
+ return file.getName().equalsIgnoreCase(nameToMatch);
+ } else {
+ return file.getName().equals(nameToMatch);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemFactory.java
new file mode 100644
index 0000000..50e7f73
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemFactory.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.file.nativefs;
+
+import java.io.File;
+
+import org.apache.sshd.common.Session;
+import org.apache.sshd.common.file.FileSystemFactory;
+import org.apache.sshd.common.file.FileSystemView;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Native file system factory. It uses the OS file system.
+ *
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+public class NativeFileSystemFactory implements FileSystemFactory {
+
+ private final Logger LOG = LoggerFactory.getLogger(NativeFileSystemFactory.class);
+
+ private boolean createHome;
+
+ private boolean caseInsensitive;
+
+ /**
+ * Should the home directories be created automatically
+ * @return true if the file system will create the home directory if not available
+ */
+ public boolean isCreateHome() {
+ return createHome;
+ }
+
+ /**
+ * Set if the home directories be created automatically
+ * @param createHome true if the file system will create the home directory if not available
+ */
+
+ public void setCreateHome(boolean createHome) {
+ this.createHome = createHome;
+ }
+
+ /**
+ * Is this file system case insensitive.
+ * Enabling might cause problems when working against case-sensitive file systems, like on Linux
+ * @return true if this file system is case insensitive
+ */
+ public boolean isCaseInsensitive() {
+ return caseInsensitive;
+ }
+
+ /**
+ * Should this file system be case insensitive.
+ * Enabling might cause problems when working against case-sensitive file systems, like on Linux
+ * @param caseInsensitive true if this file system should be case insensitive
+ */
+ public void setCaseInsensitive(boolean caseInsensitive) {
+ this.caseInsensitive = caseInsensitive;
+ }
+
+ /**
+ * Create the appropriate user file system view.
+ */
+ public FileSystemView createFileSystemView(Session session) {
+ String userName = session.getUsername();
+ // create home if does not exist
+ if (createHome) {
+ String homeDirStr = "/home/" + userName;
+ File homeDir = new File(homeDirStr);
+ if (homeDir.isFile()) {
+ LOG.warn("Not a directory :: " + homeDirStr);
+// throw new FtpException("Not a directory :: " + homeDirStr);
+ }
+ if ((!homeDir.exists()) && (!homeDir.mkdirs())) {
+ LOG.warn("Cannot create user home :: " + homeDirStr);
+// throw new FtpException("Cannot create user home :: "
+// + homeDirStr);
+ }
+ }
+
+ FileSystemView fsView = new NativeFileSystemView(userName, caseInsensitive);
+ return fsView;
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemView.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemView.java b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemView.java
new file mode 100644
index 0000000..9ba8994
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeFileSystemView.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.file.nativefs;
+
+import java.io.File;
+
+import org.apache.sshd.common.file.FileSystemView;
+import org.apache.sshd.common.file.SshFile;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <strong>Internal class, do not use directly.</strong>
+ *
+ * File system view based on native file system. Here the root directory will be
+ * user virtual root (/).
+ *
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+public class NativeFileSystemView implements FileSystemView {
+
+ private final Logger LOG = LoggerFactory
+ .getLogger(NativeFileSystemView.class);
+
+
+ // the first and the last character will always be '/'
+ // It is always with respect to the root directory.
+ private String currDir;
+
+ private String userName;
+
+ private boolean caseInsensitive = false;
+
+ /**
+ * Constructor - internal do not use directly, use {@link NativeFileSystemFactory} instead
+ */
+ protected NativeFileSystemView(String userName) {
+ this(userName, false);
+ }
+
+ /**
+ * Constructor - internal do not use directly, use {@link NativeFileSystemFactory} instead
+ */
+ public NativeFileSystemView(String userName, boolean caseInsensitive) {
+ if (userName == null) {
+ throw new IllegalArgumentException("user can not be null");
+ }
+
+ this.caseInsensitive = caseInsensitive;
+
+ currDir = getVirtualUserDir();
+ this.userName = userName;
+
+ // add last '/' if necessary
+ LOG.debug("Native filesystem view created for user \"{}\" with root \"{}\"", userName, currDir);
+ }
+
+ /**
+ * Get file object.
+ */
+ public SshFile getFile(String file) {
+ return getFile(currDir, file);
+ }
+
+ public SshFile getFile(SshFile baseDir, String file) {
+ return getFile(baseDir.getAbsolutePath(), file);
+ }
+
+ protected SshFile getFile(String dir, String file) {
+ // get actual file object
+ String physicalName = NativeSshFile.getPhysicalName(getPhysicalUserDir(),
+ dir, file, caseInsensitive);
+ File fileObj = new File(physicalName);
+
+ // strip the root directory and return
+ String userFileName = physicalName.substring(getPhysicalUserDir().length() - 1);
+ return createNativeSshFile(userFileName, fileObj, userName);
+ }
+
+ /**
+ * Returns the physical user directory, for accessing the according files or directories.
+ *
+ * @return The physical user directory.
+ */
+ public String getPhysicalUserDir() {
+ return "/";
+ }
+
+ /**
+ * Returns the virtual user directory.
+ * The will be shown in sftp client. It is relative to the physical user directory.
+ *
+ * @return The virtual user directory.
+ */
+ public String getVirtualUserDir() {
+ return System.getProperty("user.dir");
+ }
+
+ public NativeSshFile createNativeSshFile(final String fileName2, final File fileObj, final String userName2) {
+ return new NativeSshFile(this, fileName2, fileObj, userName2);
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFile.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFile.java b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFile.java
new file mode 100644
index 0000000..d2796fd
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/file/nativefs/NativeSshFile.java
@@ -0,0 +1,594 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sshd.common.file.nativefs;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.sshd.common.file.SshFile;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <strong>Internal class, do not use directly.</strong>
+ *
+ * This class wraps native file object.
+ *
+ * @author <a href="http://mina.apache.org">Apache MINA Project</a>
+ */
+public class NativeSshFile implements SshFile {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NativeSshFile.class);
+
+ // the file name with respect to the user root.
+ // The path separator character will be '/' and
+ // it will always begin with '/'.
+ private String fileName;
+
+ private File file;
+
+ private String userName;
+
+ private final NativeFileSystemView nativeFileSystemView;
+
+ /**
+ * Constructor, internal do not use directly.
+ * @param nativeFileSystemView
+ */
+ protected NativeSshFile(final NativeFileSystemView nativeFileSystemView, final String fileName, final File file,
+ final String userName) {
+ this.nativeFileSystemView = nativeFileSystemView;
+ if (fileName == null) {
+ throw new IllegalArgumentException("fileName can not be null");
+ }
+ if (file == null) {
+ throw new IllegalArgumentException("file can not be null");
+ }
+
+ if (fileName.length() == 0) {
+ throw new IllegalArgumentException("fileName can not be empty");
+ } else if (fileName.charAt(0) != '/') {
+ throw new IllegalArgumentException("fileName must be an absolute path");
+ }
+
+ this.fileName = fileName;
+ this.file = file;
+ this.userName = userName;
+ }
+
+ /**
+ * Get full name.
+ */
+ public String getAbsolutePath() {
+
+ // strip the last '/' if necessary
+ String fullName = fileName;
+ int filelen = fullName.length();
+ if ((filelen != 1) && (fullName.charAt(filelen - 1) == '/')) {
+ fullName = fullName.substring(0, filelen - 1);
+ }
+
+ return fullName;
+ }
+
+ /**
+ * Get short name.
+ */
+ public String getName() {
+
+ // root - the short name will be '/'
+ if (fileName.equals("/")) {
+ return "/";
+ }
+
+ // strip the last '/'
+ String shortName = fileName;
+ int filelen = fileName.length();
+ if (shortName.charAt(filelen - 1) == '/') {
+ shortName = shortName.substring(0, filelen - 1);
+ }
+
+ // return from the last '/'
+ int slashIndex = shortName.lastIndexOf('/');
+ if (slashIndex != -1) {
+ shortName = shortName.substring(slashIndex + 1);
+ }
+ return shortName;
+ }
+
+ /**
+ * Get owner name
+ */
+ public String getOwner() {
+ return userName;
+ }
+
+ /**
+ * Is it a directory?
+ */
+ public boolean isDirectory() {
+ return file.isDirectory();
+ }
+
+ /**
+ * Is it a file?
+ */
+ public boolean isFile() {
+ return file.isFile();
+ }
+
+ /**
+ * Does this file exists?
+ */
+ public boolean doesExist() {
+ return file.exists();
+ }
+
+ /**
+ * Get file size.
+ */
+ public long getSize() {
+ return file.length();
+ }
+
+ /**
+ * Get last modified time.
+ */
+ public long getLastModified() {
+ return file.lastModified();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean setLastModified(long time) {
+ return file.setLastModified(time);
+ }
+
+ /**
+ * Check read permission.
+ */
+ public boolean isReadable() {
+ return file.canRead();
+ }
+
+ /**
+ * Check file write permission.
+ */
+ public boolean isWritable() {
+ LOG.debug("Checking if file exists");
+ if (file.exists()) {
+ LOG.debug("Checking can write: " + file.canWrite());
+ return file.canWrite();
+ }
+
+ LOG.debug("Authorized");
+ return true;
+ }
+
+ /**
+ * File.canExecute() method is only available on JDK 1.6
+ */
+ private static final Method CAN_EXECUTE_METHOD;
+ static {
+ Method method = null;
+ try {
+ method = File.class.getMethod("canExecute");
+ } catch (Throwable t) {
+ }
+ CAN_EXECUTE_METHOD = method;
+ }
+
+ /**
+ * Check file exec permission.
+ */
+ public boolean isExecutable() {
+ if (CAN_EXECUTE_METHOD != null) {
+ try {
+ return (Boolean) CAN_EXECUTE_METHOD.invoke(file);
+ } catch (Throwable t) {
+ }
+ }
+ // Default directories to being executable
+ // as on unix systems to allow listing their contents.
+ return file.isDirectory();
+ }
+
+ /**
+ * Has delete permission.
+ */
+ public boolean isRemovable() {
+
+ // root cannot be deleted
+ if ("/".equals(fileName)) {
+ return false;
+ }
+
+ /* Added 12/08/2008: in the case that the permission is not explicitly denied for this file
+ * we will check if the parent file has write permission as most systems consider that a file can
+ * be deleted when their parent directory is writable.
+ */
+ String fullName = getAbsolutePath();
+
+ // we check FTPServer's write permission for this file.
+// if (user.authorize(new WriteRequest(fullName)) == null) {
+// return false;
+// }
+
+ // In order to maintain consistency, when possible we delete the last '/' character in the String
+ int indexOfSlash = fullName.lastIndexOf('/');
+ String parentFullName;
+ if (indexOfSlash == 0) {
+ parentFullName = "/";
+ } else {
+ parentFullName = fullName.substring(0, indexOfSlash);
+ }
+
+ // we check if the parent FileObject is writable.
+ NativeSshFile parentObject = nativeFileSystemView.createNativeSshFile(parentFullName, file
+ .getAbsoluteFile().getParentFile(), userName);
+ return parentObject.isWritable();
+ }
+
+ public SshFile getParentFile() {
+ int indexOfSlash = getAbsolutePath().lastIndexOf('/');
+ String parentFullName;
+ if (indexOfSlash == 0) {
+ parentFullName = "/";
+ } else {
+ parentFullName = getAbsolutePath().substring(0, indexOfSlash);
+ }
+
+ // we check if the parent FileObject is writable.
+ return nativeFileSystemView.createNativeSshFile(parentFullName, file
+ .getAbsoluteFile().getParentFile(), userName);
+ }
+
+ /**
+ * Delete file.
+ */
+ public boolean delete() {
+ boolean retVal = false;
+ if (isRemovable()) {
+ retVal = file.delete();
+ }
+ return retVal;
+ }
+
+ /**
+ * Create a new file
+ */
+ public boolean create() throws IOException {
+ return file.createNewFile();
+ }
+
+ /**
+ * Truncate file to length 0.
+ */
+ public void truncate() throws IOException{
+ RandomAccessFile tempFile = new RandomAccessFile(file, "rw");
+ try {
+ tempFile.setLength(0);
+ } finally {
+ tempFile.close();
+ }
+ }
+
+ /**
+ * Move file object.
+ */
+ public boolean move(final SshFile dest) {
+ boolean retVal = false;
+ if (dest.isWritable() && isReadable()) {
+ File destFile = ((NativeSshFile) dest).file;
+
+ if (destFile.exists()) {
+ // renameTo behaves differently on different platforms
+ // this check verifies that if the destination already exists,
+ // we fail
+ retVal = false;
+ } else {
+ retVal = file.renameTo(destFile);
+ }
+ }
+ return retVal;
+ }
+
+ /**
+ * Create directory.
+ */
+ public boolean mkdir() {
+ boolean retVal = false;
+ if (isWritable()) {
+ retVal = file.mkdir();
+ }
+ return retVal;
+ }
+
+ /**
+ * List files. If not a directory or does not exist, null will be returned.
+ */
+ public List<SshFile> listSshFiles() {
+
+ // is a directory
+ if (!file.isDirectory()) {
+ return null;
+ }
+
+ // directory - return all the files
+ File[] files = file.listFiles();
+ if (files == null) {
+ return null;
+ }
+
+ // make sure the files are returned in order
+ Arrays.sort(files, new Comparator<File>() {
+ public int compare(File f1, File f2) {
+ return f1.getName().compareTo(f2.getName());
+ }
+ });
+
+ // get the virtual name of the base directory
+ String virtualFileStr = getAbsolutePath();
+ if (virtualFileStr.charAt(virtualFileStr.length() - 1) != '/') {
+ virtualFileStr += '/';
+ }
+
+ // now return all the files under the directory
+ SshFile[] virtualFiles = new SshFile[files.length];
+ for (int i = 0; i < files.length; ++i) {
+ File fileObj = files[i];
+ String fileName = virtualFileStr + fileObj.getName();
+ virtualFiles[i] = nativeFileSystemView.createNativeSshFile(fileName, fileObj, userName);
+ }
+
+ return Collections.unmodifiableList(Arrays.asList(virtualFiles));
+ }
+
+ /**
+ * Create output stream for writing.
+ */
+ public OutputStream createOutputStream(final long offset)
+ throws IOException {
+
+ // permission check
+ if (!isWritable()) {
+ throw new IOException("No write permission : " + file.getName());
+ }
+
+ // move to the appropriate offset and create output stream
+ final RandomAccessFile raf = new RandomAccessFile(file, "rw");
+ try {
+ raf.setLength(offset);
+ raf.seek(offset);
+
+ // The IBM jre needs to have both the stream and the random access file
+ // objects closed to actually close the file
+ return new FileOutputStream(raf.getFD()) {
+ public void close() throws IOException {
+ super.close();
+ raf.close();
+ }
+ };
+ } catch (IOException e) {
+ raf.close();
+ throw e;
+ }
+ }
+
+ /**
+ * Create input stream for reading.
+ */
+ public InputStream createInputStream(final long offset) throws IOException {
+
+ // permission check
+ if (!isReadable()) {
+ throw new IOException("No read permission : " + file.getName());
+ }
+
+ // move to the appropriate offset and create input stream
+ final RandomAccessFile raf = new RandomAccessFile(file, "r");
+ try {
+ raf.seek(offset);
+
+ // The IBM jre needs to have both the stream and the random access file
+ // objects closed to actually close the file
+ return new FileInputStream(raf.getFD()) {
+ public void close() throws IOException {
+ super.close();
+ raf.close();
+ }
+ };
+ } catch (IOException e) {
+ raf.close();
+ throw e;
+ }
+ }
+
+ public void handleClose() {
+ // Noop
+ }
+
+ /**
+ * Normalize separate character. Separate character should be '/' always.
+ */
+ public final static String normalizeSeparateChar(final String pathName) {
+ String normalizedPathName = pathName.replace(File.separatorChar, '/');
+ normalizedPathName = normalizedPathName.replace('\\', '/');
+ return normalizedPathName;
+ }
+
+ /**
+ * Get the physical canonical file name. It works like
+ * File.getCanonicalPath().
+ *
+ * @param rootDir
+ * The root directory.
+ * @param currDir
+ * The current directory. It will always be with respect to the
+ * root directory.
+ * @param fileName
+ * The input file name.
+ * @return The return string will always begin with the root directory. It
+ * will never be null.
+ */
+ public final static String getPhysicalName(final String rootDir,
+ final String currDir, final String fileName) {
+ return getPhysicalName(rootDir, currDir, fileName, false);
+ }
+
+ public final static String getPhysicalName(final String rootDir,
+ final String currDir, final String fileName,
+ final boolean caseInsensitive) {
+
+ // get the starting directory
+ String normalizedRootDir = normalizeSeparateChar(rootDir);
+ if (normalizedRootDir.charAt(normalizedRootDir.length() - 1) != '/') {
+ normalizedRootDir += '/';
+ }
+
+ String normalizedFileName = normalizeSeparateChar(fileName);
+ String resArg;
+ String normalizedCurrDir = currDir;
+ if (normalizedFileName.charAt(0) != '/') {
+ if (normalizedCurrDir == null) {
+ normalizedCurrDir = "/";
+ }
+ if (normalizedCurrDir.length() == 0) {
+ normalizedCurrDir = "/";
+ }
+
+ normalizedCurrDir = normalizeSeparateChar(normalizedCurrDir);
+
+ if (normalizedCurrDir.charAt(0) != '/') {
+ normalizedCurrDir = '/' + normalizedCurrDir;
+ }
+ if (normalizedCurrDir.charAt(normalizedCurrDir.length() - 1) != '/') {
+ normalizedCurrDir += '/';
+ }
+
+ resArg = normalizedRootDir + normalizedCurrDir.substring(1);
+ } else {
+ resArg = normalizedRootDir;
+ }
+
+ // strip last '/'
+ if (resArg.charAt(resArg.length() - 1) == '/') {
+ resArg = resArg.substring(0, resArg.length() - 1);
+ }
+
+ // replace ., ~ and ..
+ // in this loop resArg will never end with '/'
+ StringTokenizer st = new StringTokenizer(normalizedFileName, "/");
+ while (st.hasMoreTokens()) {
+ String tok = st.nextToken();
+
+ // . => current directory
+ if (tok.equals(".")) {
+ continue;
+ }
+
+ // .. => parent directory (if not root)
+ if (tok.equals("..")) {
+ if (resArg.startsWith(normalizedRootDir)) {
+ int slashIndex = resArg.lastIndexOf('/');
+ if (slashIndex != -1) {
+ resArg = resArg.substring(0, slashIndex);
+ }
+ }
+ continue;
+ }
+
+ // ~ => home directory (in this case the root directory)
+ if (tok.equals("~")) {
+ resArg = normalizedRootDir.substring(0, normalizedRootDir
+ .length() - 1);
+ continue;
+ }
+
+ if (caseInsensitive) {
+ File[] matches = new File(resArg)
+ .listFiles(new NameEqualsFileFilter(tok, true));
+
+ if (matches != null && matches.length > 0) {
+ tok = matches[0].getName();
+ }
+ }
+
+ resArg = resArg + '/' + tok;
+ }
+
+ // add last slash if necessary
+ if ((resArg.length()) + 1 == normalizedRootDir.length()) {
+ resArg += '/';
+ }
+
+ // final check
+ if (!resArg.regionMatches(0, normalizedRootDir, 0, normalizedRootDir
+ .length())) {
+ resArg = normalizedRootDir;
+ }
+
+ return resArg;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj != null && obj instanceof NativeSshFile) {
+ File thisCanonicalFile;
+ File otherCanonicalFile;
+ try {
+ thisCanonicalFile = this.file.getCanonicalFile();
+ otherCanonicalFile = ((NativeSshFile) obj).file
+ .getCanonicalFile();
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to get the canonical path", e);
+ }
+
+ return thisCanonicalFile.equals(otherCanonicalFile);
+ }
+ return false;
+ }
+
+ /**
+ * Returns the according physical file. Needed for logging, monitoring, event handling, etc.
+ *
+ * @return The according physical file.
+ */
+ public File getPhysicalFile() {
+ return file;
+ }
+
+ @Override
+ public String toString() {
+ return fileName;
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/server/FileSystemAware.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/FileSystemAware.java b/sshd-core/src/main/java/org/apache/sshd/server/FileSystemAware.java
deleted file mode 100644
index 0cf67a5..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/FileSystemAware.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.sshd.server;
-
-/**
- * Interface that can be implemented by a command to be able to access the
- * file system in which this command will be used.
- */
-public interface FileSystemAware {
- /**
- * Set the file system in which this shell will be executed.
- *
- * @param view
- */
- void setFileSystemView(FileSystemView view);
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/server/FileSystemFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/FileSystemFactory.java b/sshd-core/src/main/java/org/apache/sshd/server/FileSystemFactory.java
deleted file mode 100644
index b80c050..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/FileSystemFactory.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.sshd.server;
-
-import java.io.IOException;
-
-import org.apache.sshd.common.Session;
-
-/**
- * Factory for file system implementations - it returns the file system view for user.
- *
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
- */
-public interface FileSystemFactory {
-
- /**
- * Create user specific file system view.
- * @param session The session created for the user
- * @return The current {@link FileSystemView} for the provided session
- * @throws IOException when the filesystem view can not be created
- */
- FileSystemView createFileSystemView(Session session) throws IOException;
-
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/server/FileSystemView.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/FileSystemView.java b/sshd-core/src/main/java/org/apache/sshd/server/FileSystemView.java
deleted file mode 100644
index 43ce91c..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/FileSystemView.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.sshd.server;
-
-/**
- * This is an abstraction over the user file system view.
- *
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
- */
-public interface FileSystemView {
-
- /**
- * Get file object.
- * @param file The path to the file to get
- * @return The {@link SshFile} for the provided path
- */
- SshFile getFile(String file);
-
- /**
- * Get file object.
- * @param baseDir The reference towards which the file should be resolved
- * @param file The path to the file to get
- * @return The {@link SshFile} for the provided path
- */
- SshFile getFile(SshFile baseDir, String file);
-
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java
index 521a8fb..81a437d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java
@@ -24,6 +24,7 @@ import org.apache.sshd.common.Factory;
import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.ForwardingAcceptorFactory;
import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.file.FileSystemFactory;
import org.apache.sshd.server.auth.gss.GSSAuthenticator;
/**
@@ -135,14 +136,6 @@ public interface ServerFactoryManager extends FactoryManager {
CommandFactory getCommandFactory();
/**
- * Retrieve the <code>FileSystemFactory</code> to be used to traverse the file system.
- *
- * @return a valid <code>FileSystemFactory</code> object or <code>null</code> if commands
- * are not supported on this server
- */
- FileSystemFactory getFileSystemFactory();
-
- /**
* Retrieve the list of named factories for <code>CommandFactory.Command</code> to
* be used to create subsystems.
*
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/server/SshFile.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/SshFile.java b/sshd-core/src/main/java/org/apache/sshd/server/SshFile.java
deleted file mode 100644
index af7830e..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/SshFile.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.sshd.server;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.List;
-
-/**
- * This is the file abstraction used by the server.
- *
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
- */
-public interface SshFile {
-
- /**
- * Get the full path from the base directory of the FileSystemView.
- * @return a path where the path separator is '/' (even if the operating system
- * uses another character as path separator).
- */
- String getAbsolutePath();
-
- /**
- * Get the file name of the file
- * @return the last part of the file path (the part after the last '/').
- */
- String getName();
-
- /**
- * Get the owner name of the file
- * @return the name of the owner.
- */
- String getOwner();
-
- /**
- * Is it a directory?
- * @return true if the {@link SshFile} is a directory
- */
- boolean isDirectory();
-
- /**
- * Is it a file?
- * @return true if the {@link SshFile} is a file, false if it is a directory
- */
- boolean isFile();
-
- /**
- * Does this file exists?
- * @return true if the {@link SshFile} exists
- */
- boolean doesExist();
-
- /**
- * Has read permission?
- * @return true if the {@link SshFile} is readable by the user
- */
- boolean isReadable();
-
- /**
- * Has write permission?
- * @return true if the {@link SshFile} is writable by the user
- */
- boolean isWritable();
-
- /**
- * Has exec permission?
- * @return true if the {@link SshFile} is executable by the user
- */
- boolean isExecutable();
-
- /**
- * Has delete permission?
- * @return true if the {@link SshFile} is removable by the user
- */
- boolean isRemovable();
-
- /**
- * Get the immediate parent. Returns the root directory if the current file is the root.
- * @return
- */
- SshFile getParentFile();
-
- /**
- * Get last modified time in UTC.
- * @return The timestamp of the last modified time for the {@link SshFile}
- */
- long getLastModified();
-
- /**
- * Set the last modified time stamp of a file
- * @param time The last modified time, in milliseconds since the epoch. See {@link java.io.File#setLastModified(long)}.
- */
- boolean setLastModified(long time);
-
- /**
- * Get file size.
- * @return The size of the {@link SshFile} in bytes
- */
- long getSize();
-
- /**
- * Create directory.
- * @return true if the operation was successful
- */
- boolean mkdir();
-
- /**
- * Delete file.
- * @return true if the operation was successful
- */
- boolean delete();
-
- /**
- * Create the file.
- * @return true if the file has been created and false if it already exist
- * @throws java.io.IOException if something wrong happen
- */
- boolean create() throws IOException;
-
- /**
- * Truncate the file to length 0.
- * @throws java.io.IOException if something wrong happen
- */
- void truncate() throws IOException;
-
- /**
- * Move file.
- * @param destination The target {@link SshFile} to move the current {@link SshFile} to
- * @return true if the operation was successful
- */
- boolean move(SshFile destination);
-
- /**
- * List file objects. If not a directory or does not exist, null will be
- * returned. Files must be returned in alphabetical order.
- * List must be immutable.
- * @return The {@link java.util.List} of {@link SshFile}s
- */
- List<SshFile> listSshFiles();
-
- /**
- * Create output stream for writing.
- * @param offset The number of bytes at where to start writing.
- * If the file is not random accessible,
- * any offset other than zero will throw an exception.
- * @return An {@link java.io.OutputStream} used to write to the {@link SshFile}
- * @throws java.io.IOException
- */
- OutputStream createOutputStream(long offset) throws IOException;
-
- /**
- * Create input stream for reading.
- * @param offset The number of bytes of where to start reading.
- * If the file is not random accessible,
- * any offset other than zero will throw an exception.
- * @return An {@link java.io.InputStream} used to read the {@link SshFile}
- * @throws java.io.IOException
- */
- InputStream createInputStream(long offset) throws IOException;
-
- /**
- * Handle post-handle-close functionality.
- * @throws IOException
- */
- void handleClose() throws IOException;
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java b/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
index b2d8b13..d337247 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
@@ -46,8 +46,8 @@ import org.apache.sshd.server.ChannelSessionAware;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.ExitCallback;
-import org.apache.sshd.server.FileSystemAware;
-import org.apache.sshd.server.FileSystemFactory;
+import org.apache.sshd.common.file.FileSystemAware;
+import org.apache.sshd.common.file.FileSystemFactory;
import org.apache.sshd.server.SessionAware;
import org.apache.sshd.server.Signal;
import org.apache.sshd.server.SignalListener;
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommand.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommand.java b/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommand.java
index a506b3a..950d569 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommand.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/command/ScpCommand.java
@@ -29,9 +29,9 @@ import org.apache.sshd.common.util.DirectoryScanner;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.ExitCallback;
-import org.apache.sshd.server.FileSystemAware;
-import org.apache.sshd.server.FileSystemView;
-import org.apache.sshd.server.SshFile;
+import org.apache.sshd.common.file.FileSystemAware;
+import org.apache.sshd.common.file.FileSystemView;
+import org.apache.sshd.common.file.SshFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/server/filesystem/NameEqualsFileFilter.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/filesystem/NameEqualsFileFilter.java b/sshd-core/src/main/java/org/apache/sshd/server/filesystem/NameEqualsFileFilter.java
deleted file mode 100644
index 2a672e1..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/filesystem/NameEqualsFileFilter.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.sshd.server.filesystem;
-
-import java.io.File;
-import java.io.FileFilter;
-
-/**
- * <strong>Internal class, do not use directly.</strong>
- *
- * FileFilter used for simple file name matching
- *
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
- */
-public class NameEqualsFileFilter implements FileFilter {
-
- private String nameToMatch;
-
- private boolean caseInsensitive = false;
-
- /**
- * Constructor
- *
- * @param nameToMatch
- * The exact file name to match
- * @param caseInsensitive
- * Wether that match should be case insensitive
- */
- public NameEqualsFileFilter(final String nameToMatch,
- final boolean caseInsensitive) {
- this.nameToMatch = nameToMatch;
- this.caseInsensitive = caseInsensitive;
- }
-
- public boolean accept(final File file) {
-
- if (caseInsensitive) {
- return file.getName().equalsIgnoreCase(nameToMatch);
- } else {
- return file.getName().equals(nameToMatch);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/server/filesystem/NativeFileSystemFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/filesystem/NativeFileSystemFactory.java b/sshd-core/src/main/java/org/apache/sshd/server/filesystem/NativeFileSystemFactory.java
deleted file mode 100644
index 24ac76e..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/filesystem/NativeFileSystemFactory.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.sshd.server.filesystem;
-
-import java.io.File;
-
-import org.apache.sshd.common.Session;
-import org.apache.sshd.server.FileSystemFactory;
-import org.apache.sshd.server.FileSystemView;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Native file system factory. It uses the OS file system.
- *
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
- */
-public class NativeFileSystemFactory implements FileSystemFactory {
-
- private final Logger LOG = LoggerFactory.getLogger(NativeFileSystemFactory.class);
-
- private boolean createHome;
-
- private boolean caseInsensitive;
-
- /**
- * Should the home directories be created automatically
- * @return true if the file system will create the home directory if not available
- */
- public boolean isCreateHome() {
- return createHome;
- }
-
- /**
- * Set if the home directories be created automatically
- * @param createHome true if the file system will create the home directory if not available
- */
-
- public void setCreateHome(boolean createHome) {
- this.createHome = createHome;
- }
-
- /**
- * Is this file system case insensitive.
- * Enabling might cause problems when working against case-sensitive file systems, like on Linux
- * @return true if this file system is case insensitive
- */
- public boolean isCaseInsensitive() {
- return caseInsensitive;
- }
-
- /**
- * Should this file system be case insensitive.
- * Enabling might cause problems when working against case-sensitive file systems, like on Linux
- * @param caseInsensitive true if this file system should be case insensitive
- */
- public void setCaseInsensitive(boolean caseInsensitive) {
- this.caseInsensitive = caseInsensitive;
- }
-
- /**
- * Create the appropriate user file system view.
- */
- public FileSystemView createFileSystemView(Session session) {
- String userName = session.getUsername();
- // create home if does not exist
- if (createHome) {
- String homeDirStr = "/home/" + userName;
- File homeDir = new File(homeDirStr);
- if (homeDir.isFile()) {
- LOG.warn("Not a directory :: " + homeDirStr);
-// throw new FtpException("Not a directory :: " + homeDirStr);
- }
- if ((!homeDir.exists()) && (!homeDir.mkdirs())) {
- LOG.warn("Cannot create user home :: " + homeDirStr);
-// throw new FtpException("Cannot create user home :: "
-// + homeDirStr);
- }
- }
-
- FileSystemView fsView = new NativeFileSystemView(userName, caseInsensitive);
- return fsView;
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/c91e7de3/sshd-core/src/main/java/org/apache/sshd/server/filesystem/NativeFileSystemView.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/filesystem/NativeFileSystemView.java b/sshd-core/src/main/java/org/apache/sshd/server/filesystem/NativeFileSystemView.java
deleted file mode 100644
index 3e78c29..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/server/filesystem/NativeFileSystemView.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.sshd.server.filesystem;
-
-import java.io.File;
-
-import org.apache.sshd.server.FileSystemView;
-import org.apache.sshd.server.SshFile;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * <strong>Internal class, do not use directly.</strong>
- *
- * File system view based on native file system. Here the root directory will be
- * user virtual root (/).
- *
- * @author <a href="http://mina.apache.org">Apache MINA Project</a>
- */
-public class NativeFileSystemView implements FileSystemView {
-
- private final Logger LOG = LoggerFactory
- .getLogger(NativeFileSystemView.class);
-
-
- // the first and the last character will always be '/'
- // It is always with respect to the root directory.
- private String currDir;
-
- private String userName;
-
- private boolean caseInsensitive = false;
-
- /**
- * Constructor - internal do not use directly, use {@link NativeFileSystemFactory} instead
- */
- protected NativeFileSystemView(String userName) {
- this(userName, false);
- }
-
- /**
- * Constructor - internal do not use directly, use {@link NativeFileSystemFactory} instead
- */
- public NativeFileSystemView(String userName, boolean caseInsensitive) {
- if (userName == null) {
- throw new IllegalArgumentException("user can not be null");
- }
-
- this.caseInsensitive = caseInsensitive;
-
- currDir = getVirtualUserDir();
- this.userName = userName;
-
- // add last '/' if necessary
- LOG.debug("Native filesystem view created for user \"{}\" with root \"{}\"", userName, currDir);
- }
-
- /**
- * Get file object.
- */
- public SshFile getFile(String file) {
- return getFile(currDir, file);
- }
-
- public SshFile getFile(SshFile baseDir, String file) {
- return getFile(baseDir.getAbsolutePath(), file);
- }
-
- protected SshFile getFile(String dir, String file) {
- // get actual file object
- String physicalName = NativeSshFile.getPhysicalName(getPhysicalUserDir(),
- dir, file, caseInsensitive);
- File fileObj = new File(physicalName);
-
- // strip the root directory and return
- String userFileName = physicalName.substring(getPhysicalUserDir().length() - 1);
- return createNativeSshFile(userFileName, fileObj, userName);
- }
-
- /**
- * Returns the physical user directory, for accessing the according files or directories.
- *
- * @return The physical user directory.
- */
- public String getPhysicalUserDir() {
- return "/";
- }
-
- /**
- * Returns the virtual user directory.
- * The will be shown in sftp client. It is relative to the physical user directory.
- *
- * @return The virtual user directory.
- */
- public String getVirtualUserDir() {
- return System.getProperty("user.dir");
- }
-
- public NativeSshFile createNativeSshFile(final String fileName2, final File fileObj, final String userName2) {
- return new NativeSshFile(this, fileName2, fileObj, userName2);
- }
-}