0%

Hadoop-Intellij-Plugin 插件设计和源码分析----HDFS文件系统对象FileSystemObject的设计与实现

  本节,简单介绍HDFS文件系统浏览器的文件系统对象。文件系统对象和HDFS文件系统对象一致,分为目录和文件,文件不再进行具体的区分文件类型。文件系统对象在UI上表现为文件系统树上的节点。FileSystemObject整个设计的类图如下:

文件系统对象的接口定义 FileSystemObject

  文件系统对象在UI上表现为树节点,因此该接口需要继承自定义的树节点接口FileSystemBrowserTreeNode接口。FileSystemObject接口定义了文件系统对象的相关属性和方法,包括显示的名称、图标、对象类型(目录还是文件)、关联的连接处理对象、父对象等等。直接贴代码了:

1
/**
2
 * 定义文件系统对象接口
3
 * Created by fangyuzhong on 17-7-15.
4
 */
5
public  interface FileSystemObject extends FileSystemBrowserTreeNode,DynamicContentElement,
6
        Referenceable, PresentableConnectionProvider
7
{
8
    /**
9
     * 获取文件系统对象类型
10
     *
11
     * @return
12
     */
13
    FileSystemObjectType getObjectType();
14
    /**
15
     * 获取文件系统对象的名称
16
     *
17
     * @return
18
     */
19
    @NotNull
20
    String getName();
21
    /**
22
     * 文件系统对象是否加载过
23
     *
24
     * @return
25
     */
26
    int getOverload();
27
28
    /**
29
     * 获取文件系统对象的类型名称
30
     *
31
     * @return
32
     */
33
    String getTypeName();
34
35
    /**
36
     * 获取文件系统对象的图标
37
     *
38
     * @return
39
     */
40
    @Nullable
41
    Icon getIcon();
42
    /**
43
     * 获取文件系统对象的连接处理对象
44
     *
45
     * @return
46
     */
47
    @NotNull
48
    ConnectionHandler getConnectionHandler();
49
    /**
50
     * 获取文件系统对象的父对象
51
     *
52
     * @return
53
     */
54
    FileSystemObject getParentObject();
55
    /**
56
     * 获取文件系统对象的集合
57
     *
58
     * @return
59
     */
60
    @NotNull
61
    FileSystemObjectBundle getObjectBundle();
62
    /*
63
     * 获取导航默认对象
64
     *
65
     * @return
66
     */
67
    @Nullable
68
    FileSystemObject getDefaultNavigationObject();
69
    /**
70
     * 获取未能进行释放的文件系统对象
71
     *
72
     * @return
73
     */
74
    @Nullable
75
    FileSystemObject getUndisposedElement();
76
    /**
77
     * 获取文件系统对象的属性
78
     *
79
     * @return
80
     */
81
    FileSystemObjectProperties getProperties();
82
    /**
83
     * 获取文件系统对象可呈现的属性集合
84
     *
85
     * @return
86
     */
87
    List<PresentableProperty> getPresentableProperties();
88
    /**
89
     * 获取文件系统对象的引用
90
     *
91
     * @return
92
     */
93
    FileSystemObjectRef getRef();
94
    /**
95
     * 对象是否已验证
96
     *
97
     * @return
98
     */
99
    boolean isValid();
100
    /**
101
     * 获取文件系统对象的父对象
102
     *
103
     * @return
104
     */
105
    @NotNull
106
    FileSystemBrowserTreeNode getParent();
107
}

HDFS根目录对象FileSystemObjectBundle接口定义

  我们把HDFS根目录”/“ 下的对象(目录也好文件也好)单独拿出来,定义成FileSystemObjectBundle,这样设计是为后面读取HDFS对象方便绑定到UI上进行显示,他也是TreeNode,因此也继承了FileSystemBrowserTreeNode,他只是个标志,并拥有 获取根节点对象的数据连接处理对象。代码如下:

1
/**
2
 * 定义文件系统对象的集合,这里特指HDFS中的根目录对象"/"
3
 * Created by fangyuzhong on 17-7-15.
4
 */
5
 public interface FileSystemObjectBundle
6
        extends FileSystemBrowserTreeNode, Disposable
7
{
8
    /**
9
     * 获取文件系统连接对象
10
     * @return
11
     */
12
    ConnectionHandler getConnectionHandler();
13
}

文件系统对象的抽象实现 FileSystemObjectImpl

抽象实现类中,有两个构造函数:

1、该构造函数以文件系统对象的父对象、HDFS的FIleStatus和对象的名称为参数

1
/**
2
 * 初始化文件系统对象
3
 * @param parentObject 父对象
4
 * @param HDFSFileStatus HDFS的文件状态对象
5
 * @param name 对象的名称
6
 */
