KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > util > xml > applicationdata > NodeWriter


1 /*
2
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8
9 */

10 package org.mmbase.util.xml.applicationdata;
11
12 import java.io.*;
13 import java.util.*;
14
15 import org.mmbase.bridge.Field;
16 import org.mmbase.core.CoreField;
17 import org.mmbase.module.core.*;
18 import org.mmbase.module.corebuilders.*;
19 import org.mmbase.util.logging.*;
20 import org.mmbase.util.Casting;
21 import org.mmbase.util.Encode;
22
23 /**
24  * Utility class for writing xml files for data- and relation sources, suppied by an application export class.
25  * Does not support or export dtd information.
26  * @author Daniel Ockeleon
27  * @author Jaco de Groot
28  * @author Pierre van Rooden
29  * @version $Id: NodeWriter.java,v 1.3 2006/03/24 13:08:30 nklasens Exp $
30  */

31 public class NodeWriter {
32
33     private static final Logger log = Logging.getLoggerInstance(NodeWriter.class);
34
35     private MMBase mmb;
36     private Logger logger;
37     private String JavaDoc directory;
38     private String JavaDoc builderName;
39     private boolean isRelationNode;
40     private File file;
41     private OutputStreamWriter fw;
42     private int nrOfNodes;
43
44     /**
45      * Constructor, opens the initial xml file and writes a header.
46      * The file opened for writing is [directory]/[buildername].xml.
47      *
48      * @param mmb MMBase object for retrieving type information
49      * @param logger place to log results.
50      * @param directory the directory to write the files to (including the
51      * trailing slash).
52      * @param buildername name of the builder to export
53      * @param isRelationNode if <code>true</code>, the source to write is a relationsource.
54      * Otherwise, a datasource is written.
55      */

56     NodeWriter(MMBase mmb, Logger logger, String JavaDoc directory,
57                String JavaDoc builderName, boolean isRelationNode) {
58         // store parameters
59
this.mmb = mmb;
60         this.logger = logger;
61         this.directory = directory;
62         this.builderName = builderName;
63         this.isRelationNode = isRelationNode;
64         // define and open the file to write
65
file = new File(directory + builderName + ".xml");
66         try {
67             log.debug("Opening " + file + " for writing.");
68             fw = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
69         } catch (Exception JavaDoc e) {
70             logger.error("Failed opening file " + file);
71         }
72         // Write the header
73
write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
74         //write("<!DOCTYPE builder PUBLIC \"-//MMBase/data//EN\" \"http://www.mmbase.org/dtd/data.dtd\">\n");
75
Calendar cal= Calendar.getInstance();
76         long htimestamp=cal.get(Calendar.YEAR)*10000+
77                        (cal.get(Calendar.MONTH)+1)*100+
78                        cal.get(Calendar.DAY_OF_MONTH);
79         long ltimestamp= cal.get(Calendar.AM_PM)*120000+
80                          cal.get(Calendar.HOUR)*10000+
81                          cal.get(Calendar.MINUTE)*100+
82                          cal.get(Calendar.SECOND);
83         long timestamp=(htimestamp*1000000)+ltimestamp;
84
85         write("<" + builderName + " "
86               + "exportsource=\"mmbase://"+ // was: mmbase://127.0.0.1/install/b1
87
mmb.getHost()+"/"+mmb.getStorageManagerFactory().getCatalog()+"/"+mmb.getBaseName()+"\" "+
88               "timestamp=\""+timestamp+"\">\n"); // was : 20000602143030
89
// initialize the nr of nodes written
90
nrOfNodes = 0;
91     }
92
93     /**
94      * Writes a node (object) to the datasource file.
95      * Relationsources are stored in a slightly different format from data sources.
96      * @param node The object to store.
97      */

98     public void write(MMObjectNode node) {
99         // retrieve basic information of the node
100
int number=node.getIntValue("number");
101         String JavaDoc owner=node.getStringValue("owner");
102         // start writing the node
103
if (isRelationNode) {
104             // For a relationnode, the fields snumber, dnumber and rnumber are stored as
105
// named references (as snumber, rnumber, and rtype).
106
// determine the relation 'type' (use the value of sname in RelDef, or the
107
// current buildername by default)
108
String JavaDoc rtype = builderName;
109             int rnumber=node.getIntValue("rnumber");
110             MMObjectNode reldefnode=mmb.getRelDef().getNode(rnumber);
111             if (reldefnode!=null) {
112                 rtype = reldefnode.getStringValue("sname");
113             }
114             write("\t<node number=\""+number+"\" owner=\""+owner+"\" snumber=\""+ node.getIntValue("snumber") +"\" dnumber=\""+ node.getIntValue("dnumber") +"\" rtype=\""+ rtype +"\"");
115             // add directionality if used
116
if (InsRel.usesdir) {
117                 int dir=node.getIntValue("dir");
118                 if (dir==1) {
119                     write(" dir=\"unidirectional\"");
120                 } else {
121                     write(" dir=\"bidirectional\"");
122                 }
123             }
124             write(">\n");
125         } else {
126             // For a data node, store the alias if at all possible.
127
String JavaDoc tm = mmb.getOAlias().getAlias(number);
128             if (tm == null) {
129                 write("\t<node number=\"" + number+"\" owner=\"" + owner + "\">\n");
130             } else {
131                 write("\t<node number=\"" + number+"\" owner=\"" + owner + "\" alias=\"" + tm + "\">\n");
132             }
133         }
134         MMObjectBuilder bul = node.getBuilder();
135         Iterator nd = bul.getFields().iterator();
136         while (nd.hasNext()) {
137             CoreField def = (CoreField)nd.next();
138             if (def.inStorage()) {
139                 String JavaDoc key = def.getName();
140                 if (isRelationNode) {
141                     // note that the routine below assumes
142
// fields in a relation node cannot contain binary blobs
143
//
144
if (!key.equals("number") && !key.equals("owner")
145                             && !key.equals("otype")
146                             && !key.equals("snumber") && !key.equals("dnumber")
147                             && !key.equals("rnumber") && !key.equals("dir") && !def.isTemporary()) {
148                         write("\t\t<" + key + ">" + node.getValue(key) + "</" + key + ">\n");
149                     }
150                 } else {
151                     //due to current tcp implementation sometimes nodeField are created
152
//those fiels always start with an underscore. If a node starts with
153
//we skip it
154
if (!def.isTemporary()) {
155                         write(writeXMLField(key, node, directory, mmb));
156                     }
157                 }
158             }
159         }
160         // end the node
161
write("\t</node>\n\n");
162         nrOfNodes++;
163     }
164
165     /**
166      * Writes a footer to the xml file, and closes the file.
167      */

168     public void done() {
169         // write the footer
170
write("</"+ builderName + ">\n");
171         logger.info("Saving " + nrOfNodes + " " + builderName
172                                + " to : " + file);
173         try {
174             log.debug("Closing file " + file);
175             fw.close();
176         } catch (Exception JavaDoc e) {
177             logger.error("Failed closing file " + file);
178         }
179     }
180
181     /**
182      * Writes a string datasource file.
183      * @param s The string to store.
184      */

185     private void write(String JavaDoc s) {
186         try {
187             fw.write(s);
188         } catch (Exception JavaDoc e) {
189             logger.error("Failed writing to file " + file);
190         }
191     }
192
193     /**
194      * Creates a description string of a field in a node for use in a datasource file.
195      * Binary data (such as images) are stored as seperate binary files, the string then contains
196      * a reference in lieu of the actual value.
197      * A number of 'special purpose' fields (number, owner, otype) are skipped and not written.
198      * Other fields are added 'in line'.
199      * @param key the fieldname to store
200      * @param node The node wose field to store
201      * @param targetpath the path where any binary files may be stored
202      * @param mmb MMBase object for retrieving type info
203      * @return A <code>String</code> descriving in xml-format the field's content (or a reference to that content)
204      */

205     private static String JavaDoc writeXMLField(String JavaDoc key,MMObjectNode node, String JavaDoc targetpath,MMBase mmb) {
206         if (!key.equals("number") && !key.equals("owner") && !key.equals("otype")) {
207             // this is a bad way of doing it imho
208
int type=node.getDBType(key);
209             String JavaDoc stype=mmb.getTypeDef().getValue(node.getIntValue("otype"));
210             if (type==Field.TYPE_BINARY) {
211                 String JavaDoc body="\t\t<"+key+" file=\""+stype+"/"+node.getIntValue("number")+"."+key+"\" />\n";
212                 File file = new File(targetpath+stype);
213                 try {
214                     file.mkdirs();
215                 } catch(Exception JavaDoc e) {
216                     log.error("Can't create dir : "+targetpath+stype);
217                 }
218                 byte[] value=node.getByteValue(key);
219                 saveFile(targetpath+stype+"/"+node.getIntValue("number")+"."+key,value);
220                 return body;
221             } else {
222                 String JavaDoc body="\t\t<"+key+">"+Encode.encode("ESCAPE_XML", "" + Casting.toString(node.getValue(key))) +"</"+key+">\n";
223                 return body;
224            }
225         }
226         return "";
227     }
228
229     /**
230      * Stores binary data in a file
231      * @param filename path of the file to store the data
232      * @param value binary data to store (byte array)
233      * @return <code>true</code> if the write was succesful, <code>false</code> if an exception occurred
234      */

235     static boolean saveFile(String JavaDoc filename,byte[] value) {
236         File sfile = new File(filename);
237         try {
238             DataOutputStream scan = new DataOutputStream(new FileOutputStream(sfile));
239             scan.write(value);
240             scan.flush();
241             scan.close();
242         } catch(Exception JavaDoc e) {
243             log.error(e.toString());
244             log.error(Logging.stackTrace(e));
245             return false;
246         }
247         return true;
248     }
249 }
250
Popular Tags