001/*
002 * Copyright 2015-2020 the original author or authors
003 *
004 * This software is licensed under the Apache License, Version 2.0,
005 * the GNU Lesser General Public License version 2 or later ("LGPL")
006 * and the WTFPL.
007 * You may choose either license to govern your use of this software only
008 * upon the condition that you accept all of the terms of either
009 * the Apache License 2.0, the LGPL 2.1+ or the WTFPL.
010 */
011package org.minidns.edns;
012
013import java.io.DataOutputStream;
014import java.io.IOException;
015
016import org.minidns.edns.Edns.OptionCode;
017
018public abstract class EdnsOption {
019
020    public final int optionCode;
021    public final int optionLength;
022
023    protected final byte[] optionData;
024
025    protected EdnsOption(int optionCode, byte[] optionData) {
026        this.optionCode = optionCode;
027        this.optionLength = optionData.length;
028        this.optionData = optionData;
029    }
030
031    protected EdnsOption(byte[] optionData) {
032        this.optionCode = getOptionCode().asInt;
033        this.optionLength = optionData.length;
034        this.optionData =  optionData;
035    }
036
037    public final void writeToDos(DataOutputStream dos) throws IOException {
038        dos.writeShort(optionCode);
039        dos.writeShort(optionLength);
040        dos.write(optionData);
041    }
042
043    public abstract OptionCode getOptionCode();
044
045    private String toStringCache;
046
047    @Override
048    public final String toString() {
049        if (toStringCache == null) {
050            toStringCache = toStringInternal().toString();
051        }
052        return toStringCache;
053    }
054
055    protected abstract CharSequence toStringInternal();
056
057    private String terminalOutputCache;
058
059    public final String asTerminalOutput() {
060        if (terminalOutputCache == null) {
061            terminalOutputCache = asTerminalOutputInternal().toString();
062        }
063        return terminalOutputCache;
064    }
065
066    protected abstract CharSequence asTerminalOutputInternal();
067
068    public static EdnsOption parse(int intOptionCode, byte[] optionData) {
069        OptionCode optionCode = OptionCode.from(intOptionCode);
070        EdnsOption res;
071        switch (optionCode) {
072        case NSID:
073            res = new Nsid(optionData);
074            break;
075        default:
076            res = new UnknownEdnsOption(intOptionCode, optionData);
077            break;
078        }
079        return res;
080    }
081
082}