View Javadoc
1 /* 2 * PROJECT : DAR Runtime and Tools 3 * COPYRIGHT : Copyright (C) 1999-2004 tim.stephenson@enableit.org 4 * LICENSE : GNU LESSER GENERAL PUBLIC LICENSE 5 * Version 2.1, February 1999 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22 package org.enableit.db.darrt; 23 24 import java.io.File; 25 import java.io.IOException; 26 import java.io.InputStreamReader; 27 import java.io.OutputStream; 28 import java.io.StringWriter; 29 import java.net.MalformedURLException; 30 import java.net.URL; 31 import java.rmi.RemoteException; 32 import java.util.ArrayList; 33 import java.util.Enumeration; 34 import java.util.Iterator; 35 import java.util.List; 36 import java.util.Map; 37 import java.util.zip.ZipEntry; 38 import java.util.zip.ZipFile; 39 import java.util.zip.ZipOutputStream; 40 41 import org.apache.axis.utils.DOM2Writer; 42 import org.apache.log4j.Logger; 43 import org.enableit.db.DBException; 44 import org.enableit.db.beans.Column; 45 import org.enableit.db.beans.Database; 46 import org.enableit.db.beans.ForeignKey; 47 import org.enableit.db.beans.Provider; 48 import org.enableit.db.beans.ProviderExt; 49 import org.enableit.db.beans.RowSet; 50 import org.enableit.db.beans.Schema; 51 import org.enableit.db.beans.Table; 52 import org.exolab.castor.xml.CastorException; 53 import org.exolab.castor.xml.MarshalException; 54 import org.exolab.castor.xml.Unmarshaller; 55 import org.exolab.castor.xml.ValidationException; 56 import org.w3c.dom.Document; 57 58 59 /*** 60 * Manipulates Database Archives (.dar) files. 61 */ 62 public class DarHandler implements FileProcessor { 63 64 /*** 65 * CVS info ABOUT this class and its current version 66 */ 67 public static final String ABOUT = "$Revision: 1.13 $"; 68 69 /*** 70 * Name of .DAR entry representing the schema deployment descriptor. 71 */ 72 public static final String SCHEMA_ENTRY = "META-INF/schema.xml"; 73 74 /*** 75 * The Log4J <code>Logger</code> doing the logging. 76 */ 77 private static Logger logger = Logger.getLogger(DarHandler.class); 78 79 private Provider target; 80 81 private List importedRowsets; 82 83 /*** 84 * Debug flag 85 */ 86 private boolean debug = false; 87 88 /*** 89 * Default Constructor. 90 */ 91 public DarHandler() { 92 } 93 94 /*** 95 * Sets the dar file name. 96 */ 97 public void setDebug(boolean debug) { 98 this.debug = debug; 99 } 100 101 public void create(OutputStream out, Database database) 102 throws DBException, DarHandlingException { 103 create(out, database, new ArrayList()); 104 } 105 106 /*** 107 * Creates a .dar file. 108 * 109 * <p><b>Implementation Note:</b> Once there is a good take up of the 110 * generics capability on JDK 1.5 this method will be refactored into 111 * two or more methods overloading the <code>List<code> parameter with 112 * typed lists.</p> 113 * 114 * @param out The stream to write the .dar to. 115 * @param database Identifies <code>Provider</code> and other meta-data 116 * for the .dar. 117 * @param dataList <code>List</code> of <code>Strings</code> naming 118 * tables to export or <code>RowSets</code> of already exported data. 119 * <em>See implementation note above.</em> 120 * @throws DBException 121 * @throws DarHandlingException 122 */ 123 public void create(OutputStream out, Database database, List dataList) 124 throws DBException, DarHandlingException { 125 try { 126 ZipOutputStream zos = new ZipOutputStream(out); 127 128 // Do schema entry 129 zos.putNextEntry(new ZipEntry(SCHEMA_ENTRY)); 130 131 StringWriter databaseXml = new StringWriter(); 132 133 database.marshal(databaseXml); 134 databaseXml.close(); 135 zos.write(databaseXml.toString().getBytes()); 136 zos.closeEntry(); 137 138 // Do data entries 139 DataHandler dataHandler = new DataHandler(); 140 141 dataHandler.setOnlineRefSchema(database.getProvider()); 142 143 for (Iterator it = dataList.iterator(); it.hasNext();) { 144 Object obj = it.next(); 145 146 if (obj instanceof String) { 147 // Though method accepts table pattern, can supply exact match 148 dataHandler.setTablePattern((String) obj); 149 150 Map dataMap = dataHandler.export(); 151 152 logger.debug("data exported: " + dataMap); 153 154 for (Iterator j = dataMap.keySet().iterator(); j.hasNext();) { 155 String key = (String) j.next(); 156 Document doc = (Document) dataMap.get(key); 157 158 addDataItem(zos, key, doc); 159 } 160 } else if (obj instanceof RowSet) { 161 RowSet rs = (RowSet) obj; 162 163 addDataItem(zos, rs); 164 } else { 165 throw new IllegalArgumentException(); 166 } 167 } 168 169 zos.close(); 170 } catch (java.io.IOException e) { 171 logger.error(e.getMessage(), e); 172 throw new DarHandlingException(e.getMessage(), e); 173 } catch (MarshalException e) { 174 logger.error(e.getMessage(), e); 175 throw new DarHandlingException(e.getMessage(), e); 176 } catch (ValidationException e) { 177 logger.error(e.getMessage(), e); 178 throw new DarHandlingException(e.getMessage(), e); 179 180 /* } catch (DBException e) { 181 // Should already be logged 182 throw new DarHandlingException(e.getMessage(), e) ;*/ 183 } 184 } 185 186 private void addDataItem(ZipOutputStream zos, RowSet rowSet) 187 throws IOException, DarHandlingException { 188 zos.putNextEntry(new ZipEntry("data/" + rowSet.getTable() + ".xml")); 189 190 StringWriter dataXml = new StringWriter(); 191 192 try { 193 rowSet.marshal(dataXml); 194 } catch (MarshalException e) { 195 logger.error(e.getMessage(), e); 196 throw new DarHandlingException(e.getMessage(), e); 197 } catch (ValidationException e) { 198 logger.error(e.getMessage(), e); 199 throw new DarHandlingException(e.getMessage(), e); 200 } 201 202 dataXml.close(); 203 zos.write(dataXml.toString().getBytes()); 204 zos.closeEntry(); 205 } 206 207 private void addDataItem(ZipOutputStream zos, String key, Document doc) 208 throws IOException { 209 // Add zip entry 210 zos.putNextEntry(new ZipEntry("data/" + key + ".xml")); 211 212 StringWriter dataXml = new StringWriter(); 213 214 //((RowSet) dataMap.get(key)).marshal(dataXml) ; 215 if (doc != null) { 216 DOM2Writer.serializeAsXML(doc, dataXml, true, false); 217 } 218 219 dataXml.close(); 220 zos.write(dataXml.toString().getBytes()); 221 zos.closeEntry(); 222 } 223 224 /*** 225 * Installs a data archive in its entirety. 226 */ 227 public void install(URL url) 228 throws DBException { 229 logger.info("METHOD_ENTRY: install, url=" + url); 230 231 List errorSets = new ArrayList(); 232 233 try { 234 // Check the dar exists 235 ZipFile dar = null; 236 237 if ("file".equals(url.getProtocol())) { 238 File darFile = new File(url.getFile()); 239 240 if (!darFile.exists()) { 241 throw new DarHandlingException("Could not locate dar: " 242 + darFile); 243 } 244 245 dar = new ZipFile(darFile); 246 } else { 247 Object darObj = url.getContent(); 248 249 logger.debug("Found dar is instance of: " 250 + dar.getClass().getName()); 251 } 252 253 if (dar == null) { 254 throw new DarHandlingException("Could not locate dar: " + url); 255 } 256 257 // Get the deployment descriptor 258 ZipEntry dd = dar.getEntry(SCHEMA_ENTRY); 259 InputStreamReader isr = new InputStreamReader(dar.getInputStream(dd)); 260 Database schema = (Database) Unmarshaller.unmarshal(Database.class, 261 isr); 262 263 if (target == null) { 264 target = schema.getProvider(); 265 } 266 267 // Install the schema 268 SchemaHandler sh = new SchemaHandler(); 269 270 sh.setDebug(debug); 271 sh.setRefDatabase(schema); 272 sh.setOnlineTargetSchema(target); 273 sh.createSchema(); 274 275 // Register schema 276 MetaDataFactory mdf = MetaDataFactory.getInstance() ; 277 mdf.setMetaData(target, schema) ; 278 279 // Iterate archive entries processing them according to DAR format 280 DataHandler dh = new DataHandler(); 281 // Provider provider = schema.getProvider(); 282 List tableList = new ArrayList(); 283 importedRowsets = new ArrayList() ; 284 285 for (Enumeration entries = dar.entries(); 286 entries.hasMoreElements();) { 287 ZipEntry entry = (ZipEntry) entries.nextElement(); 288 289 if (!entry.isDirectory() && entry.getName().startsWith("data/")) { 290 logger.warn("Installing XML data from: " + entry.getName()); 291 292 // Collect table names 293 tableList.add(entry.getName().substring(5, 294 entry.getName().lastIndexOf("."))) ; 295 296 // Install data 297 importData(errorSets, dh, target, schema, dar, entry); 298 } else { 299 if (!entry.getName().equals(SCHEMA_ENTRY)) { 300 logger.warn("Unhandled archive entry: " 301 + entry.getName()); 302 } 303 } 304 } 305 } catch (IOException e) { 306 logger.error("IO exception: " + e.getMessage(), e); 307 } catch (CastorException e) { 308 logger.error("Castor exception: " + e.getMessage(), e); 309 } finally { 310 if ((errorSets != null) && (errorSets.size() > 0)) { 311 throw new DarHandlingException(errorSets); 312 } 313 } 314 315 logger.info("METHOD_EXIT: install"); 316 } 317 318 private void importData( 319 List errorSets, DataHandler dh, Provider provider, 320 Database schema, ZipFile dar, ZipEntry entry) 321 throws DBException, IllegalArgumentException, IOException { 322 logger.info("METHOD_ENTRY importData, provider: " 323 + ProviderExt.toString(provider)) ; 324 325 if (importedRowsets.contains(entry.getName())) { 326 return ; 327 } 328 329 RowSet rows = null; 330 try { 331 // Unmarshal and delegate import to data handler 332 String tableName = entry.getName().substring(5, 333 entry.getName().lastIndexOf(".")); 334 335 Table table = getMetaData(schema, tableName); 336 337 // Check if there is reference data to load first 338 for (int i = 0 ; i < table.getColumnCount() ; i++) { 339 Column col = table.getColumn(i) ; 340 if (col.getForeignKey() != null) { 341 ForeignKey fk = col.getForeignKey() ; 342 String fkTable = fk.getFkTableName() ; 343 if (dar.getEntry("data/" + fkTable + ".xml") != null) { 344 logger.warn("Detected dependency on table: " + fkTable) ; 345 String entryName = "data/" + fkTable + ".xml" ; 346 importData(errorSets, dh, provider, schema, dar, 347 dar.getEntry(entryName)) ; 348 importedRowsets.add(entryName) ; 349 } 350 } 351 } 352 353 DataParser parser = DataParserFactory.getInstance(entry 354 .getName()); 355 356 rows = parser.getRowSet(dar.getInputStream(entry), table); 357 dh.importData(provider, rows); 358 importedRowsets.add(entry.getName()) ; 359 } catch (DataImportException e) { 360 // Record failure and continue with next file 361 logger.error("Failed to install data from file: " 362 + entry.getName()); 363 logger.error("... becos: " + e.getMessage(), e); 364 365 if (e instanceof DataImportException) { 366 errorSets.add(((DataImportException) e) 367 .getErrorRowSet()); 368 } else { 369 errorSets.add(rows); 370 } 371 } 372 } 373 374 /*** 375 * @param db The entire database def'n containing all table def'ns. 376 * @param tableName The table def'n sought. 377 * @return Table def'n, never null. 378 * @throws DBException If table def not found in either dar or 379 * the target database. 380 */ 381 private Table getMetaData(Database db, String tableName) throws DBException { 382 Table table = null ; 383 for (int i = 0 ; i < db.getSchemaCount() ; i++) { 384 Schema schema = db.getSchema(i) ; 385 for (int j = 0 ; j < schema.getTableCount() ; j++) { 386 if (schema.getTable(j).getName().equals(tableName)) { 387 table = schema.getTable(j) ; 388 } 389 } 390 } 391 392 if (table == null) { 393 MetaDataFactory factory = MetaDataFactory.getInstance(); 394 table = factory.getMetaData(db.getProvider(), tableName) ; 395 } 396 return table ; 397 } 398 399 /* (non-Javadoc) 400 * @see org.enableit.db.darrt.FileProcessor#process(java.io.File, java.lang.String) 401 */ 402 public void process(File file, String fileType) 403 throws ConfigurationException, DBException, RemoteException { 404 try { 405 install(file.toURL()); 406 } catch (MalformedURLException e) { 407 String msg = "Error installing DAR"; 408 409 logger.error(msg, e); 410 throw new ConfigurationException(msg, e); 411 } 412 } 413 414 /*** 415 * Override the target for the DAR file to be imported to. 416 * @see org.enableit.db.darrt.FileProcessor#setProvider(org.enableit.db.beans.Provider) 417 */ 418 public void setProvider(Provider provider) 419 throws ConfigurationException, DBException, RemoteException { 420 this.target = provider; 421 } 422 }

This page was automatically generated by Maven