blob: 2399996b6baccbfa9d21fe0e6d1fbb71dab9d546 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2019 Xored Software Inc and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Xored Software Inc - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.rcptt.core.persistence.plain;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;
import org.eclipse.rcptt.internal.core.RcpttPlugin;
import org.eclipse.rcptt.util.Base64;
import org.eclipse.rcptt.util.FileUtil;
public class PlainReader implements IPlainConstants {
private BufferedReader reader;
private InputStream in;
public static class Entry {
public String name;
private Object content;
public Map<String, String> attributes;
public String rawData;
public Object getContent() {
if (content == null && rawData != null) {
try {
byte[] decode = Base64.decode(rawData);
if (decode == null) {
RcpttPlugin.log(
"Failed to decode RCPTT file format, invalid content",
null);
return null;
}
ByteArrayInputStream bin = new ByteArrayInputStream(decode);
ZipInputStream zin = new ZipInputStream(bin);
zin.getNextEntry();
content = FileUtil.getStreamContent(zin);
rawData = null;
} catch (Exception e) {
RcpttPlugin.log(e);
}
}
return content;
}
}
public PlainReader(InputStream stream) throws IOException {
this.in = stream;
reader = new BufferedReader(new InputStreamReader(
new BufferedInputStream(stream), ENCODING));
}
private static final List<String> VALID_HEADERS = Arrays.asList(PLAIN_HEADER, PLAIN_METADATA, PLAIN_VERIFICATION,
LEGACY_PLAIN_HEADER, LEGACY_PLAIN_METADATA, LEGACY_PLAIN_VERIFICATION);
public Map<String, String> readHeader() throws Exception {
String header = reader.readLine();
if (header == null) {
return null;
}
header = header.trim();
while( header.startsWith("#")) {
header = reader.readLine();
if( header == null) {
return null;
}
header = header.trim();
}
boolean headerOK = false;
for (String validHeader : VALID_HEADERS) {
if (validHeader.equalsIgnoreCase(header)) {
headerOK = true;
break;
}
}
if (!headerOK) {
// Not a plain file
return null;
}
Map<String, String> map = readAttributes();
return map;
}
private Map<String, String> readAttributes() throws IOException, Exception {
Map<String, String> map = new HashMap<String, String>();
while (true) {
String line = reader.readLine();
if (line == null || line.trim().length() == 0) {
break;
}
int pos = line.indexOf(": ");
if (pos != -1) {
String key = line.substring(0, pos);
String value = FileUtil.unescape(line.substring(pos + 2));
if (map.containsKey(key)) {
throw new PlainFormatException(
"Wrong RCPTT plain format, duplicate attribute entry.");
}
map.put(key, value);
} else {
if (line.trim().endsWith(":")) {
// Null Value, skip it
} else {
throw new PlainFormatException("Wrong RCPTT plain format");
}
}
}
return map;
}
/**
* Return next entry and null if end of stream are detected
*
* @return
* @throws IOException
*/
public Entry readEntry() throws Exception {
String entryHeader = reader.readLine();
if (entryHeader == null) {
return null;
}
// Skip newlines.
while (entryHeader != null && entryHeader.trim().length() == 0) {
entryHeader = reader.readLine();
}
if (entryHeader == null) {
return null;
}
if (entryHeader.startsWith(NODE_PREFIX)) {
Entry entry = new Entry();
entry.attributes = readAttributes();
entry.name = entry.attributes.get(ATTR_ENTRY_NAME);
String contentType = entry.attributes.get(ATTR_CONTENT_TYPE);
List<String> lines = new ArrayList<String>();
while (true) {
String line = reader.readLine();
if (line == null
|| line.trim().equals(entryHeader + NODE_POSTFIX)) {
break;
}
lines.add(line);
}
if (contentType != null && contentType.contains("text")) {
// Text mode content
StringBuilder builder = new StringBuilder();
for (String s : lines) {
builder.append(s).append("\n");
}
String resultStr = builder.toString();
if (resultStr.endsWith("\n")) {
resultStr = resultStr.substring(0, resultStr.length()
- "\n".length());
}
entry.content = resultStr;
} else if (contentType != null && contentType.contains("binary")) {
// Base64 encoded content
StringBuilder builder = new StringBuilder();
for (String s : lines) {
builder.append(s);
}
entry.rawData = builder.toString();
}
return entry;
} else {
throw new PlainFormatException("Wrong RCPTT plain format");
}
}
public void close() {
FileUtil.safeClose(reader);
FileUtil.safeClose(in);
}
}