1 package javaclients.simplereader;
2
3 import java.io.File;
4 import java.io.FileOutputStream;
5 import java.io.IOException;
6 import java.util.logging.Logger;
7
8 import org.xmlBlaster.client.key.UpdateKey;
9 import org.xmlBlaster.client.qos.UpdateQos;
10 import org.xmlBlaster.util.EncodableData;
11 import org.xmlBlaster.util.Global;
12 import org.xmlBlaster.util.XmlBlasterException;
13 import org.xmlBlaster.util.def.Constants;
14 import org.xmlBlaster.util.def.ErrorCode;
15
16 public class FileDumper {
17 private static String ME = "FileDumper";
18 private static Logger log = Logger.getLogger(FileDumper.class.getName());
19 private Global glob;
20 private String directoryName;
21 /** forceBase64==false: ASCII dump for content if possible (XML embedable) */
22 private boolean forceBase64 = false;
23
24 public FileDumper(Global glob) throws XmlBlasterException {
25 this.glob = glob;
26 String defaultPath = System.getProperty("user.home") + System.getProperty("file.separator") + "FileDumper";
27 this.directoryName = this.glob.getProperty().get("directoryName", defaultPath);
28 initDirectory(null, "directoryName", this.directoryName);
29
30 log.info("Dumping occurrences of topic '" + Constants.OID_DEAD_LETTER + "' to directory " + this.directoryName);
31 this.forceBase64 = this.glob.getProperty().get("forceBase64", this.forceBase64);
32 }
33
34 /**
35 * Dump dead message to hard disk.
36 * The file name is the receive timestamp of the message, for example
37 * <tt>/home/xmlblast/tmp/2004-10-23_18_52_39_87.xml</tt>
38 */
39 public void dumpMessage(UpdateKey updateKey, byte[] content, UpdateQos updateQos) {
40 try {
41 String fn = updateQos.getRcvTime();
42 String key = updateKey.toXml();
43 String qos = updateQos.toXml();
44 String oid = updateKey.getOid();
45
46 fn = Global.getStrippedString(fn); // Strip chars like ":" so that fn is usable as a file name
47 fn = fn + ".xml";
48
49 initDirectory(null, "directoryName", this.directoryName); // In case somebody has removed it
50 File to_file = new File(this.directoryName, fn);
51
52 FileOutputStream to = new FileOutputStream(to_file);
53 log.info("Dumping dead message to '" + to_file.toString() + "'" );
54
55 StringBuffer sb = new StringBuffer(qos.length() + key.length() + 1024);
56 //sb.append("<?xml version='1.0' encoding='iso-8859-1'?>");
57 //sb.append("<?xml version='1.0' encoding='utf-8' ?>");
58
59 sb.append("\n <!-- Dump of topic '").append(oid).append("' -->");
60 sb.append("\n<xmlBlaster>");
61 sb.append("\n <publish>");
62 to.write(sb.toString().getBytes());
63 sb.setLength(0);
64
65 {
66 sb.append(qos);
67 sb.append(key);
68 to.write(sb.toString().getBytes());
69 sb.setLength(0);
70
71 // TODO: Potential charset problem when not Base64 protected
72 boolean doEncode = forceBase64;
73 if (!forceBase64) {
74 int len = content.length - 2;
75 for (int i=0; i<len; i++) {
76 if (content[i] == (byte)']' && content[i+1] == (byte)']' && content[i+2] == (byte)'>') {
77 doEncode = true;
78 break;
79 }
80 }
81 }
82
83 if (doEncode) {
84 EncodableData data = new EncodableData("content", null, Constants.TYPE_BLOB, Constants.ENCODING_BASE64);
85 data.setValue(content);
86 data.setSize(content.length);
87 to.write(data.toXml(" ").getBytes());
88 }
89 else {
90 EncodableData data = new EncodableData("content", null, null, null);
91 //String charSet = "UTF-8"; // "ISO-8859-1", "US-ASCII"
92 //data.setValue(new String(content, charSet), null);
93 data.setValueRaw(new String(content));
94 data.forceCdata(true);
95 data.setSize(content.length);
96 to.write(data.toXml(" ").getBytes());
97 }
98 }
99 {
100 //MsgUnitRaw msg = new MsgUnitRaw(key, content, qos);
101 //msg.toXml(" ", to);
102 }
103
104 sb.append("\n </publish>");
105 sb.append("\n</xmlBlaster>");
106 to.write(sb.toString().getBytes());
107 to.close();
108 }
109 catch (Throwable e) {
110 log.severe("Dumping of message failed: " + updateQos.toXml() + updateKey.toXml() + new String(content));
111 }
112 }
113
114 /**
115 * Returns the specified directory or null or if needed it will create one
116 * @param parent
117 * @param propName For logging only
118 * @param dirName
119 * @return
120 * @throws XmlBlasterException
121 */
122 private File initDirectory(File parent, String propName, String dirName) throws XmlBlasterException {
123 File dir = null;
124 if (dirName != null) {
125 File tmp = new File(dirName);
126 if (tmp.isAbsolute() || parent == null) {
127 dir = new File(dirName);
128 }
129 else {
130 dir = new File(parent, dirName);
131 }
132 if (!dir.exists()) {
133 String absDirName = null;
134 try {
135 absDirName = dir.getCanonicalPath();
136 }
137 catch (IOException ex) {
138 absDirName = dir.getAbsolutePath();
139 }
140 log.info("Constructor: directory '" + absDirName + "' does not yet exist. I will create it");
141 boolean ret = dir.mkdir();
142 if (!ret)
143 throw new XmlBlasterException(this.glob, ErrorCode.RESOURCE_FILEIO, ME, "could not create directory '" + absDirName + "'");
144 }
145 if (!dir.isDirectory()) {
146 throw new XmlBlasterException(this.glob, ErrorCode.RESOURCE_FILEIO, ME, "'" + dir.getAbsolutePath() + "' is not a directory");
147 }
148 if (!dir.canRead())
149 throw new XmlBlasterException(this.glob, ErrorCode.RESOURCE_FILEIO, ME + ".constructor", "no rights to read from the directory '" + dir.getAbsolutePath() + "'");
150 if (!dir.canWrite())
151 throw new XmlBlasterException(this.glob, ErrorCode.RESOURCE_FILEIO, ME + ".constructor", "no rights to write to the directory '" + dir.getAbsolutePath() + "'");
152 }
153 else {
154 log.info("Constructor: the '" + propName + "' property is not set. Instead of moving concerned entries they will be deleted");
155 }
156 return dir;
157 }
158 }
syntax highlighted by Code2HTML, v. 0.9.1