package multimonster.systemadministration; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.sql.Blob; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import javax.jms.JMSException; import javax.naming.NamingException; import org.apache.log4j.Logger; import multimonster.common.setting.Setting; import multimonster.common.setting.SettingDomain; import multimonster.common.setting.SettingID; import multimonster.common.setting.SettingValue; import multimonster.common.util.MDBSender; import multimonster.exceptions.MultiMonsterException; import multimonster.systemadministration.exceptions.SettingNotExistsException; import multimonster.systemadministration.exceptions.SettingOutOfDomainException; public class SettingAdministration { private Logger log; /** * static Variable wird zur Datenhaltung w�hrend einer Systeminstanz (von Start bis Herunterfahren) * verwendet * reicht aus, da nur einmal gebraucht und auch nur hier * daher DB �berfl�ssig */ private static HashMap proxies = new HashMap(); public SettingAdministration() { log = Logger.getLogger(this.getClass()); } /** * Registriert ein SettingProxyObjekt und stellt somit die Verbindung zwischen * Prefix und ProxyObjekt her * * @param prefix das zugeordnete Prefix zur Komponente * @param proxy referenz auf SettingProxyObjekt * @return void */ public void registerSettingProxy(short prefix, SettingProxy proxy) { Short key = new Short(prefix); SettingAdministration.proxies.put(key, proxy); // // QueryManager und Connection holen // QueryManager qmnr = new QueryManager(); // int connNr = qmnr.reserveConnection(); // // String query = "insert into settingProxy values(" + prefix + ", '" + JNDIname + "');"; // // try { // qmnr.dbOpInsert(query, connNr); // } catch (MultiMonsterException e) { // // TODO better Exception handling // wasSuccessful = false; // e.printStackTrace(); // } // // wasSuccessful = true; // qmnr.bringBackConn(connNr); } /** * @see SettingAdministration#getAllSettings() * @return */ public Setting[] getAllSettings() { return getAllSettings((short)0); } /** * Registriert ein SettingProxyObjekt und stellt somit die Verbindung zwischen * Prefix und ProxyObjekt her * * @param prefix das zugeordnete Prefix zur Komponente * @param proxy referenz auf SettingProxyObjekt * @return void */ public Setting[] getAllSettings(short prefix) { Setting[] allSettings = null; // QueryManager und Connection holen QueryManager qmnr = new QueryManager(); int connNr = qmnr.reserveConnection(); String query = ""; if (prefix == 0) { // alle existierenden setting rausgeben query = "select * from setting;"; } else { query = "select * from setting where prefix = " + prefix + ";"; } ResultSet result = qmnr.dbOpExec(query, connNr); ArrayList list = new ArrayList(); try { while (result.next()) { //log.debug("Rows found: " + result.getFetchSize()); // Werte aus dem Resultset holen int setid = result.getInt("id"); String setName = result.getString("name"); Blob valueBlob = result.getBlob("value"); SettingValue setValue = (SettingValue) deserialize(valueBlob.getBytes(1, (int) valueBlob.length())); Blob domainBlob = result.getBlob("domain"); SettingDomain setDomain = (SettingDomain) deserialize(domainBlob.getBytes(1, (int) domainBlob.length())); String descr = result.getString("description"); Setting setting = new Setting(setName, setValue, setDomain, descr); setting.setId(new SettingID(setid)); list.add(setting); } } catch (SQLException e) { log.error("Fehler bei getAllSettings"); } allSettings = new Setting[list.size()]; for (int i = 0; i < list.size(); i++) { allSettings[i] = (Setting) list.get(i); } return allSettings; } /** * entfernt ein zuvor registriertes ProxyObjekt aus der DB * * @param prefix eindeutiger Zugriff auf ein ProxyObjekt * @return void */ public void removeSettingProxy(short prefix) { Short key = new Short(prefix); SettingAdministration.proxies.remove(key); // // QueryManager und Connection holen // QueryManager qmnr = new QueryManager(); // int connNr = qmnr.reserveConnection(); // // String query = "delete from settingProxy where prefix = " + prefix + ";"; // // try { // qmnr.dbOpInsert(query, connNr); // } catch (MultiMonsterException e) { // // TODO better exception handling // e.printStackTrace(); // wasSuccessful = false; // } // // wasSuccessful = true; // qmnr.bringBackConn(connNr); } /** * Gibt zu einem spezifizierten prefix die Referenz auf das zugeh�rige ProxyObjekt zur�ck * @param prefix * @return */ public SettingProxy getSettingProxy(short prefix) { SettingProxy proxy = null; // aus dem Prefix den Key machen Short key = new Short(prefix); // ProxyReferenz explizit casten proxy = (SettingProxy) SettingAdministration.proxies.get(key); return proxy; // String JNDIname = null; // // // QueryManager und Connection holen // QueryManager qmnr = new QueryManager(); // int connNr = qmnr.reserveConnection(); // // String query = "select JNDIname from settingProxy where prefix = " + prefix + ";"; // // ResultSet result = null; // result = qmnr.dbOpExec(query, connNr); // // try { // if (result.next()) { // JNDIname = result.getString(1); // } // } catch (SQLException e1) { // log.error("Fehler beim Holen des JNDIname f�r prefix " + prefix); // } // // return JNDIname; } /** * F�gt ein Setting in die DB ein. Vergibt f�r jedes neue Setting eine neue ID. * Diese SettingID wird als Returnwert zur�ckgeliefert. * * @param setting * @return SettingID */ public SettingID registerSetting(Setting setting) { QueryManager qmnr = new QueryManager(); int connNr = qmnr.reserveConnection(); // build statement String query = buildStatement_insertSetting(setting); // build BLOBs byte[] ba1 = serialize(setting.getValue()); byte[] ba2 = serialize(setting.getDomain()); // execute statement try { qmnr.dbOpInsertBLOB(query, ba1, ba2, connNr); } catch (MultiMonsterException e) { log.error("Fehler beim einf�gen von Setting in DB!"); } ResultSet result = null; result = qmnr.dbOpExec("SELECT LAST_INSERT_ID();", connNr); int settingID = 0; try { if (result.next()) { settingID = result.getInt(1); //log.debug("Setting ID vergeben: " + settingID); } } catch (SQLException e1) { log.error("Error getting last insert id!"); } SettingID setID = new SettingID(settingID); log.debug("Setting inserted in DB with ID=" + settingID); qmnr.bringBackConn(connNr); return setID; } public void releaseSetting(SettingID settingId) { } public void removeSetting(SettingID settingID) { } /** * Setzt den Wert eines Settings neu. * * @param settingID * @param value */ public void setValue(SettingID settingID, SettingValue value) throws SettingNotExistsException, SettingOutOfDomainException { if (settingID == null || value == null) { log.error("Einer der Parameter war null!"); return; } // Pr�fen ob Setting �berhaupt existiert if (checkSettingExistence(settingID) == false) { log.error("Setting mit dieser SettingID existiert nicht!"); throw new SettingNotExistsException("SettingID existiert nicht!"); } // Pr�fen ob Value innerhalb der SettingDomain liegt if (checkValueDomain(settingID, value) == false) { log.error("SettingValue liegt ausserhalb des Domain-Bereichs!"); throw new SettingOutOfDomainException(); } QueryManager qmnr = new QueryManager(); int connNr = qmnr.reserveConnection(); byte[] ba = serialize(value); // SettingId herausholen int setID = settingID.getId(); String query = "update setting set value = ? where id = " + setID + ";"; try { qmnr.dbOpUpdateBLOB(query, ba, connNr); } catch (MultiMonsterException e) { log.error("Fehler beim Update der Value mit id = " + setID); } qmnr.bringBackConn(connNr); //SettingChangeController asynchron aufrufen try { MDBSender.sendObjectMessage( SettingChangeControllerBean.JMS_QUEUE_NAME, settingID); } catch (NamingException e) { log.error(e); } catch (JMSException e) { log.error(e); } } /** * Die Methode gibt den Wert zu einer SettingID heraus. * * @param settingID * @return SettingValue (Error => null) */ public SettingValue getValue(SettingID settingID) throws SettingNotExistsException { if (settingID == null) { log.error("getValue mit Parameter = null aufgerufen!"); return null; } //SettingValue val = null; Object obj = null; SettingValue setval = null; int setID = settingID.getId(); QueryManager qmnr = new QueryManager(); int connNr = qmnr.reserveConnection(); // build statement String query = "select value from setting where id = " + setID + ";"; ResultSet result = qmnr.dbOpExec(query, connNr); try { if (result.next()) { Blob blob = result.getBlob(1); int bloblength = (int) blob.length(); byte[] ba = blob.getBytes(1, bloblength); obj = deserialize(ba); } else { log.error("Setting mit dieser SettingID existiert nicht!"); throw new SettingNotExistsException(); } } catch (SQLException e) { log.error("Fehler bei getValue: Wert auslesen aus setting"); } if (obj != null) { //log.debug("Try to cast to SettingValue"); try { setval = (SettingValue) obj; } catch (ClassCastException cce) { log.error( "Fehler beim Lesen von SettingValue aus DB mit id=" + setID); return null; } //log.debug("Cast erfolgreich abgeschlossen."); } else { log.warn("Deserialisiertes Object aus DB ist null f�r id=" + setID); throw new SettingNotExistsException(); } qmnr.bringBackConn(connNr); return setval; } /** * returns the human readable description for the given settingID * @param settingID * @return * @throws SettingNotExistsException */ public String getDescription(SettingID settingID) throws SettingNotExistsException { String descr = null; int setID = settingID.getId(); QueryManager qmnr = new QueryManager(); int connNr = qmnr.reserveConnection(); // build statement String query = "select description from setting where id = " + setID + ";"; ResultSet result = qmnr.dbOpExec(query, connNr); try { if (result.next()) { descr = result.getString(1); } else { log.error("Setting mit id = " + setID + " existiert nicht!"); throw new SettingNotExistsException( "Setting mit id = " + setID + " existiert nicht!"); } } catch (SQLException e) { log.error("Fehler bei checkExistence: DB Zugriff!"); } qmnr.bringBackConn(connNr); return descr; } /** * Bildet ein Mapping zwischen Klassennamen und eindeutigen * Prefixes f�r die Settings * Jedes Setting bekommt ein sogenanntes Prefix zugewiesen, * was die Zuordnung eines Settings zu einer Komponente erlaubt * * @param classname * @return */ public short getPrefix(String classname) { short prefix = -1; QueryManager qmnr = new QueryManager(); int connNr = qmnr.reserveConnection(); // build statement String query = "select prefix from componentprefix where classname = '" + classname + "';"; ResultSet result = qmnr.dbOpExec(query, connNr); if (result == null) { log.error("Fehlerhafte Query!!!"); return -1; } try { if (result.next()) { prefix = result.getShort("prefix"); //log.debug("getPrefix(): Prefix ist " + prefix); } else { // es gibt den Eintrag f�r diesen classname noch nicht // => neuen Vergeben und in die DB eintragen prefix = insertNewPrefix(classname); log.debug("getPrefix(): Neu vergebener Prefix ist " + prefix); } } catch (SQLException e) { log.error("Fehler bei getPrefix: lesen aus der DB!"); return -1; } catch (MultiMonsterException e) { log.error("Fehler beim neu Eintragen in die DB!"); return -1; } qmnr.bringBackConn(connNr); return prefix; } /** * returns the appropriate prefix for a given SettingID * @param classname * @return */ public short getPrefix(SettingID setID) { short prefix = 0; int settingID = 0; settingID = setID.getId(); if (settingID == 0) { return prefix; } QueryManager qmnr = new QueryManager(); int connNr = qmnr.reserveConnection(); // build statement String query = "select prefix from setting where id = '" + settingID + "';"; ResultSet result = qmnr.dbOpExec(query, connNr); if (result == null) { log.error("Fehlerhafte Query!!!"); return -1; } try { if (result.next()) { prefix = result.getShort("prefix"); log.debug("getPrefix(): Prefix ist " + prefix); } else { return prefix; } } catch (SQLException e) { log.error("Fehler bei getPrefix: lesen aus der DB!"); return -1; } qmnr.bringBackConn(connNr); return prefix; } /** * return the associated Domain for a given setting * @param settingID * @return * @throws SettingNotExistsException */ public SettingDomain getSettingDomain(SettingID settingID) throws SettingNotExistsException { SettingDomain domain = null; Object obj = null; int setID = settingID.getId(); QueryManager qmnr = new QueryManager(); int connNr = qmnr.reserveConnection(); // build statement String query = "select domain from setting where id = " + setID + ";"; ResultSet result = qmnr.dbOpExec(query, connNr); try { if (result.next()) { Blob blob = result.getBlob(1); int bloblength = (int) blob.length(); byte[] ba = blob.getBytes(1, bloblength); obj = deserialize(ba); } else { log.error("Setting mit dieser SettingID existiert nicht!"); throw new SettingNotExistsException( "Setting mit ID = " + setID + " existiert nicht!"); } } catch (SQLException e) { log.error("Fehler bei checkExistence: DB Zugriff!"); } if (obj != null) { try { domain = (SettingDomain) obj; } catch (ClassCastException cce) { log.error("getSettingDomain(): Can't cast to SettingDomain"); } } else { log.error("Deserialisieren des SettingDomain nicht m�glich!"); } qmnr.bringBackConn(connNr); return domain; } //******* Helper Methods ****************/ private String buildStatement_insertSetting(Setting setting) { String query = null; query = "insert into setting values(null, " + setting.getId().getPrefix() + " , '" + setting.getName() + "', ?, ?, '" + setting.getDescription() + "');"; //log.debug("Query for inserting setting: " + query); return query; } private byte[] serialize(Object object) { byte[] buf = null; String serObject = null; try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput objout = new ObjectOutputStream(bos); //log.debug("serialize: Outputstreams are set up"); objout.writeObject(object); //log.debug("serialize: Object was written into stream"); objout.close(); //log.debug("serialize: stream was closed"); // write to byteArray buf = bos.toByteArray(); //log.debug("serialized Object: " + buf); // // bring byte[] to String to use it with Database // StringBuffer intermediate = new StringBuffer(); // for (int i = 0; i < buf.length; i++) { // intermediate.append((char) buf[i]); // } // serObject = intermediate.toString(); // log.debug("serialize(): serialized Object: " + serObject); } catch (IOException e) { log.error("Fehler beim serialisieren eines setting-Objekts!"); } return buf; } private Object deserialize(byte[] buf) { Object result = null; //byte[] buf = null; try { // // bring String to byte[] by copying char for char // int bufferlength = serObject.length(); // buf = new byte[bufferlength]; // for (int j = 0; j < bufferlength; j++) { // buf[j] = (byte) serObject.charAt(j); // } ByteArrayInputStream byteIn = new ByteArrayInputStream(buf); //log.debug("deserialize: Byteinputstream was set up"); ObjectInputStream objin = new ObjectInputStream(byteIn); //log.debug("deserialize: ObjectInputStream was set up"); result = objin.readObject(); //log.debug("deserialize(): Objekt ausgelesen!"); } catch (IOException e) { log.error("deserialize(): Fehler beim Auslesen des Objekts"); } catch (ClassNotFoundException e) { log.error("deserialize(): ClassnotFound Exception"); } return result; } /** * Vergibt f�r Klassennamen ein eindeutiges Prefix * und legt es in der DB ab * * @param classname * @return */ private short insertNewPrefix(String classname) throws MultiMonsterException { short prefix = (new Integer(Math.abs(classname.hashCode()))).shortValue(); log.debug("Klasse erzeugt folgenden Hash: " + classname + " " + prefix); QueryManager qmnr = new QueryManager(); int connNr = qmnr.reserveConnection(); String query = "insert into componentprefix values('" + classname + "'," + prefix + " );"; try { qmnr.dbOpInsert(query, connNr); } catch (MultiMonsterException e) { log.error("Fehler beim einf�gen in componentprefix!"); //TODO Change Exception type throw new MultiMonsterException("Error while inserting in componentprefix!"); } return prefix; } /** * Pr�ft ob ein Setting schon in der DB existiert * * @param settingID * @return */ private boolean checkSettingExistence(SettingID settingID) { boolean exists = false; int setID = settingID.getId(); QueryManager qmnr = new QueryManager(); int connNr = qmnr.reserveConnection(); // build statement String query = "select * from setting where id = " + setID + ";"; ResultSet result = qmnr.dbOpExec(query, connNr); try { if (result.next()) { exists = true; } else { exists = false; } } catch (SQLException e) { log.error("Fehler bei checkExistence: DB Zugriff!"); } qmnr.bringBackConn(connNr); return exists; } /** * Pr�ft ob der Wert im vorgegebenen Domainbereich liegt * * @param settingID * @param value * @return * @throws SettingNotExistsException */ private boolean checkValueDomain(SettingID settingID, SettingValue value) throws SettingNotExistsException { boolean isOk = false; SettingDomain domain = null; //zuerst Domain holen domain = getSettingDomain(settingID); if (domain.isContinuous() == true) { // Setting is continous data-type Comparable lower = domain.getLowerLimit(); Comparable upper = domain.getUpperLimit(); Comparable setVal = value.getValueCont(); // Value must lie in between lower and upper limit if (lower.compareTo(setVal) <= 0 && upper.compareTo(setVal) >= 0) { isOk = true; } } else { // Setting is discrete data-type Object[] objects = domain.getDiscrete(); Object setVal = value.getValueDiscr(); for (int i = 0; i < objects.length; i++) { if (objects[i].equals(setVal) == true) { isOk = true; } } } return isOk; } }