001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.fabric.netty.fileserver.handlers;
016    
017    import com.liferay.portal.fabric.netty.fileserver.CompressionLevel;
018    import com.liferay.portal.fabric.netty.fileserver.FileHelperUtil;
019    import com.liferay.portal.fabric.netty.fileserver.FileRequest;
020    import com.liferay.portal.fabric.netty.fileserver.FileResponse;
021    
022    import io.netty.channel.ChannelHandlerContext;
023    import io.netty.channel.DefaultFileRegion;
024    import io.netty.channel.SimpleChannelInboundHandler;
025    
026    import java.io.IOException;
027    
028    import java.nio.channels.FileChannel;
029    import java.nio.file.Files;
030    import java.nio.file.NoSuchFileException;
031    import java.nio.file.Path;
032    import java.nio.file.StandardOpenOption;
033    import java.nio.file.attribute.BasicFileAttributes;
034    import java.nio.file.attribute.FileTime;
035    
036    /**
037     * @author Shuyang Zhou
038     */
039    public class FileRequestChannelHandler
040            extends SimpleChannelInboundHandler<FileRequest> {
041    
042            public static final String NAME = FileRequestChannelHandler.class.getName();
043    
044            public FileRequestChannelHandler(CompressionLevel compressionLevel) {
045                    _compressionLevel = compressionLevel;
046            }
047    
048            @Override
049            protected void channelRead0(
050                            ChannelHandlerContext channelHandlerContext,
051                            FileRequest fileRequest)
052                    throws IOException {
053    
054                    Path path = fileRequest.getPath();
055    
056                    BasicFileAttributes basicFileAttributes = null;
057    
058                    try {
059                            basicFileAttributes = Files.readAttributes(
060                                    path, BasicFileAttributes.class);
061                    }
062                    catch (NoSuchFileException nsfe) {
063                            channelHandlerContext.writeAndFlush(
064                                    new FileResponse(path, FileResponse.FILE_NOT_FOUND, -1, false));
065    
066                            return;
067                    }
068    
069                    FileTime fileTime = basicFileAttributes.lastModifiedTime();
070    
071                    if (fileTime.toMillis() <= fileRequest.getLastModifiedTime()) {
072                            channelHandlerContext.writeAndFlush(
073                                    new FileResponse(
074                                            path, FileResponse.FILE_NOT_MODIFIED, -1, false));
075    
076                            return;
077                    }
078    
079                    FileChannel fileChannel = null;
080    
081                    if (basicFileAttributes.isDirectory()) {
082                            fileChannel = FileChannel.open(
083                                    FileHelperUtil.zip(
084                                            path, FileHelperUtil.TEMP_DIR_PATH, _compressionLevel),
085                                    StandardOpenOption.DELETE_ON_CLOSE);
086    
087                            if (fileRequest.isDeleteAfterFetch()) {
088                                    FileHelperUtil.delete(path);
089                            }
090                    }
091                    else if (fileRequest.isDeleteAfterFetch()) {
092                            fileChannel = FileChannel.open(
093                                    path, StandardOpenOption.DELETE_ON_CLOSE);
094                    }
095                    else {
096                            fileChannel = FileChannel.open(path);
097                    }
098    
099                    channelHandlerContext.write(
100                            new FileResponse(
101                                    path, fileChannel.size(), fileTime.toMillis(),
102                                    basicFileAttributes.isDirectory()));
103    
104                    channelHandlerContext.writeAndFlush(
105                            new DefaultFileRegion(fileChannel, 0, fileChannel.size()));
106            }
107    
108            private final CompressionLevel _compressionLevel;
109    
110    }