001: package org.mmbase.util.magicfile;
002:
003: import java.io.*;
004: import java.util.*;
005:
006: import org.mmbase.util.*;
007: import org.mmbase.util.logging.*;
008: import org.mmbase.util.xml.DocumentReader;
009: import org.w3c.dom.Element;
010: import org.xml.sax.InputSource;
011: import java.util.concurrent.CopyOnWriteArrayList;
012:
013: /**
014: * Reads <config>/magic.xml
015: */
016: public class MagicXMLReader extends DocumentReader implements
017: DetectorProvider {
018:
019: private static Logger log = Logging
020: .getLoggerInstance(MagicXMLReader.class);
021:
022: private static MagicXMLReader reader = null;
023: protected static final String MAGICXMLFILE = "magic.xml";
024:
025: // Name of the XML magic file - should reside in top config dir
026:
027: private static void setReader(String config)
028: throws IllegalArgumentException {
029: try {
030: InputSource is = ResourceLoader.getConfigurationRoot()
031: .getInputSource(config);
032: if (is != null) {
033: reader = new MagicXMLReader(is);
034: }
035: } catch (IOException ie) {
036: log.warn(ie);
037: }
038: }
039:
040: /**
041: * Gets the one MagicXMLReader (there can only be one).
042: * @return MagicXMLReader if mmbase was staterd or null if mmbase was not started
043: */
044:
045: public synchronized static MagicXMLReader getInstance() {
046: if (reader == null) { // can only occur once.
047:
048: setReader(MAGICXMLFILE);
049:
050: if (reader != null) {
051: log.info("Magic XML file is: " + reader.getSystemId());
052: }
053:
054: ResourceWatcher watcher = new ResourceWatcher() {
055: public void onChange(String file) {
056: // reader is replaced on every change of magic.xml
057: setReader(file);
058: }
059: };
060: watcher.start();
061: watcher.add(MAGICXMLFILE);
062:
063: }
064: return reader;
065: }
066:
067: private List<Detector> detectors = null;
068:
069: private MagicXMLReader(InputSource is) {
070: super (is, MagicXMLReader.class);
071: }
072:
073: public String getVersion() {
074: Element e = getElementByPath("magic.info.version");
075: return getElementValue(e);
076: }
077:
078: public String getAuthor() {
079: Element e = getElementByPath("magic.info.author");
080: return getElementValue(e);
081: }
082:
083: public String getDescription() {
084: Element e = getElementByPath("magic.info.description");
085: return getElementValue(e);
086: }
087:
088: /**
089: * Returns all 'Detectors'.
090: */
091: public List<Detector> getDetectors() {
092: if (detectors == null) {
093: detectors = new CopyOnWriteArrayList<Detector>();
094: Element e = getElementByPath("magic.detectorlist");
095: if (e == null) {
096: log
097: .fatal("Could not find magic/detectorlist in magic.xml");
098: // aargh!
099: return detectors;
100: }
101: for (Element element : getChildElements(e)) {
102: Detector d = getOneDetector(element);
103: detectors.add(d);
104: }
105: }
106: return detectors;
107: }
108:
109: /**
110: * Replaces octal representations of bytes, written as \ddd to actual byte values.
111: */
112: private String convertOctals(String s) {
113: int p = 0;
114: int stoppedAt = 0;
115: ByteArrayOutputStream buf = new ByteArrayOutputStream();
116: char c;
117: try {
118: while (p < s.length()) {
119: c = s.charAt(p);
120: if (c == '\\') {
121: if (p > s.length() - 4) {
122: // Can't be a full octal representation here, let's cut it off
123: break;
124: } else {
125: char c0;
126: boolean failed = false;
127: for (int p0 = p + 1; p0 < p + 4; p0++) {
128: c0 = s.charAt(p0);
129: if (!(c0 >= '0' && c0 <= '7')) {
130: failed = true;
131: }
132: }
133: if (!failed) {
134: byte[] bytes = s.substring(stoppedAt, p)
135: .getBytes("US-ASCII");
136: buf.write(bytes, 0, bytes.length);
137: buf.write(Integer.parseInt(s.substring(
138: p + 1, p + 4), 8));
139: stoppedAt = p + 4;
140: p = p + 4;
141: } else {
142: p++;
143: }
144: }
145: } else {
146: p++;
147: }
148: }
149: byte[] bytes = s.substring(stoppedAt, p).getBytes(
150: "US-ASCII");
151: buf.write(bytes, 0, bytes.length);
152: return buf.toString("US-ASCII");
153: } catch (java.io.UnsupportedEncodingException use) { // could not happen US-ASCII is supported
154: return "";
155: }
156: }
157:
158: private Detector getOneDetector(Element e) {
159: Detector d = new Detector();
160: Element e1;
161:
162: e1 = getElementByPath(e, "detector.mimetype");
163: d.setMimeType(getElementValue(e1));
164:
165: e1 = getElementByPath(e, "detector.extension");
166: d.setExtension(getElementValue(e1));
167:
168: e1 = getElementByPath(e, "detector.designation");
169: d.setDesignation(getElementValue(e1));
170:
171: e1 = getElementByPath(e, "detector.test");
172: if (e1 != null) {
173: d.setTest(convertOctals(getElementValue(e1)));
174: d.setOffset(getElementAttributeValue(e1, "offset"));
175: d.setType(getElementAttributeValue(e1, "type"));
176: String comparator = getElementAttributeValue(e1,
177: "comparator");
178: if (comparator.equals(">")) {
179: d.setComparator('>');
180: } else if (comparator.equals("<")) {
181: d.setComparator('<');
182: } else if (comparator.equals("&")) {
183: d.setComparator('&');
184: } else if (comparator.length() == 1) {
185: d.setComparator(comparator.charAt(0));
186: } else {
187: d.setComparator('=');
188: }
189: }
190:
191: e1 = getElementByPath(e, "detector.childlist");
192: if (e1 != null) {
193: for (Element element : getChildElements(e1)) {
194: Detector child = getOneDetector(element);
195: d.addChild(child, 1); // Not sure if this is the right thing
196: }
197: }
198: return d;
199: }
200: }
|