001: // Upgrader.java
002: // $Id: Upgrader.java,v 1.6 2001/01/31 12:49:29 ylafon Exp $
003: // (c) COPYRIGHT MIT, INRIA and Keio, 1999.
004: // Please first read the full copyright statement in file COPYRIGHT.html
005:
006: package org.w3c.tools.resources.upgrade;
007:
008: import java.io.BufferedInputStream;
009: import java.io.BufferedWriter;
010: import java.io.DataInputStream;
011: import java.io.EOFException;
012: import java.io.File;
013: import java.io.FileInputStream;
014: import java.io.FileNotFoundException;
015: import java.io.FileOutputStream;
016: import java.io.FileWriter;
017: import java.io.FilenameFilter;
018: import java.io.FilterInputStream;
019: import java.io.IOException;
020: import java.io.PrintStream;
021: import java.io.UTFDataFormatException;
022: import java.io.Writer;
023:
024: import java.util.Hashtable;
025: import java.util.Properties;
026: import java.util.Vector;
027:
028: import java.lang.reflect.Constructor;
029:
030: import org.w3c.jigsaw.http.httpd;
031: import org.w3c.jigsaw.daemon.ServerHandlerManager;
032: import org.w3c.tools.resources.AttributeRegistry;
033: import org.w3c.tools.resources.Resource;
034: import org.w3c.tools.resources.UnknownResource;
035: import org.w3c.tools.resources.store.ResourceStoreManager;
036: import org.w3c.tools.resources.serialization.Serializer;
037:
038: /**
039: * @version $Revision: 1.6 $
040: * @author Benoît Mahé (bmahe@w3.org)
041: */
042: public class Upgrader {
043:
044: public static final boolean debug = true;
045:
046: Serializer serializer = null;
047: String server = null;
048: File config = null;
049: File props = null;
050:
051: public static void usage() {
052: System.err.println("Usage : java "
053: + "org.w3c.tools.resources.upgrade.Upgrader "
054: + "<Jigsaw Install Directory>\n");
055: System.exit(-1);
056: }
057:
058: /**
059: * Get the index of the given attribute in the given attribute array
060: * @param name, the attribute name.
061: * @param attributes, the atribute array.
062: * @return an int
063: */
064: public static int lookupAttribute(String name,
065: org.w3c.tools.resources.Attribute attributes[]) {
066: for (int i = 0; i < attributes.length; i++) {
067: if (name.equals(attributes[i].getName()))
068: return i;
069: }
070: return -1;
071: }
072:
073: /**
074: * Get the old attribute relative to the given new kind of attribute.
075: * @param attr the new attribute
076: * @return the old attribute
077: */
078: public static Attribute getOldAttribute(
079: org.w3c.tools.resources.Attribute attr)
080: throws UpgradeException {
081: String classname = attr.getClass().getName();
082: int idx = classname.lastIndexOf('.');
083: String newclassname = "org.w3c.tools.resources.upgrade."
084: + classname.substring(idx + 1);
085:
086: try {
087: Class c = Class.forName(newclassname);
088:
089: Class params[] = new Class[3];
090: params[0] = Class.forName("java.lang.String");
091: if (attr.getType() == null)
092: throw new UpgradeException(
093: "*** ERROR : no type defined for "
094: + attr.getName());
095: // welcome to the land of ugly hacks
096: if (attr.getType().equals("java.util.Date"))
097: params[1] = Class.forName("java.lang.Long");
098: else
099: params[1] = Class.forName(attr.getType());
100: params[2] = Class.forName("java.lang.Integer");
101:
102: Constructor cons = c.getConstructor(params);
103: Object initargs[] = { attr.getName(), attr.getDefault(),
104: new Integer(1) };
105: return (Attribute) cons.newInstance(initargs);
106: } catch (Exception ex) {
107: ex.printStackTrace();
108: throw new RuntimeException("unable to instanciate :"
109: + newclassname);
110: }
111: }
112:
113: public static void unpickleProlog(DataInputStream in)
114: throws IOException {
115: in.readInt();
116: in.readUTF();
117: in.readInt();
118: }
119:
120: public static void readIndex(DataInputStream in) throws IOException {
121: int count = in.readInt();
122: for (int i = 0; i < count; i++) {
123: in.readInt();
124: in.readInt();
125: in.readUTF();
126: }
127: }
128:
129: /**
130: * load a resoure from the given DataInputStream.
131: * @param in the DataInputStream
132: * @return a Resource instance
133: */
134: public static Resource readResource(DataInputStream in)
135: throws IOException, UpgradeException {
136: String classname = null;
137: try {
138: classname = in.readUTF();
139: } catch (EOFException ex) {
140: //no more resources
141: return null;
142: } catch (UTFDataFormatException utfex) {
143: //silent...
144: return null;
145: }
146:
147: if (classname.startsWith("org.w3c.jigsaw.map")) {
148: System.out.println("\n*** WARNING : " + classname
149: + " is no more supported.");
150: return new UnknownResource();
151: }
152:
153: try {
154: Class c = Class.forName(classname);
155: Resource res = (Resource) c.newInstance();
156: Hashtable values = new Hashtable(10);
157: org.w3c.tools.resources.Attribute attrs[] = org.w3c.tools.resources.AttributeRegistry
158: .getClassAttributes(c);
159:
160: boolean slowpickle = !in.readBoolean();
161: if (slowpickle) {
162: String name = null;
163: while (!(name = in.readUTF()).equals("")) {
164: int ai = lookupAttribute(name, attrs);
165: int as = ((int) in.readShort() & 0xffff);
166: if (ai >= 0) {
167: Attribute oldattr = getOldAttribute(attrs[ai]);
168: Object value = oldattr.unpickle(in);
169: if (value != null)
170: values.put(name, value);
171: } else {
172: in.skip(as);
173: }
174: }
175: } else {
176: for (int i = 0; i < attrs.length; i++) {
177: if (in.readBoolean()) {
178: Attribute oldattr = getOldAttribute(attrs[i]);
179: Object value = oldattr.unpickle(in);
180: if (value != null)
181: values.put(attrs[i].getName(), value);
182: }
183: }
184: }
185: res.pickleValues(values);
186: return res;
187: } catch (UTFDataFormatException utfex) {
188: //silent...
189: return null;
190: } catch (ClassNotFoundException cnfex) {
191: System.out.println("\n*** ERROR loading " + classname);
192: System.out.println("*** Class not found : "
193: + cnfex.getMessage());
194: return null;
195: } catch (IllegalAccessException iaex) {
196: System.out.println("\n*** ERROR loading " + classname);
197: System.out.println("*** " + iaex.getMessage());
198: return null;
199: } catch (InstantiationException iex) {
200: System.out.println("\n*** ERROR loading " + classname);
201: System.out.println("*** " + iex.getMessage());
202: return null;
203: } catch (NoClassDefFoundError err) {
204: System.out.println("\n*** ERROR loading " + classname);
205: System.out.println("*** Class not found : "
206: + err.getMessage());
207: return null;
208: }
209: }
210:
211: /**
212: * Read the resource from a repository.
213: * @param rep the repository (a File)
214: * @return a Resource array
215: */
216: public static Resource[] readRepository(File rep)
217: throws FileNotFoundException, IOException, UpgradeException {
218: DataInputStream in = null;
219: in = new DataInputStream(new BufferedInputStream(
220: new FileInputStream(rep)));
221: //first unpickle prolog
222: unpickleProlog(in);
223: //read the index
224: readIndex(in);
225: //read the resources
226: Vector vres = new Vector(10);
227: Resource res = null;
228: do {
229: res = readResource(in);
230: if (res != null)
231: vres.addElement(res);
232: } while (res != null);
233: Resource resources[] = new Resource[vres.size()];
234: vres.copyInto(resources);
235: return resources;
236: }
237:
238: /**
239: * update the index file (in stores)
240: * @exception IOException if an IO error occurs
241: */
242: public void updateEntriesIndex(File storedir) throws IOException,
243: UpgradeException {
244: if (storedir.isDirectory()) {
245: FilenameFilter filter = new FilenameFilter() {
246: public boolean accept(File dir, String name) {
247: return ((name.indexOf("-index") != -1)
248: && (!name.endsWith(".bak")) && (!name
249: .endsWith(".xml")));
250: }
251: };
252: File files[] = storedir.listFiles(filter);
253: if ((files == null) || (files.length == 0)) {
254: String msg = "\n*** ERROR : unable to find index file.\n"
255: + "*** Please check that \""
256: + storedir.getAbsolutePath()
257: + "\" is the Jigsaw store directory";
258: throw new UpgradeException(msg);
259: } else if (files.length > 1) {
260: String msg = "\n*** ERROR: several index files found, "
261: + "please delete or move the invalid index files : ";
262: for (int i = 0; i < files.length; i++)
263: msg += "\n\t" + files[i].getName();
264: throw new UpgradeException(msg);
265: } else {
266: //good!
267: File oldIndexFile = files[0];
268: System.out.print("Found index file \""
269: + oldIndexFile.getName() + "\", upgrading...");
270: File newIndexFile = new File(storedir, oldIndexFile
271: .getName()
272: + ".xml");
273: ResourceStoreManager.updateEntriesIndex(oldIndexFile,
274: newIndexFile, serializer);
275: System.out.println(" done.");
276: }
277: } else if (storedir.exists()) {
278: throw new UpgradeException("\n*** ERROR : \""
279: + storedir.getAbsolutePath()
280: + "\" is not a directory.");
281: } else {
282: throw new UpgradeException("\n*** ERROR : \""
283: + storedir.getAbsolutePath() + "\" doesn't exists.");
284: }
285: }
286:
287: /**
288: * Create the subdirectories under /stores.
289: */
290: protected boolean createSubDirs(File storedir) {
291: for (int i = 0; i < ResourceStoreManager.SUBDIRS; i++) {
292: File subd = new File(storedir, Integer.toString(i));
293: if ((!subd.exists()) && !subd.mkdirs())
294: return false;
295: }
296: return true;
297: }
298:
299: /**
300: * Get the new store location.
301: * @param oldstore the Old store.
302: * @return a File instance
303: */
304: protected File getNewStore(File storedir, File oldstore) {
305: String rep = oldstore.getName();
306: if (rep.equals("root.idx")) {
307: return new File(storedir, "root.xml");
308: } else {
309: int number = Integer.parseInt(rep.substring(3));
310: return new File(storedir,
311: (number % ResourceStoreManager.SUBDIRS) + "/" + rep);
312: }
313: }
314:
315: /**
316: * Upgrade the stores (st-xxx) under the given store directory.
317: * @param storedir the store directory
318: * @param filter the filter to use to list the stores
319: */
320: protected void upgradeStores(File storedir, FilenameFilter filter)
321: throws UpgradeException {
322: File stores[] = storedir.listFiles(filter);
323: if (stores == null) {
324: System.err.println("No store files found!");
325: return;
326: }
327: System.out.print("Upgrading " + stores.length + " store files");
328: for (int i = 0; i < stores.length; i++) {
329: try {
330: Resource resources[] = readRepository(stores[i]);
331: File newstore = getNewStore(storedir, stores[i]);
332: Writer writer = new BufferedWriter(new FileWriter(
333: newstore));
334: serializer.writeResources(resources, writer);
335: System.out.print(".");
336: } catch (Exception ex) {
337: System.err.println("\n*** ERROR : unable to upgrade "
338: + stores[i].getName());
339: ex.printStackTrace();
340: }
341: }
342: System.out.println(" done.");
343: }
344:
345: /**
346: * Upgrade the stores (.db) under the given store directory.
347: * @param storedir the store directory
348: * @param filter the filter to use to list the stores
349: */
350: protected void upgradeDB(File storedir, FilenameFilter filter) {
351: File stores[] = storedir.listFiles(filter);
352: if (stores == null) {
353: System.err.println("No store files found!");
354: return;
355: }
356: System.out.print("Upgrading " + stores.length
357: + " store files...");
358: for (int i = 0; i < stores.length; i++) {
359: try {
360: Resource resources[] = readRepository(stores[i]);
361: Writer writer = new BufferedWriter(new FileWriter(
362: stores[i]));
363: serializer.writeResources(resources, writer);
364: System.out.print(".");
365: } catch (Exception ex) {
366: System.err.println("\n*** ERROR : unable to upgrade "
367: + stores[i].getName());
368: ex.printStackTrace();
369: }
370: }
371: System.out.println(" done.");
372: }
373:
374: /**
375: * backup the stores under the given store directory.
376: * @param storedir the store directory
377: * @param filter the filter to use to list the stores
378: */
379: protected void backupStores(File storedir, FilenameFilter filter)
380: throws IOException {
381: File backupdir = new File(storedir, "backup");
382: backupdir.mkdirs();
383: System.out.print("Doing backup, copying store files in \""
384: + backupdir.getAbsolutePath() + "\"...");
385: File files[] = storedir.listFiles(filter);
386: for (int i = 0; i < files.length; i++) {
387: File backuped = new File(files[i].getParentFile(),
388: "backup/" + files[i].getName());
389: org.w3c.util.IO.copy(files[i], backuped);
390: }
391: System.out.println(" done.");
392: }
393:
394: /**
395: * clean the stores under the given store directory.
396: * @param storedir the store directory
397: * @param filter the filter to use to list the stores
398: */
399: protected void cleanStores(File storedir, FilenameFilter filter)
400: throws IOException {
401: System.out.print("Cleaning stores in \""
402: + storedir.getAbsolutePath() + "\"...");
403: File files[] = storedir.listFiles(filter);
404: for (int i = 0; i < files.length; i++) {
405: files[i].delete();
406: }
407: System.out.println(" done.");
408: }
409:
410: /**
411: * Update the properties to add the serializer class in it.
412: */
413: protected void updateProperties(int version) {
414: System.out.println("\nUpgrading properties files...");
415: System.out.print("Updating \"" + props.getName() + "\"...");
416: Properties p = loadProps(props);
417: p
418: .put(httpd.SERIALIZER_CLASS_P,
419: "org.w3c.tools.resources.serialization.xml.XMLSerializer");
420: p.put(httpd.VERSCOUNT_P, String.valueOf(version));
421: saveProps(p, props);
422: System.out.println(" done.");
423: }
424:
425: private Properties loadProps(File file) {
426: Properties p = new Properties();
427: FileInputStream in = null;
428: try {
429: in = new FileInputStream(file);
430: p.load(in);
431: } catch (Exception ex) {
432: System.err.println("*** ERROR : " + ex.getMessage());
433: } finally {
434: try {
435: in.close();
436: } catch (Exception e) {
437: }
438: }
439: return p;
440: }
441:
442: private void saveProps(Properties p, File file) {
443: FileOutputStream out = null;
444: try {
445: out = new FileOutputStream(file);
446: p.store(out, "Updated by Upgrader");
447: } catch (Exception ex) {
448: System.err.println("*** ERROR : " + ex.getMessage());
449: } finally {
450: try {
451: out.close();
452: } catch (Exception e) {
453: }
454: }
455: }
456:
457: protected void checkDir(File dir) throws UpgradeException {
458: if (!dir.exists()) {
459: String msg = "*** ERROR : \"" + dir.getAbsolutePath()
460: + "\" doesn't exists, please check that \""
461: + dir.getParentFile().getParent()
462: + "\" is the Jigsaw Install Directory.";
463: throw new UpgradeException(msg);
464: } else if (!dir.isDirectory()) {
465: String msg = "*** ERROR : \"" + dir.getAbsolutePath()
466: + "\" is not a directory, please check that \""
467: + dir.getParentFile().getParent()
468: + "\" is the Jigsaw Install Directory.";
469: throw new UpgradeException(msg);
470: }
471: }
472:
473: /**
474: * The big stuff, upgrade the configuration in XML
475: * <ol>
476: * <li> Upgrade the resource stores
477: * <li> Upgrade the indexers (if any)
478: * <li> Upgrade the realms (if any)
479: * <li> Upgrade the properties files
480: * </ol>
481: * @exception IOException if an IO error occurs
482: */
483: public void upgrade(int version) throws IOException,
484: UpgradeException {
485: checkDir(config);
486:
487: //
488: // config/stores
489: //
490:
491: File storedir = new File(config, "stores");
492: checkDir(storedir);
493: System.out.println("Upgrading stores in \""
494: + storedir.getAbsolutePath() + "\"...");
495: updateEntriesIndex(storedir);
496: System.out.print("Creating subdirectories... ");
497: createSubDirs(storedir);
498: System.out.println("done.");
499: //store files
500: FilenameFilter storefilter = new FilenameFilter() {
501: public boolean accept(File dir, String name) {
502: return ((name.startsWith("st-") || name
503: .equals("root.idx")) && (!name.endsWith(".bak")));
504: }
505: };
506: FilenameFilter cleanfilter = new FilenameFilter() {
507: public boolean accept(File dir, String name) {
508: return (name.startsWith("st-")
509: || name.equals("root.idx")
510: || name.equals("root.idx.bak")
511: || name.equals("state")
512: || name.endsWith("-index") || name
513: .endsWith("-index.bak"));
514: }
515: };
516:
517: backupStores(storedir, cleanfilter);
518: upgradeStores(storedir, storefilter);
519: cleanStores(storedir, cleanfilter);
520:
521: //
522: // config/auth
523: //
524:
525: storefilter = new FilenameFilter() {
526: public boolean accept(File dir, String name) {
527: return name.endsWith(".db");
528: }
529: };
530: cleanfilter = new FilenameFilter() {
531: public boolean accept(File dir, String name) {
532: return name.endsWith(".bak");
533: }
534: };
535:
536: try {
537: File authdir = new File(config, "auth");
538: checkDir(authdir);
539: System.out.println("\nUpgrading realms in \""
540: + authdir.getAbsolutePath() + "\"...");
541: backupStores(authdir, storefilter);
542: upgradeDB(authdir, storefilter);
543: cleanStores(authdir, cleanfilter);
544: } catch (UpgradeException uex) {
545: //silent
546: }
547:
548: //
549: // config/idexers
550: //
551:
552: try {
553: File indexers = new File(config, "indexers");
554: checkDir(indexers);
555: System.out.println("\nUpgrading indexers in \""
556: + indexers.getAbsolutePath() + "\"...");
557: backupStores(indexers, storefilter);
558: upgradeDB(indexers, storefilter);
559: cleanStores(indexers, cleanfilter);
560: } catch (UpgradeException uex) {
561: //silent
562: }
563:
564: updateProperties(version);
565:
566: }
567:
568: /**
569: * Constructor
570: * @param server the server name
571: * @param config the server config directory
572: * @param props the server properties file
573: * @param serializer the XML Serializer
574: */
575: public Upgrader(String server, File config, File props,
576: Serializer serializer) {
577: this.server = server;
578: this.config = config;
579: this.props = props;
580: this.serializer = serializer;
581: }
582:
583: }
|