View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.openr66.protocol.utils;
21  
22  import org.waarp.common.command.exception.CommandAbstractException;
23  import org.waarp.common.digest.FilesystemBasedDigest;
24  import org.waarp.common.digest.FilesystemBasedDigest.DigestAlgo;
25  import org.waarp.common.file.AbstractDir;
26  import org.waarp.common.logging.WaarpLogger;
27  import org.waarp.openr66.context.R66Session;
28  import org.waarp.openr66.context.filesystem.R66File;
29  import org.waarp.openr66.context.task.exception.OpenR66RunnerErrorException;
30  
31  import java.io.IOException;
32  import java.security.NoSuchAlgorithmException;
33  
34  /**
35   * File Utils
36   */
37  public final class FileUtils {
38  
39    private static final byte[] EMPTY_ARRAY = {};
40  
41    private FileUtils() {
42    }
43  
44    /**
45     * Change or create the R66File associated with the context
46     *
47     * @param logger
48     * @param session
49     * @param filenameSrc new filename
50     * @param isPreStart
51     * @param isSender
52     * @param isThrough
53     * @param file old R66File if any (might be null)
54     *
55     * @return the R66File
56     *
57     * @throws OpenR66RunnerErrorException
58     */
59    public static R66File getFile(final WaarpLogger logger,
60                                  final R66Session session,
61                                  final String filenameSrc,
62                                  final boolean isPreStart,
63                                  final boolean isSender, final boolean isThrough,
64                                  R66File file)
65        throws OpenR66RunnerErrorException {
66      String filename;
67      logger.debug("PreStart: {}", isPreStart);
68      logger.debug("Dir is: {}", session.getDir().getFullPath());
69      logger.debug("File is: {}", filenameSrc);
70      if (isPreStart) {
71        filename = AbstractDir.normalizePath(filenameSrc);
72        filename = AbstractDir.pathFromURI(filename);
73        logger.debug("File becomes: {}", filename);
74      } else {
75        filename = filenameSrc;
76      }
77      if (isSender) {
78        try {
79          if (file == null) {
80            try {
81              file = (R66File) session.getDir().setFile(filename, false);
82            } catch (final CommandAbstractException e) {
83              logger.warn("File not placed in normal directory" + " : {}",
84                          e.getMessage());
85              // file is not under normal base directory, so is external
86              // File should already exist but can be using special code ('*?')
87              file = session.getDir().setFileNoCheck(filename);
88            }
89          }
90          if (isThrough) {
91            // no test on file since it does not really exist
92            logger.debug("File is in through mode: {}", file);
93          } else if (!file.canRead()) {
94            logger.debug(
95                "File {} cannot be read, so try external from " + filename, file);
96            // file is not under normal base directory, so is external
97            // File should already exist but cannot use special code ('*?')
98            final R66File file2 =
99                new R66File(session, session.getDir(), filename);
100           if (!file2.canRead()) {
101             throw new OpenR66RunnerErrorException(
102                 "File cannot be read: " + file.getTrueFile().getAbsolutePath());
103           }
104           file = file2;
105         }
106       } catch (final CommandAbstractException e) {
107         throw new OpenR66RunnerErrorException(e);
108       }
109     } else {
110       // not sender so file is just registered as is but no test of existence
111       file = new R66File(session, session.getDir(), filename);
112     }
113     return file;
114   }
115 
116   /**
117    * @param buffer
118    * @param size
119    * @param algo for packet only
120    * @param digestGlobal
121    *
122    * @return the hash from the given Buffer
123    */
124   public static byte[] getHash(final byte[] buffer, final int size,
125                                final DigestAlgo algo,
126                                final FilesystemBasedDigest digestGlobal) {
127     if (buffer == null || size == 0) {
128       return EMPTY_ARRAY;
129     }
130     final byte[] newkey;
131     try {
132       if (digestGlobal == null) {
133         newkey = FilesystemBasedDigest.getHash(buffer, size, algo);
134       } else {
135         final FilesystemBasedDigest digestPacket =
136             new FilesystemBasedDigest(algo);
137         digestPacket.Update(buffer, 0, size);
138         newkey = digestPacket.Final();
139         digestGlobal.Update(buffer, 0, size);
140       }
141     } catch (final IOException e) {
142       return EMPTY_ARRAY;
143     } catch (final NoSuchAlgorithmException e) {
144       return EMPTY_ARRAY;
145     }
146     return newkey;
147   }
148 
149   /**
150    * Compute global hash and local hash (if possible)
151    *
152    * @param digestGlobal
153    * @param digestLocal
154    * @param buffer
155    * @param size size of the buffer
156    */
157   public static void computeGlobalHash(final FilesystemBasedDigest digestGlobal,
158                                        final FilesystemBasedDigest digestLocal,
159                                        final byte[] buffer, final int size) {
160     if (buffer == null || size == 0) {
161       return;
162     }
163     if (digestGlobal != null) {
164       digestGlobal.Update(buffer, 0, size);
165     }
166     if (digestLocal != null) {
167       digestLocal.Update(buffer, 0, size);
168     }
169   }
170 }