001 /*
002 * Copyright 2010 The Apache Software Foundation.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.vafer.jdeb.descriptors;
017
018 import java.io.BufferedReader;
019 import java.io.IOException;
020 import java.io.InputStream;
021 import java.io.InputStreamReader;
022 import java.io.StringReader;
023 import java.text.ParseException;
024 import java.util.HashMap;
025 import java.util.HashSet;
026 import java.util.Map;
027 import java.util.Set;
028
029 import org.vafer.jdeb.utils.Utils;
030 import org.vafer.jdeb.utils.VariableResolver;
031
032 /**
033 * A descriptor holds the usual key value pairs.
034 *
035 * @see <a href="http://www.debian.org/doc/debian-policy/ch-controlfields.html">Debian Policy Manual - Control files and their fields</a>
036 *
037 * @author Torsten Curdt <tcurdt@vafer.org>
038 */
039 public abstract class AbstractDescriptor {
040
041 private final Map values = new HashMap();
042 private final VariableResolver resolver;
043 private static String openToken = "[[";
044 private static String closeToken = "]]";
045
046 public AbstractDescriptor( final VariableResolver pResolver ) {
047 resolver = pResolver;
048 }
049
050 public AbstractDescriptor( final AbstractDescriptor pDescriptor ) {
051 values.putAll(pDescriptor.values);
052 resolver = pDescriptor.resolver;
053 }
054
055 public static void setOpenToken( final String pToken ) {
056 openToken = pToken;
057 }
058
059 public static void setCloseToken( final String pToken ) {
060 closeToken = pToken;
061 }
062
063 protected void parse( final InputStream pInput ) throws IOException, ParseException {
064 final BufferedReader br = new BufferedReader(new InputStreamReader(pInput));
065 StringBuffer buffer = new StringBuffer();
066 String key = null;
067 int linenr = 0;
068 while(true) {
069 final String line = br.readLine();
070
071 if (line == null) {
072 if (buffer.length() > 0) {
073 // flush value of previous key
074 set(key, buffer.toString());
075 buffer = null;
076 }
077 break;
078 }
079
080 linenr++;
081
082 if (line.length() == 0) {
083 throw new ParseException("Empty line", linenr);
084 }
085
086 final char first = line.charAt(0);
087 if (Character.isLetter(first)) {
088
089 // new key
090
091 if (buffer.length() > 0) {
092 // flush value of previous key
093 set(key, buffer.toString());
094 buffer = new StringBuffer();
095 }
096
097
098 final int i = line.indexOf(':');
099
100 if (i < 0) {
101 throw new ParseException("Line misses ':' delimitter", linenr);
102 }
103
104 key = line.substring(0, i);
105 buffer.append(line.substring(i+1).trim());
106
107 continue;
108 }
109
110 // continuing old value
111 buffer.append('\n').append(line.substring(1));
112 }
113 br.close();
114
115 }
116
117 public void set( final String pKey, final String pValue ) {
118
119 if (resolver != null) {
120 try {
121 values.put(pKey, Utils.replaceVariables(resolver, pValue, openToken, closeToken));
122 return;
123 } catch (ParseException e) {
124 // FIXME maybe throw an Exception?
125 }
126 }
127
128 values.put(pKey, pValue);
129 }
130
131 public String get( final String pKey ) {
132 return (String)values.get(pKey);
133 }
134
135 public abstract String[] getMandatoryKeys();
136
137 public boolean isValid() {
138 return invalidKeys().size() == 0;
139 }
140
141 public Set invalidKeys() {
142 final Set invalid = new HashSet();
143
144 final String[] mk = getMandatoryKeys();
145 for (int i = 0; i < mk.length; i++) {
146 if (get(mk[i]) == null) {
147 invalid.add(mk[i]);
148 }
149 }
150
151 return invalid;
152 }
153
154 public String toString( final String[] pKeys ) {
155 final StringBuffer s = new StringBuffer();
156 for (int i = 0; i < pKeys.length; i++) {
157 final String key = pKeys[i];
158 final String value = (String) values.get(key);
159 if (value != null) {
160 s.append(key).append(":");
161
162 try {
163 BufferedReader reader = new BufferedReader(new StringReader(value));
164 String line;
165 while ((line = reader.readLine()) != null) {
166 if (line.length() != 0 && !Character.isWhitespace(line.charAt(0))) {
167 s.append(' ');
168 }
169
170 s.append(line).append('\n');
171 }
172 } catch (IOException e) {
173 e.printStackTrace();
174 }
175 }
176 }
177 return s.toString();
178 }
179 }