7
protected FileSystemObjectImpl(FileSystemObject parentObject,
8
                               org.apache.hadoop.fs.FileStatus HDFSFileStatus, String name)
9
{
10
    this.connectionHandlerRef = ConnectionHandlerRef.from(parentObject.getConnectionHandler());
11
    this.parentObjectRef = FileSystemObjectRef.from(parentObject);
12
    this.name = name;
13
    init(HDFSFileStatus,null);
14
}

2、该构造函数以文件系统对象连接处理对象、HDFS的FIleStatus和对象的名称为参数,当读取HDFS的根目录“/”对象的时候,调用该构造函数,除此之外,调用构造函数1

1
/**
2
 * 初始化文件系统对象
3
 * @param connectionHandler 文件对象的连接处理类
4
 * @param HDFSFileStatus  HDFS的文件状态对象
5
 * @param name 对象的名称
6
 */
7
protected FileSystemObjectImpl(ConnectionHandler connectionHandler,
8
                               org.apache.hadoop.fs.FileStatus HDFSFileStatus, String name)
9
{
10
    this.connectionHandlerRef = ConnectionHandlerRef.from(connectionHandler);
11
    this.name = name;
12
    init(HDFSFileStatus,connectionHandler);
13
}

方法 init(org.apache.hadoop.fs.FileStatus HDFSFileStatus,ConnectionHandler connectionHandler),构建对象的引用,并且读取对象的相关信息,目录或文件的创建者、文件目录大小、文件目录路径等等。

1
/**
2
 * 初始化,获取HDFS系统的对象
3
 * @param HDFSFileStatus
4
 * @param connectionHandler
5
 */
6
private void init(org.apache.hadoop.fs.FileStatus HDFSFileStatus,ConnectionHandler connectionHandler)
7
{
8
    FileSystemObjectType fileSystemObjectType = HDFSFileStatus.isDirectory()? FileSystemObjectType.DIRECTORY: FileSystemObjectType.FILE;
9
    this.objectRef = new FileSystemObjectRef(this, fileSystemObjectType,connectionHandler);
10
    fileSystemInform = HDFSUtil.getFileSystemInformation(HDFSFileStatus);
11
}

内部构建子对象

  获取该对象的全部子对象,使用多线程的方式,获取其子对象,调用抽象方法(该抽象方法在具体的对象实现类中去重写) :

1
public abstract List<FileSystemBrowserTreeNode> buildAllPossibleTreeChildren();
2
public List<? extends FileSystemBrowserTreeNode> getChildren()
3
{
4
    if (this.visibleTreeChildren == null)
5
    {
6
        synchronized (this)
7
        {
8
            if (this.visibleTreeChildren == null)
9
            {
10
                this.visibleTreeChildren = new ArrayList();
11
                this.visibleTreeChildren.add(new LoadInProgressTreeNode(this));
12
                ConnectionHandler connectionHandler = getConnectionHandler();
13
                String connectionString = connectionHandler == null ? "" : " (" + connectionHandler.getName() + ")";
14
                new BackgroundTask(getProject(), "Loading data " + connectionString, true)
15
                {
16
                    public void execute(@NotNull ProgressIndicator progressIndicator)
17
                    {
18
                        buildTreeChildren(false);
19
                    }
20
                }.start();
21
            }
22
        }
23
    }
24
    return this.visibleTreeChildren;
25
}

  内部构建子对象:首先获取全部可能的对象,然后遍历对象,进行对象的初始化,判断是否是加载数据节点,是的话,删除该节点,并设置该对象的子对象加载完毕标志,最后,触发通知,TreeNode已经修改,需要重新加载该对象。

1
private void buildTreeChildren(boolean isreBuild)
2
{
3
    FailsafeUtil.check(this);
4
    List<FileSystemBrowserTreeNode> allPossibleTreeChildren = getAllPossibleTreeChildren(isreBuild);
5
    List<FileSystemBrowserTreeNode> newTreeChildren = allPossibleTreeChildren;
6
    if (allPossibleTreeChildren.size() > 0)
7
    {
8
        newTreeChildren = new ArrayList(newTreeChildren);
9
        for (FileSystemBrowserTreeNode treeNode : newTreeChildren)
10
        {
11
            FileSystemObject objectList = (FileSystemObject) treeNode;
12
            objectList.initTreeElement();
13
            FailsafeUtil.check(this);
14
        }
15
        if ((this.visibleTreeChildren.size() == 1) && ((this.visibleTreeChildren.get(0) instanceof LoadInProgressTreeNode)))
16
        {
17
            this.visibleTreeChildren.get(0).dispose();
18
        }
19
    }
20
    this.visibleTreeChildren = newTreeChildren;
21
    this.treeChildrenLoaded = true;
22
    //通知TreeNode修改,需要重新加载
23
    Project project = FailsafeUtil.get(getProject());
24
    ( EventUtil.notify(project, BrowserTreeEventListener.TOPIC)).nodeChanged(this, TreeEventType.STRUCTURE_CHANGED);
25
    FileSystemBrowserManager.scrollToSelectedElement(getConnectionHandler());
26
}

