# HG changeset patch # User František Kučera # Date 1702600577 -3600 # Node ID 1ab5ce94a146093520a26bfed29d5bd18a58800a # Parent d511e4bf7d8f1b41e7d3b1e1cb1d492791709f1a konfigurace, parser CLI parametrů diff -r d511e4bf7d8f -r 1ab5ce94a146 java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/CLIParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/CLIParser.java Fri Dec 15 01:36:17 2023 +0100 @@ -0,0 +1,173 @@ +/** + * Rozšířené atributy – program na správu rozšířených atributů souborů + * Copyright © 2023 František Kučera (frantovo.cz) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package cz.frantovo.rozsireneatributy; + +import cz.frantovo.rozsireneatributy.Konfigurace.DefiniceAtributu; +import cz.frantovo.rozsireneatributy.Konfigurace.DefiniceHodnoty; +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.ResourceBundle; + +/** + * Converts command line arguments from String array to object. Checks basic + * constraints (if only supported options are used and if they have correct + * number of parameters) + * + * @author Ing. František Kučera (frantovo.cz) + */ +public class CLIParser { + + private static final ResourceBundle překlady = ResourceBundle + .getBundle(Atribut.class.getPackageName() + ".Překlady"); + + public Konfigurace parsujParametry(String[] parametry) + throws CLIParserException { + Konfigurace k = new Konfigurace(); + + for (int i = 0; i < parametry.length; i++) { + String parametr = parametry[i]; + + boolean odpovídá = false; + + for (Token t : Token.values()) { + if (t.odpovídá(parametr)) { + int parsedArgs = t.parsuj(parametry, i, k); + i = i + parsedArgs; + odpovídá = true; + } + } + + if (!odpovídá) { + throw new CLIParserException( + překlady.getString("chyba.cli.neznámýParametr") + parametr); + } + } + + if (k.getSoubor() == null) + throw new CLIParserException( + překlady.getString("chyba.cli.chybíSoubor")); + + return k; + } + + private static String načtiDalší(String[] parametry, int index) + throws CLIParserException { + if (index < parametry.length) { + return parametry[index]; + } else { + throw new CLIParserException("Expecting value for option: " + + parametry[index - 1]); + } + } + + private static boolean načtiDalšíBoolean(String[] parametry, int index) + throws CLIParserException { + String s = načtiDalší(parametry, index); + switch (s) { + case "true": + case "ano": + return true; + case "false": + case "ne": + return false; + default: + throw new CLIParserException("Neplatná logická hodnota: " + s); + } + } + + private static enum Token { + + SOUBOR("--soubor", "--file") { + @Override + public int parsuj(String[] parametry, int index, Konfigurace k) + throws CLIParserException { + int originalIndex = index; + k.setSoubor(new File(načtiDalší(parametry, ++index))); + return index - originalIndex; + } + }, + POVINNÉ_ZAMYKÁNÍ("--povinné-zamykání", "--mandatory-locking") { + @Override + public int parsuj(String[] parametry, int index, Konfigurace k) + throws CLIParserException { + int originalIndex = index; + k.setPovinnéZamykání(načtiDalšíBoolean(parametry, ++index)); + return index - originalIndex; + } + }, + DEFINICE_ATRIBUTU("--definice-atributu", "--attribute-definition") { + @Override + public int parsuj(String[] parametry, int index, Konfigurace k) + throws CLIParserException { + int originalIndex = index; + String název = načtiDalší(parametry, ++index); + String popis = načtiDalší(parametry, ++index); + k.addAtribut(new DefiniceAtributu(název, popis)); + return index - originalIndex; + } + }, + HODNOTA_ATRIBUTU("--hodnota", "--value") { + @Override + public int parsuj(String[] parametry, int index, Konfigurace k) + throws CLIParserException { + int originalIndex = index; + String hodnota = načtiDalší(parametry, ++index); + String popis = načtiDalší(parametry, ++index); + + if (k.getAtributy().isEmpty()) + throw new CLIParserException( + překlady.getString("chyba.cli.chybíDefiniceAtributu")); + + k.getAtributy() + .get(k.getAtributy().size() - 1) + .addHodnota(new DefiniceHodnoty(hodnota, popis)); + + return index - originalIndex; + } + }; + + private final Collection parametry; + + private Token(String... parametry) { + this.parametry = Arrays.asList(parametry); + } + + /** + * @param parametr e.g. „--input-file“ + * @return whether option is this token + */ + public boolean odpovídá(String parametr) { + return parametry.contains(parametr); + } + + /** + * Parse String arguments and fill values into the options object. + * + * @param parametry CLI arguments + * @param index index of the option matched by this token, like + * „--input-file“ + * @param k object to be filled + * @return number of parsed arguments – if option has no arguments (just + * boolean flag), return 0, otherwise return positive integer: number of + * eaten arguments. + * @throws CLIParserException + */ + public abstract int parsuj(String[] parametry, int index, Konfigurace k) + throws CLIParserException; + } +} diff -r d511e4bf7d8f -r 1ab5ce94a146 java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/CLIParserException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/CLIParserException.java Fri Dec 15 01:36:17 2023 +0100 @@ -0,0 +1,39 @@ +/** + * Rozšířené atributy – program na správu rozšířených atributů souborů + * Copyright © 2023 František Kučera (frantovo.cz) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package cz.frantovo.rozsireneatributy; + +/** + * + * @author Ing. František Kučera (frantovo.cz) + */ +public class CLIParserException extends Exception { + + public CLIParserException() { + } + + public CLIParserException(String message) { + super(message); + } + + public CLIParserException(Throwable cause) { + super(cause); + } + + public CLIParserException(String message, Throwable cause) { + super(message, cause); + } +} diff -r d511e4bf7d8f -r 1ab5ce94a146 java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Konfigurace.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Konfigurace.java Fri Dec 15 01:36:17 2023 +0100 @@ -0,0 +1,122 @@ +/** + * Rozšířené atributy – program na správu rozšířených atributů souborů + * Copyright © 2023 František Kučera (frantovo.cz) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package cz.frantovo.rozsireneatributy; + +import java.io.File; +import java.util.LinkedList; +import java.util.List; + +/** + * @author Ing. František Kučera (frantovo.cz) + */ +public class Konfigurace { + + public static class DefiniceAtributu { + + private String název; + private String popis; + private final List hodnoty = new LinkedList<>(); + + public DefiniceAtributu(String název, String popis) { + this.název = název; + this.popis = popis; + } + + public String getNázev() { + return název; + } + + public void setNázev(String název) { + this.název = název; + } + + public String getPopis() { + return popis; + } + + public void setPopis(String popis) { + this.popis = popis; + } + + public List getHodnoty() { + return hodnoty; + } + + public void addHodnota(DefiniceHodnoty hodnota) { + this.hodnoty.add(hodnota); + } + + } + + public static class DefiniceHodnoty { + + private String název; + private String popis; + + public DefiniceHodnoty(String název, String popis) { + this.název = název; + this.popis = popis; + } + + public String getNázev() { + return název; + } + + public void setNázev(String název) { + this.název = název; + } + + public String getPopis() { + return popis; + } + + public void setPopis(String popis) { + this.popis = popis; + } + } + + private File soubor; + + private boolean povinnéZamykání = false; + + private final List atributy = new LinkedList<>(); + + public File getSoubor() { + return soubor; + } + + public void setSoubor(File soubor) { + this.soubor = soubor; + } + + public boolean isPovinnéZamykání() { + return povinnéZamykání; + } + + public void setPovinnéZamykání(boolean povinnéZamykání) { + this.povinnéZamykání = povinnéZamykání; + } + + public List getAtributy() { + return atributy; + } + + public void addAtribut(DefiniceAtributu atribut) { + this.atributy.add(atribut); + } + +} diff -r d511e4bf7d8f -r 1ab5ce94a146 java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Překlady_cs.properties --- a/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Překlady_cs.properties Tue Dec 12 21:19:11 2023 +0100 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Překlady_cs.properties Fri Dec 15 01:36:17 2023 +0100 @@ -1,12 +1,15 @@ titulek=Roz\u0161\u00ed\u0159en\u00e9 stributy souboru: {0} +chyba=Chyba: chyba.titulek=Chyba chyba.souborNeexistuje=Soubor neexistuje: {0} -chyba.chyb\u00edParametr=O\u010dek\u00e1v\u00e1m pr\u00e1v\u011b jeden parametr \u2013 n\u00e1zev souboru. chyba.nepoda\u0159iloSeSmazat=Nepoda\u0159ilo se smazat atribut. chyba.nepoda\u0159iloSeNa\u010d\u00edst=Nepoda\u0159ilo se na\u010d\u00edst atributy. chyba.nepoda\u0159iloSeNastavitZ\u00e1mek=Nepoda\u0159ilo se nastavit z\u00e1mek. chyba.lzeZamknoutJenSoubor=Je podporov\u00e1no zamyk\u00e1n\u00ed pouze norm\u00e1ln\u00edch sobour\u016f ne adres\u00e1\u0159\u016f atd. +chyba.cli.nezn\u00e1m\u00fdParametr=Nezn\u00e1m\u00fd parametr: +chyba.cli.chyb\u00edDefiniceAtributu=Chyb\u00ed definice atributu (hodnota se vztahuje k n\u00ed). +chyba.cli.chyb\u00edSoubor=Nebyl uveden soubor. tabulka.n\u00e1zev=N\u00e1zev tabulka.hodnota=Hodnota diff -r d511e4bf7d8f -r 1ab5ce94a146 java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Překlady_en.properties --- a/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Překlady_en.properties Tue Dec 12 21:19:11 2023 +0100 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Překlady_en.properties Fri Dec 15 01:36:17 2023 +0100 @@ -1,12 +1,15 @@ titulek=Extended Attributes of file: {0} +chyba=Error: chyba.titulek=Error chyba.souborNeexistuje=File does not exist: {0} -chyba.chyb\u00edParametr=Expecting one parameter \u2013 file name. chyba.nepoda\u0159iloSeSmazat=Failed to delete the attribute. chyba.nepoda\u0159iloSeNa\u010d\u00edst=Failed to load attributes. chyba.nepoda\u0159iloSeNastavitZ\u00e1mek=Unable to lock the file. chyba.lzeZamknoutJenSoubor=File locking is supported only for regular files, not for directories or specials. +chyba.cli.nezn\u00e1m\u00fdParametr=Unknown option: +chyba.cli.chyb\u00edDefiniceAtributu=Missing attribute definition (value is associated with it). +chyba.cli.chyb\u00edSoubor=File name was not specified. tabulka.n\u00e1zev=Name tabulka.hodnota=Value diff -r d511e4bf7d8f -r 1ab5ce94a146 java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Startér.java --- a/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Startér.java Tue Dec 12 21:19:11 2023 +0100 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/Startér.java Fri Dec 15 01:36:17 2023 +0100 @@ -23,7 +23,6 @@ import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.io.File; -import java.io.IOException; import java.text.MessageFormat; import java.util.ResourceBundle; import java.util.logging.Level; @@ -39,11 +38,11 @@ * http://freedesktop.org/wiki/CommonExtendedAttributes * http://download.oracle.com/javase/tutorial/essential/io/fileAttr.html#user * http://today.java.net/pub/a/today/2008/07/03/jsr-203-new-file-apis.html - * #so-what-is-a-path-really + * #so-what-is-a-path-really * - * $ setfattr -n "user.franta.pozdrav" -v 'Dobrý den!' pokus.txt - * (v javě pak pracujeme s klíči bez předpony „user.“) - * + * $ setfattr -n "user.franta.pozdrav" -v 'Dobrý den!' pokus.txt (v javě pak + * pracujeme s klíči bez předpony „user.“) + * * @author Ing. František Kučera (frantovo.cz) */ public class Startér { @@ -55,18 +54,20 @@ /** * @param args název souboru - * @throws IOException TODO: ošetřit výjimku */ - public static void main(String[] args) throws IOException { + public static void main(String[] args) { + try { + // TODO: načítat konfiguraci i z XML souboru + CLIParser parser = new CLIParser(); + Konfigurace konfigurace = parser.parsujParametry(args); - if (args.length == 1 && args[0].length() > 0) { - File soubor = new File(args[0]); + File soubor = konfigurace.getSoubor(); if (soubor.exists()) { log.log(Level.INFO, "Pracuji se souborem: {0}", soubor); - Model model = new Model(soubor); + Model model = new Model(konfigurace); final JFrame f = new JFrame(); Panel p = new Panel(model); @@ -74,9 +75,10 @@ f.setLayout(new BorderLayout()); f.add(p, BorderLayout.CENTER); - /** Ukončení programu klávesou Escape */ + // Ukončení programu klávesou Escape: f.getRootPane().registerKeyboardAction(new ActionListener() { + @Override public void actionPerformed(ActionEvent ae) { f.dispose(); } @@ -94,8 +96,9 @@ ukončiChybou(MessageFormat.format(překlady .getString("chyba.souborNeexistuje"), soubor)); } - } else { - ukončiChybou(překlady.getString("chyba.chybíParametr")); + } catch (Exception e) { + log.log(Level.SEVERE, překlady.getString("chyba"), e); + ukončiChybou(e.getLocalizedMessage()); } } diff -r d511e4bf7d8f -r 1ab5ce94a146 java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/EditorNázvůAtributů.java --- a/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/EditorNázvůAtributů.java Tue Dec 12 21:19:11 2023 +0100 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/EditorNázvůAtributů.java Fri Dec 15 01:36:17 2023 +0100 @@ -16,6 +16,8 @@ */ package cz.frantovo.rozsireneatributy.gui; +import cz.frantovo.rozsireneatributy.Konfigurace; +import cz.frantovo.rozsireneatributy.Konfigurace.DefiniceAtributu; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -37,11 +39,13 @@ extends JComboBox implements TableCellEditor { + private final Konfigurace konfigurace; protected EventListenerList posluchače = new EventListenerList(); protected ChangeEvent událost = new ChangeEvent(this); - public EditorNázvůAtributů() { + public EditorNázvůAtributů(Konfigurace konfigurace) { super(); + this.konfigurace = konfigurace; setEditable(true); addActionListener(new ActionListener() { @@ -71,7 +75,7 @@ /** * TODO: * - další standardní atributy - * - konfigurovatelnost + * - načítat z XML souboru * * @see http://www.freedesktop.org/wiki/CommonExtendedAttributes */ @@ -85,7 +89,12 @@ } addItem((String) názevAtributu); setSelectedItem(názevAtributu); - + + for (DefiniceAtributu da : konfigurace.getAtributy()) { + addItem(da.getNázev()); + } + + if (!konfigurace.getAtributy().isEmpty()) return; // General attributes in current use addItem("mime_type"); diff -r d511e4bf7d8f -r 1ab5ce94a146 java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/Model.java --- a/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/Model.java Tue Dec 12 21:19:11 2023 +0100 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/Model.java Fri Dec 15 01:36:17 2023 +0100 @@ -1,22 +1,23 @@ /** * Rozšířené atributy – program na správu rozšířených atributů souborů * Copyright © 2012 František Kučera (frantovo.cz) - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package cz.frantovo.rozsireneatributy.gui; import cz.frantovo.rozsireneatributy.Atribut; +import cz.frantovo.rozsireneatributy.Konfigurace; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; @@ -46,28 +47,32 @@ .getLogger(Model.class.getSimpleName()); private static final ResourceBundle překlady = ResourceBundle .getBundle(Atribut.class.getPackageName() + ".Překlady"); - private String[] sloupečky = { + private final String[] sloupečky = { překlady.getString("tabulka.název"), překlady.getString("tabulka.hodnota") }; - private Set posluchače = new HashSet<>(); - private File soubor; - private UserDefinedFileAttributeView souborovýSystém; - private List atributy = new ArrayList<>(); + private final Set posluchače = new HashSet<>(); + private final Konfigurace konfigurace; + private final UserDefinedFileAttributeView souborovýSystém; + private final List atributy = new ArrayList<>(); private RandomAccessFile zámekSoubor; private FileChannel zámekKanál; private FileLock zámek; - public Model(File soubor) throws IOException { - this.soubor = soubor; - Path cesta = soubor.toPath(); + public Model(Konfigurace konfigurace) throws IOException { + this.konfigurace = konfigurace; + Path cesta = konfigurace.getSoubor().toPath(); FileSystemProvider posyktovatelFS = cesta.getFileSystem().provider(); souborovýSystém = posyktovatelFS .getFileAttributeView(cesta, UserDefinedFileAttributeView.class); načtiAtributy(); } + public Konfigurace getKonfigurace() { + return konfigurace; + } + @Override public int getRowCount() { return atributy.size(); @@ -95,12 +100,13 @@ @Override public Object getValueAt(int m, int n) { - if (n == 0) { - return atributy.get(m).getKlíč(); - } else if (n == 1) { - return atributy.get(m).getHodnota(); - } else { - return null; + switch (n) { + case 0: + return atributy.get(m).getKlíč(); + case 1: + return atributy.get(m).getHodnota(); + default: + return null; } } @@ -109,7 +115,9 @@ Atribut a = atributy.get(m); try { if (n == 0) { - /** Měníme klíč – název atributu */ + /** + * Měníme klíč – název atributu + */ String novýKlíč = String.valueOf(hodnota); if (!novýKlíč.equals(a.getKlíč())) { if (a.isPlatnýKlíč()) { @@ -121,7 +129,9 @@ } } } else if (n == 1) { - /** Měníme hodnotu atributu */ + /** + * Měníme hodnotu atributu + */ a.setHodnota(String.valueOf(hodnota)); if (a.isPlatnýKlíč() && a.isPlatnáHodnota()) { souborovýSystém.write(a.getKlíč(), a.getHodnotaBajty()); @@ -182,7 +192,7 @@ } public boolean isZámekPodporovaný() { - return soubor.isFile(); + return konfigurace.getSoubor().isFile(); } public void nastavZámek(boolean zamknout) throws IOException { @@ -192,7 +202,7 @@ } if (zamknout && zámekSoubor == null) { - zámekSoubor = new RandomAccessFile(soubor, "rw"); + zámekSoubor = new RandomAccessFile(konfigurace.getSoubor(), "rw"); zámekKanál = zámekSoubor.getChannel(); zámek = zámekKanál.lock(); } else if (!zamknout && zámekSoubor != null) { diff -r d511e4bf7d8f -r 1ab5ce94a146 java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/Panel.java --- a/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/Panel.java Tue Dec 12 21:19:11 2023 +0100 +++ b/java/rozsirene-atributy/src/cz/frantovo/rozsireneatributy/gui/Panel.java Fri Dec 15 01:36:17 2023 +0100 @@ -75,7 +75,7 @@ private void nastavEditor() { tabulka.getColumnModel().getColumn(SLOUPEC_NÁZVU) - .setCellEditor(new EditorNázvůAtributů()); + .setCellEditor(new EditorNázvůAtributů(model.getKonfigurace())); } private Model getModel() {