Java tutorial
/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.com * ******************************************************************************* * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ package org.pentaho.di.shared; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.Collection; import java.util.Hashtable; import java.util.List; import java.util.Map; import org.apache.commons.vfs.FileObject; import org.pentaho.di.cluster.ClusterSchema; import org.pentaho.di.cluster.SlaveServer; import org.pentaho.di.core.Const; import org.pentaho.di.core.database.DatabaseMeta; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.exception.KettleXMLException; import org.pentaho.di.core.variables.Variables; import org.pentaho.di.core.vfs.KettleVFS; import org.pentaho.di.core.xml.XMLHandler; import org.pentaho.di.i18n.BaseMessages; import org.pentaho.di.partition.PartitionSchema; import org.pentaho.di.trans.step.StepMeta; import org.pentaho.metastore.api.IMetaStore; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Based on a piece of XML, this factory will give back a list of objects. In other words, it does XML de-serialisation * * @author Matt * */ public class SharedObjects { private static Class<?> PKG = SharedObjects.class; // for i18n purposes, needed by Translator2!! private static final String XML_TAG = "sharedobjects"; private String filename; private Map<SharedEntry, SharedObjectInterface> objectsMap; private class SharedEntry { public String className; public String objectName; /** * @param className * @param objectName */ public SharedEntry(String className, String objectName) { this.className = className; this.objectName = objectName; } public boolean equals(Object obj) { SharedEntry sharedEntry = (SharedEntry) obj; return className.equals(sharedEntry.className) && objectName.equalsIgnoreCase(objectName); } public int hashCode() { return className.hashCode() ^ objectName.hashCode(); } } public SharedObjects(String sharedObjectsFile) throws KettleXMLException { try { this.filename = createFilename(sharedObjectsFile); this.objectsMap = new Hashtable<SharedEntry, SharedObjectInterface>(); // Extra information FileObject file = KettleVFS.getFileObject(filename); // If we have a shared file, load the content, otherwise, just keep this one empty if (file.exists()) { Document document = XMLHandler.loadXMLFile(file); Node sharedObjectsNode = XMLHandler.getSubNode(document, XML_TAG); if (sharedObjectsNode != null) { List<SlaveServer> privateSlaveServers = new ArrayList<SlaveServer>(); List<DatabaseMeta> privateDatabases = new ArrayList<DatabaseMeta>(); NodeList childNodes = sharedObjectsNode.getChildNodes(); // First load databases & slaves // for (int i = 0; i < childNodes.getLength(); i++) { Node node = childNodes.item(i); String nodeName = node.getNodeName(); SharedObjectInterface isShared = null; if (nodeName.equals(DatabaseMeta.XML_TAG)) { DatabaseMeta sharedDatabaseMeta = new DatabaseMeta(node); isShared = sharedDatabaseMeta; privateDatabases.add(sharedDatabaseMeta); } else if (nodeName.equals(SlaveServer.XML_TAG)) { SlaveServer sharedSlaveServer = new SlaveServer(node); isShared = sharedSlaveServer; privateSlaveServers.add(sharedSlaveServer); } if (isShared != null) { isShared.setShared(true); storeObject(isShared); } } // Then load the other objects that might reference databases & slaves // for (int i = 0; i < childNodes.getLength(); i++) { Node node = childNodes.item(i); String nodeName = node.getNodeName(); SharedObjectInterface isShared = null; if (nodeName.equals(StepMeta.XML_TAG)) { StepMeta stepMeta = new StepMeta(node, privateDatabases, (IMetaStore) null); stepMeta.setDraw(false); // don't draw it, keep it in the tree. isShared = stepMeta; } else if (nodeName.equals(PartitionSchema.XML_TAG)) { isShared = new PartitionSchema(node); } else if (nodeName.equals(ClusterSchema.XML_TAG)) { isShared = new ClusterSchema(node, privateSlaveServers); } if (isShared != null) { isShared.setShared(true); storeObject(isShared); } } } } } catch (Exception e) { throw new KettleXMLException( BaseMessages.getString(PKG, "SharedOjects.Readingfile.UnexpectedError", sharedObjectsFile), e); } } public static final String createFilename(String sharedObjectsFile) { String filename; if (Const.isEmpty(sharedObjectsFile)) { // First fallback is the environment/kettle variable ${KETTLE_SHARED_OBJECTS} // This points to the file filename = Variables.getADefaultVariableSpace().getVariable(Const.KETTLE_SHARED_OBJECTS); // Last line of defence... if (Const.isEmpty(filename)) { filename = Const.getSharedObjectsFile(); } } else { filename = sharedObjectsFile; } return filename; } public SharedObjects() throws KettleXMLException { this(null); } public Map<SharedEntry, SharedObjectInterface> getObjectsMap() { return objectsMap; } public void setObjectsMap(Map<SharedEntry, SharedObjectInterface> objects) { this.objectsMap = objects; } /** * Store the sharedObject in the object map. It is possible to have 2 different types of shared object with the same * name. They will be stored separately. * * @param sharedObject */ public void storeObject(SharedObjectInterface sharedObject) { SharedEntry key = new SharedEntry(sharedObject.getClass().getName(), sharedObject.getName()); objectsMap.put(key, sharedObject); } /** * Remove the sharedObject from the object map. * * @param sharedObject */ public void removeObject(SharedObjectInterface sharedObject) { SharedEntry key = new SharedEntry(sharedObject.getClass().getName(), sharedObject.getName()); objectsMap.remove(key); } public void saveToFile() throws IOException, KettleException { FileObject fileObject = KettleVFS.getFileObject(filename); if (fileObject.exists()) { // Create a backup before overwriting... // FileObject backupFile = KettleVFS.getFileObject(filename + ".backup"); fileObject.moveTo(backupFile); } OutputStream outputStream = KettleVFS.getOutputStream(fileObject, false); PrintStream out = new PrintStream(outputStream); out.print(XMLHandler.getXMLHeader(Const.XML_ENCODING)); out.println("<" + XML_TAG + ">"); Collection<SharedObjectInterface> collection = objectsMap.values(); for (SharedObjectInterface sharedObject : collection) { out.println(sharedObject.getXML()); } out.println("</" + XML_TAG + ">"); out.flush(); out.close(); outputStream.close(); } /** * @return the filename */ public String getFilename() { return filename; } /** * @param filename * the filename to set */ public void setFilename(String filename) { this.filename = filename; } /** * Return the shared object with the given class and name * * @param clazz * The class of the shared object * @param objectName * the name of the object * @return The shared object or null if none was found. */ public SharedObjectInterface getSharedObject(Class<SharedObjectInterface> clazz, String objectName) { return getSharedObject(clazz.getName(), objectName); } /** * Return the shared object with the given class name and object name * * @param clasName * The class name of the shared object * @param objectName * the name of the object * @return The shared object or null if none was found. */ public SharedObjectInterface getSharedObject(String className, String objectName) { SharedEntry entry = new SharedEntry(className, objectName); return objectsMap.get(entry); } /** * Get the shared database with the specified name * * @param name * The name of the shared database * @return The database or null if nothing was found. */ public DatabaseMeta getSharedDatabase(String name) { return (DatabaseMeta) getSharedObject(DatabaseMeta.class.getName(), name); } }