HDFS的目录和文件对象的实现 HadoopDirectoryObject 、HadoopFileObject

HDFS目录对象的实现HadoopDirectoryObject。

  继承抽象类FileSystemObjectImpl和,重写对象类型、HDFS目录所在的路径、获取目录对象的子对象。代码如下:

1
/**
2
 * 定义HDFS目录对象
3
 * Created by fangyuzhong on 17-7-17.
4
 */
5
public class HadoopDirectoryObject extends FileSystemObjectImpl
6
{
7
   private List<FileSystemBrowserTreeNode> fileSystemBrowserTreeNodeLists =null;
8
   private org.apache.hadoop.fs.FileStatus fileStatus=null;
9
    /**
10
     * 初始化 HDFS目录对象
11
     * @param parentObject 父对象
12
     * @param resultSet HDFS的FileStatus
13
     * @param name 对象的名称
14
     */
15
    public HadoopDirectoryObject(FileSystemObject parentObject,
16
                                 org.apache.hadoop.fs.FileStatus resultSet, String name)
17
    {
18
        super(parentObject,resultSet,name);
19
        fileStatus = resultSet;
20
    }
21
    /**
22
     * 初始化HDFS目录对象
23
     * @param connectionHandler 对象的连接
24
     * @param resultSet HDFS的FileStatus
25
     * @param name 对象的名称
26
     */
27
    public HadoopDirectoryObject(ConnectionHandler connectionHandler,
28
                                 org.apache.hadoop.fs.FileStatus resultSet, String name)
29
    {
30
        super(connectionHandler,resultSet,name);
31
        fileStatus = resultSet;
32
        fileSystemBrowserTreeNodeLists = new ArrayList();
33
    }
34
    /**
35
     * 获取对象的类型 这里是目录
36
     * @return
37
     */
38
   public FileSystemObjectType getObjectType()
39
    {
40
        return FileSystemObjectType.DIRECTORY;
41
    }
42
43
    /**
44
     * 获取目录对象的HDFS路径
45
     * @return
46
     */
47
    public String getLocationString()
48
    {
49
        return fileStatus.getPath().toString();
50
    }
51
    /**
52
     * 重写,构建目录的下面的子对象
53
     * @return
54
     */
55
   public List<FileSystemBrowserTreeNode> buildAllPossibleTreeChildren()
56
   {
57
      ConnectionHandler connectionHandler = getConnectionHandler();
58
      FileSystem fileSystem = connectionHandler.getMainFileSystem();
59
       try
60
       {
61
           String path = fileStatus.getPath().toString();
62
           FileStatus[] fileStatuses = fileSystem.listStatus(new Path(fileStatus.getPath().toString()));
63
           FileSystemBrowserTreeNode[] fileSystemBrowserTreeNodes = new FileSystemBrowserTreeNode[fileStatuses.length];
64
           for (int i = 0; i < fileStatuses.length; i++)
65
           {
66
               FileStatus f = fileStatuses[i];
67
               if (f.isDirectory())
68
               {
69
                   FileSystemObject dirdbObject = new HadoopDirectoryObject(this, f,f.getPath().getName());
70
                   fileSystemBrowserTreeNodes[i] = dirdbObject;
71
               } else
72
               {
73
                   FileSystemObject filedbObject = new HadoopFileObject(this, f,f.getPath().getName());
74
                   fileSystemBrowserTreeNodes[i] = filedbObject;
75
               }
76
           }
77
           fileSystemBrowserTreeNodeLists = FileSystemBrowserUtils.createList(fileSystemBrowserTreeNodes);
78
       }
79
       catch (Exception ex)
80
       {
81
82
       }
83
       return fileSystemBrowserTreeNodeLists;
84
   }
85
}

HDFS的文件对象的实现HadoopFileObject。

  和目录实现一样,唯一区别是 对象类型是文件类型并且文件是没有子对象的,但也要重写:
public List buildAllPossibleTreeChildren()
并且不能返回NULL。 代码如下:

1
/**
2
 * 定义HDFS文件对象
3
 * Created by fangyuzhong on 17-7-17.
4
 */
