jx/internal/transport/file.go

247 lines
5.3 KiB
Go
Raw Permalink Normal View History

2024-07-01 07:16:55 +00:00
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
package transport
import (
_ "errors"
"path/filepath"
"io"
"io/fs"
2024-07-01 07:16:55 +00:00
"os"
"net/url"
"strings"
"fmt"
"compress/gzip"
"log/slog"
"decl/internal/ext"
2024-07-01 07:16:55 +00:00
)
type File struct {
uri *url.URL
path string
exttype string
fileext string
readHandle *os.File
writeHandle *os.File
gzip bool
gzipWriter io.WriteCloser
gzipReader io.ReadCloser
}
type FileReader struct {
*File
readHandle *os.File
gzipReader io.ReadCloser
}
type FileWriter struct {
*File
writeHandle *os.File
gzipWriter io.WriteCloser
}
2024-07-17 08:19:55 +00:00
func FilePath(u *url.URL) string {
return filepath.Join(u.Hostname(), u.Path)
2024-07-17 08:19:55 +00:00
}
func FileExists(u *url.URL) bool {
_, err := os.Stat(FilePath(u))
return !os.IsNotExist(err)
}
func NewFileReader(u *url.URL) (f *FileReader, err error) {
f = &FileReader {
File: &File {
uri: u,
path: FilePath(u),
},
}
f.extension()
f.DetectGzip()
exists := FileExists(u)
slog.Info("transport.NewFileReader()", "uri", u, "path", f.Path(), "file", f, "error", err, "exists", exists)
if f.Path() == "" || f.Path() == "-" {
f.readHandle = os.Stdin
} else {
if f.readHandle, err = os.Open(f.Path()); err == nil {
var fi fs.FileInfo
fi, err = f.readHandle.Stat()
if fi.IsDir() {
f.readHandle.Close()
f.readHandle = nil
err = fmt.Errorf("is a directory")
}
}
if err != nil {
slog.Info("transport.NewFileReader()", "file", f, "path", f.Path(), "error", err)
return
}
}
if f.Gzip() {
if exists {
if f.gzipReader, err = gzip.NewReader(f.readHandle); err != nil {
return
}
}
}
slog.Info("transport.NewFileReader() - created reader transport", "uri", u, "file", f, "error", err)
return
}
func NewFileWriter(u *url.URL) (f *FileWriter, err error) {
f = &FileWriter {
File: &File {
uri: u,
path: FilePath(u),
},
}
f.extension()
f.DetectGzip()
slog.Info("transport.NewFileWriter()", "file", f.File)
exists := FileExists(u)
slog.Info("transport.NewFileWriter()", "file", f, "error", err, "exists", exists)
if f.Path() == "" || f.Path() == "-" {
f.writeHandle = os.Stdout
} else {
if f.writeHandle, err = os.OpenFile(f.Path(), os.O_RDWR|os.O_CREATE, 0644); err != nil {
slog.Info("transport.NewFileWriter()", "file", f, "path", f.Path(), "error", err)
return
}
}
if f.Gzip() {
f.gzipWriter = ext.WriteAddCloser(gzip.NewWriter(f.writeHandle), func() error { return f.writeHandle.Close() })
}
slog.Info("transport.NewFileWriter()", "file", f, "error", err)
return
2024-07-17 08:19:55 +00:00
}
2024-07-01 07:16:55 +00:00
func NewFile(u *url.URL) (f *File, err error) {
f = &File {
uri: u,
2024-07-17 08:19:55 +00:00
path: FilePath(u),
2024-07-01 07:16:55 +00:00
}
f.extension()
f.DetectGzip()
exists := FileExists(u)
slog.Info("transport.NewFile()", "file", f, "error", err, "exists", exists)
2024-07-01 07:16:55 +00:00
if f.path == "" || f.path == "-" {
f.readHandle = os.Stdin
f.writeHandle = os.Stdout
} else {
if f.readHandle, err = os.OpenFile(f.Path(), os.O_RDWR|os.O_CREATE, 0644); err != nil {
slog.Info("transport.NewFile()", "file", f, "path", f.Path(), "error", err)
2024-07-01 07:16:55 +00:00
return
}
f.writeHandle = f.readHandle
}
if f.Gzip() {
f.gzipWriter = ext.WriteAddCloser(gzip.NewWriter(f.writeHandle), func() error { return f.writeHandle.Close() })
if exists {
if f.gzipReader, err = gzip.NewReader(f.readHandle); err != nil {
return
}
2024-07-01 07:16:55 +00:00
}
}
slog.Info("transport.NewFile()", "file", f, "error", err)
2024-07-01 07:16:55 +00:00
return
}
func (f *File) extension() {
elements := strings.Split(f.path, ".")
numberOfElements := len(elements)
2024-07-17 08:19:55 +00:00
if numberOfElements > 1 {
if numberOfElements > 2 {
f.exttype = elements[numberOfElements - 2]
f.fileext = elements[numberOfElements - 1]
} else {
f.exttype = elements[numberOfElements - 1]
2024-07-17 08:19:55 +00:00
}
2024-07-01 07:16:55 +00:00
}
}
func (f *File) DetectGzip() {
f.gzip = (f.uri.Query().Get("gzip") == "true" || f.fileext == "gz" || f.exttype == "tgz" || f.exttype == "gz" || f.fileext == "tgz")
2024-07-01 07:16:55 +00:00
}
func (f *File) URI() *url.URL {
return f.uri
}
func (f *File) Path() string {
return f.path
}
func (f *File) Signature() (documentSignature string) {
if signatureResp, signatureErr := os.Open(fmt.Sprintf("%s.sig", f.uri.String())); signatureErr == nil {
defer signatureResp.Close()
readSignatureBody, readSignatureErr := io.ReadAll(signatureResp)
if readSignatureErr == nil {
documentSignature = string(readSignatureBody)
} else {
panic(readSignatureErr)
}
} else {
panic(signatureErr)
}
return documentSignature
}
func (f *File) ContentType() string {
var ext strings.Builder
2024-07-17 08:19:55 +00:00
if f.uri.Scheme != "file" {
return f.uri.Scheme
}
if f.fileext == "" {
return f.exttype
}
ext.WriteString(f.exttype)
ext.WriteRune('.')
ext.WriteString(f.fileext)
return ext.String()
}
func (f *File) Stat() (fs.FileInfo, error) {
return f.FileInfo()
}
func (f *File) FileInfo() (info fs.FileInfo, err error) {
return os.Lstat(f.Path())
2024-07-01 07:16:55 +00:00
}
func (f *File) SetGzip(gzip bool) {
f.gzip = gzip
}
func (f *File) Gzip() bool {
return f.gzip
}
func (f *FileReader) Reader() io.ReadCloser {
2024-07-01 07:16:55 +00:00
if f.Gzip() {
var err error
if f.gzipReader, err = gzip.NewReader(f.readHandle); err != nil {
panic(err)
}
2024-07-01 07:16:55 +00:00
return f.gzipReader
}
return f.readHandle
}
func (f *FileWriter) Writer() io.WriteCloser {
2024-07-01 07:16:55 +00:00
if f.Gzip() {
f.gzipWriter = gzip.NewWriter(f.writeHandle)
2024-07-01 07:16:55 +00:00
return f.gzipWriter
}
return f.writeHandle
}
func (f *File) ReadWriter() io.ReadWriteCloser {
return f.writeHandle
}