/* * Lokomo OneCMDB - An Open Source Software for Configuration * Management of Datacenter Resources * * Copyright (C) 2006 Lokomo Systems AB * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. * * Lokomo Systems AB can be contacted via e-mail: info@lokomo.com or via * paper mail: Lokomo Systems AB, Sv�rdv�gen 27, SE-182 33 * Danderyd, Sweden. * */ package org.onecmdb.ui.gwt.desktop.server.service.change; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.onecmdb.core.IRfcResult; import org.onecmdb.core.utils.bean.CiBean; import org.onecmdb.core.utils.bean.ValueBean; import org.onecmdb.core.utils.graph.query.GraphQuery; import org.onecmdb.core.utils.graph.query.constraint.AttributeValueConstraint; import org.onecmdb.core.utils.graph.query.selector.ItemAliasSelector; import org.onecmdb.core.utils.graph.query.selector.ItemOffspringSelector; import org.onecmdb.core.utils.graph.query.selector.ItemRelationSelector; import org.onecmdb.core.utils.graph.result.Graph; import org.onecmdb.core.utils.graph.result.Template; import org.onecmdb.core.utils.wsdl.IOneCMDBWebService; import org.onecmdb.core.utils.xml.XmlParser; import org.onecmdb.ui.gwt.desktop.client.service.CMDBRPCException; import org.onecmdb.ui.gwt.desktop.client.service.change.ChangeFilter; import org.onecmdb.ui.gwt.desktop.client.service.change.ChangeItem; import org.onecmdb.ui.gwt.desktop.client.service.change.ChangeRecord; import org.onecmdb.ui.gwt.desktop.client.service.change.ChangeResult; import org.onecmdb.ui.gwt.desktop.client.service.change.IChangeService; import org.onecmdb.ui.gwt.desktop.client.service.content.ContentData; import org.onecmdb.ui.gwt.desktop.client.service.content.ContentFile; import org.onecmdb.ui.gwt.desktop.client.service.model.CIModel; import org.onecmdb.ui.gwt.desktop.client.service.model.StoreResult; import org.onecmdb.ui.gwt.desktop.client.service.model.ValueListModel; import org.onecmdb.ui.gwt.desktop.client.service.model.ValueModel; import org.onecmdb.ui.gwt.desktop.client.service.model.mdr.MDRHistoryState; import org.onecmdb.ui.gwt.desktop.server.service.CMDBRPCHandler; import org.onecmdb.ui.gwt.desktop.server.service.content.ContentParserFactory; import org.onecmdb.ui.gwt.desktop.server.service.model.CMDBWebServiceFactory; import org.onecmdb.ui.gwt.desktop.server.service.model.Transform; import com.google.gwt.user.server.rpc.RemoteServiceServlet; public class ChangeServiceImpl extends RemoteServiceServlet implements IChangeService { private static final boolean CiBean = false; private IChangeStore changeStore; public IChangeStore getChangeStore() { if (changeStore == null) { changeStore = new ChangeStoreImpl(); } return changeStore; } public void setChangeStore(IChangeStore changeStore) { this.changeStore = changeStore; } public ChangeServiceImpl() { } public StoreResult commit(String token, CIModel mdr, CIModel config, CIModel mdrHistory, List<ChangeItem> items) throws Exception { System.out.println("Commit Changes<>"); CIMDRCollection localMDR = new CIMDRCollection(getMDRId(mdr, config)); for (ContentData file : getContentFiles(mdrHistory)) { if (!(file instanceof ContentFile)) { continue; } ICIMDR local = null; local = (ICIMDR) ContentParserFactory.get().getAdaptor(file, ICIMDR.class); if (local == null) { throw new IllegalArgumentException("Can't adapt content " + file.getName() + " to " + ICIMDR.class.getName()); } localMDR.add(local); } IChangeStore store = getChangeStore(); ICIMDR baseMDR = store.getBase(localMDR); ICIMDR remoteMDR = store.getRemote(); ReconciliationEngine engine = new ReconciliationEngine(token, localMDR, baseMDR, remoteMDR); IRfcResult result = engine.commit(items); System.out.println("Commit: " + result.isRejected() + " : " + result.getRejectCause()); if (!result.isRejected()) { store.commit(token, localMDR, items); } CIModel mdrHistoryCopy = null; if (mdrHistory.getIdAsString() != null) { mdrHistoryCopy = mdrHistory.copy(); } Transform.updateModel(mdrHistory, "txid", result.getTxId()); Transform.updateModel(mdrHistory, "added", result.getCiAdded()); Transform.updateModel(mdrHistory, "deleted", result.getCiDeleted()); Transform.updateModel(mdrHistory, "modified", result.getCiModified()); Transform.updateModel(mdrHistory, "rejected", result.isRejected()); Transform.updateModel(mdrHistory, "rejectCause", result.getRejectCause()); if (result.isRejected()) { Transform.updateModel(mdrHistory, "status", MDRHistoryState.REJECTED); } else { // Update the last COMMITTED to OUT_OF_DATE... Transform.updateModel(mdrHistory, "status", MDRHistoryState.COMMITTED); updateOutOfDateHistory(token, mdr, config, mdrHistory); } CiBean localHistBean = new Transform().convert(remoteMDR, token, mdrHistory); CiBean localHistBeanCopy = null; if (mdrHistoryCopy != null) { localHistBeanCopy = new Transform().convert(remoteMDR, token, mdrHistoryCopy); } // Store history... IOneCMDBWebService service = CMDBWebServiceFactory.get().getOneCMDBWebService(); service.update(token, new CiBean[] {localHistBean}, (localHistBeanCopy == null ? null : new CiBean[] {localHistBeanCopy})); //updateBean(this.mdrHistory, "commitStart", result.getStart()); //updateBean(this.mdrHistory, "commitStop", result.getStop()); // Store history.... StoreResult cRes = new StoreResult(); cRes.setRejected(result.isRejected()); cRes.setRejectCause(result.getRejectCause()); cRes.setTxId(result.getTxId()); cRes.setAdded(result.getCiAdded()); cRes.setModfied(result.getCiModified()); cRes.setDelted(result.getCiDeleted()); cRes.setStart(result.getStart()); cRes.setStop(result.getStop()); return(cRes); } public StoreResult delete(String token, CIModel mdr, CIModel config, CIModel mdrHistory, List<ChangeItem> items) throws Exception { System.out.println("Delete Items"); CIMDRCollection localMDR = new CIMDRCollection(getMDRId(mdr, config)); for (ContentData file : getContentFiles(mdrHistory)) { if (!(file instanceof ContentFile)) { continue; } ICIMDR local = null; local = (ICIMDR) ContentParserFactory.get().getAdaptor(file, ICIMDR.class); if (local == null) { throw new IllegalArgumentException("Can't adapt content " + file.getName() + " to " + ICIMDR.class.getName()); } localMDR.add(local); } IChangeStore store = getChangeStore(); ICIMDR baseMDR = store.getBase(localMDR); ICIMDR remoteMDR = store.getRemote(); ReconciliationEngine engine = new ReconciliationEngine(token, localMDR, baseMDR, remoteMDR); IRfcResult result = engine.delete(items); System.out.println("Delete: " + result.isRejected() + " : " + result.getRejectCause()); if (!result.isRejected()) { store.reset(token, localMDR, items); } CIModel mdrHistoryCopy = null; if (mdrHistory.getIdAsString() != null) { mdrHistoryCopy = mdrHistory.copy(); } Transform.updateModel(mdrHistory, "txid", result.getTxId()); Transform.updateModel(mdrHistory, "added", result.getCiAdded()); Transform.updateModel(mdrHistory, "deleted", result.getCiDeleted()); Transform.updateModel(mdrHistory, "modified", result.getCiModified()); Transform.updateModel(mdrHistory, "rejected", result.isRejected()); Transform.updateModel(mdrHistory, "rejectCause", result.getRejectCause()); if (result.isRejected()) { Transform.updateModel(mdrHistory, "status", MDRHistoryState.REJECTED); } else { // Update the last COMMITTED to OUT_OF_DATE... Transform.updateModel(mdrHistory, "status", MDRHistoryState.DELETED); updateOutOfDateHistory(token, mdr, config, mdrHistory); } CiBean localHistBean = new Transform().convert(remoteMDR, token, mdrHistory); CiBean localHistBeanCopy = null; if (mdrHistoryCopy != null) { localHistBeanCopy = new Transform().convert(remoteMDR, token, mdrHistoryCopy); } // Store history... IOneCMDBWebService service = CMDBWebServiceFactory.get().getOneCMDBWebService(); service.update(token, new CiBean[] {localHistBean}, (localHistBeanCopy == null ? null : new CiBean[] {localHistBeanCopy})); //updateBean(this.mdrHistory, "commitStart", result.getStart()); //updateBean(this.mdrHistory, "commitStop", result.getStop()); // Store history.... StoreResult cRes = new StoreResult(); cRes.setRejected(result.isRejected()); cRes.setRejectCause(result.getRejectCause()); cRes.setTxId(result.getTxId()); cRes.setAdded(result.getCiAdded()); cRes.setModfied(result.getCiModified()); cRes.setDelted(result.getCiDeleted()); cRes.setStart(result.getStart()); cRes.setStop(result.getStop()); return(cRes); } private void updateOutOfDateHistory(String token, CIModel mdr, CIModel config, CIModel currentHistory) { try { GraphQuery q = new GraphQuery(); ItemOffspringSelector history = new ItemOffspringSelector("history", MDRHistoryState.getHistoryTemplate()); AttributeValueConstraint aCon = new AttributeValueConstraint(); aCon.setAlias("status"); aCon.setValue(MDRHistoryState.COMMITTED); aCon.setOperation(AttributeValueConstraint.EQUALS); history.applyConstraint(aCon); ItemAliasSelector cfg = new ItemAliasSelector("cfg", config.getDerivedFrom()); cfg.setAlias(config.getAlias()); cfg.setPrimary(true); ItemRelationSelector history2cfg = new ItemRelationSelector("history2cfg", "Reference", cfg.getId(), history.getId()); q.addSelector(cfg); q.addSelector(history); q.addSelector(history2cfg); IOneCMDBWebService service; service = CMDBWebServiceFactory.get().getOneCMDBWebService(); Graph result = service.queryGraph(token, q); Template n = result.fetchNode(history.getId()); if (n == null) { return; } if (n.getOffsprings() == null || n.getOffsprings().size() == 0) { return; } List<CiBean> local = new ArrayList<CiBean>(); List<CiBean> base = new ArrayList<CiBean>(); for (CiBean hBean : n.getOffsprings()) { if (hBean.getAlias().equals(currentHistory.getAlias())) { continue; } base.add(hBean.copy()); ValueBean vBean = hBean.fetchAttributeValueBean("status", 0); if (vBean != null) { vBean.setValue(MDRHistoryState.OUT_OF_DATE); } local.add(hBean); } service.update(token, local.toArray(new CiBean[0]), base.toArray(new CiBean[0])); } catch (Exception e) { e.printStackTrace(); } } private String getMDRId(CIModel mdr, CIModel config) { String id = mdr.getValueAsString("name") + "/" + config.getValueAsString("name").replace(" ", "_"); return(id); } private List<ContentFile> getContentFiles(CIModel history) { List<ContentFile> files = new ArrayList<ContentFile>(); ValueModel value = history.getValue("files"); if (value == null) { return(files); } if (value instanceof ValueListModel) { for (ValueModel vModel : ((ValueListModel)value).getValues()) { if (vModel.getValue() != null) { ContentFile file = new ContentFile(vModel.getValue()); files.add(file); } } } else { if (value.getValue() != null) { ContentFile file = new ContentFile(value.getValue()); files.add(file); } } return(files); } public ChangeRecord loadChanges(String token, CIModel mdr, CIModel config, CIModel mdrHistory, ChangeFilter filter) throws CMDBRPCException { try { String id = getMDRId(mdr, config); System.out.println("Load Changes for MDR<" + id +">"); CIMDRCollection localMDR = new CIMDRCollection(id); for (ContentData content : getContentFiles(mdrHistory)) { if (!(content instanceof ContentFile)) { continue; } ICIMDR local = null; local = (ICIMDR) ContentParserFactory.get().getAdaptor(content, ICIMDR.class); if (local == null) { throw new IllegalArgumentException("Can't adapt content " + content.getName() + " to " + ICIMDR.class.getName()); } localMDR.add(local); } IChangeStore store = getChangeStore(); ICIMDR baseMDR = store.getBase(localMDR); ICIMDR remoteMDR = store.getRemote(); ReconciliationEngine engine = new ReconciliationEngine(token, localMDR, baseMDR, remoteMDR); List<ChangeItem> result = engine.reconciliate(); ChangeRecord record = new ChangeRecord(); record.setChangeItems(result); List<CiBean> cis = localMDR.getCI(token); // Produce statistics... int templateCount = 0; HashMap<String, Integer> map = new HashMap<String, Integer>(); for (CiBean ci : cis) { if (ci.isTemplate()) { templateCount++; } else { Integer count = map.get(ci.getDerivedFrom()); if (count == null) { count = new Integer(0); } map.put(ci.getDerivedFrom(), new Integer(count.intValue() + 1)); } } // Produce Summary text. StringBuffer summary = new StringBuffer(); summary.append("<p><b>Summary</b></br>"); summary.append(templateCount + " templates </br>"); for (String name : map.keySet()) { summary.append(map.get(name) + " " + name + " instances</br>"); } summary.append("</p>"); record.setSummary(summary.toString()); return(record); } catch (Throwable t) { t.printStackTrace(); throw new CMDBRPCException("Load Chnages", t.getMessage(), CMDBRPCHandler.getStackTrace(t)); } } }