5
public class HadoopFileObject extends FileSystemObjectImpl
6
{
7
   private List<FileSystemBrowserTreeNode> fileSystemBrowserTreeNodes =null;
8
   private FileStatus fileStatus;
9
    /**
10
     * 初始化HDFS文件对象
11
     * @param parentObject 父对象
12
     * @param resultSet HDFS的FIleStatus
13
     * @param name 文件名称
14
     */
15
    public HadoopFileObject(FileSystemObject parentObject,
16
                            org.apache.hadoop.fs.FileStatus resultSet, String name)
17
    {
18
        super(parentObject, resultSet,name);
19
        fileSystemBrowserTreeNodes = new ArrayList();
20
        fileStatus = resultSet;
21
    }
22
    /**
23
     * 初始化HDFS的文件对象
24
     * @param connectionHandler 连接处理对象
25
     * @param resultSet HDFS的FIleStatus
26
     * @param name 文件名称
27
     */
28
    public HadoopFileObject(ConnectionHandler connectionHandler,
29
                            org.apache.hadoop.fs.FileStatus resultSet, String name)
30
    {
31
        super(connectionHandler, resultSet,name);
32
        fileSystemBrowserTreeNodes = new ArrayList();
33
        fileStatus = resultSet;
34
    }
35
    /**
36
     * 获取HDFS文件所在的路径
37
     * @return
38
     */
39
    public String getLocationString()
40
    {
41
        return fileStatus.getPath().toString();
42
    }
43
    /**
44
     * 获取对象类型,这里是文件
45
     * @return
46
     */
47
    public FileSystemObjectType getObjectType()
48
    {
49
        return FileSystemObjectType.FILE;
50
    }
51
    /**
52
     * 文件没有子对象,但不能给NULL
53
     * @return
54
     */
55
    public List<FileSystemBrowserTreeNode> buildAllPossibleTreeChildren()
56
    {
57
        return fileSystemBrowserTreeNodes;
58
    }
59
}

HDFS的根目录对象的实现FileSystemObjectBundleImpl。

  该类继承树节点的抽象类FileSystemBrowserTreeNodeBase和FileSystemObjectBundle接口。该类,重点关注,怎么读取HDFS的根目录“/”对象,获取其数据进行绑定的。该类只有一个构造函数,在构造函数中通过 loadData()开始HDFS根目录的数据加载。

1
/**
2
 * 初始化
3
 * @param connectionHandler 连接处理接口
4
 * @param treeParent 父节点
5
 */
6
public FileSystemObjectBundleImpl(ConnectionHandler connectionHandler, FileSystemBrowserTreeNode treeParent)
7
{
8
    this.connectionHandler = connectionHandler;
9
    this.treeParent = treeParent;
10
    loadData();
11
}
12
/**
13
 * 重新加载数据
14
 */
15
public void loadData()
16
{
17
    //获取根节点下的所有文件和目录 创建 节点
18
    fileSystem = connectionHandler.getMainFileSystem();
19
    if(connectionHandler.getConnectionStatus().isConnected())
20
    {
21
        try
22
        {
23
            if( this.allPossibleTreeChildren!=null)
24
            {
25
                this.allPossibleTreeChildren.clear();
26
            }
27
            FileStatus[] fileStatuses = fileSystem.listStatus(new Path("/"));
28
            FileSystemBrowserTreeNode[] fileSystemBrowserTreeNodes = new FileSystemBrowserTreeNode[fileStatuses.length];
29
            for (int i = 0; i < fileStatuses.length; i++)
30
            {
31
                FileStatus f = fileStatuses[i];
32
                if (f.isDirectory())
33
                {
34
                    //如果是目录,实例化目录对象
35
                    FileSystemObject dirdbObject = new HadoopDirectoryObject(connectionHandler, f, f.getPath().getName());
36
                    fileSystemBrowserTreeNodes[i] = dirdbObject;
37
                } else
38
                {
39
                    //如果是文件,实例化文件对象
40
                    FileSystemObject filedbObject = new HadoopFileObject(connectionHandler, f, f.getPath().getName());
41
                    fileSystemBrowserTreeNodes[i] = filedbObject;
42
                }
43
            }
44
            this.allPossibleTreeChildren = FileSystemBrowserUtils.createList(fileSystemBrowserTreeNodes);
45
        }
46
        catch (Exception ex)
47
        {
48
        }
49
    }
50
    else
51
    {
52
        if( this.allPossibleTreeChildren!=null)
53
        {
54
            this.allPossibleTreeChildren.clear();
55
        }
56
    }
57
}
----------------------- 本文结束 感谢阅读 -----------------------
坚持原创技术分享,您的支持将鼓励我继续创作!