diff options
Diffstat (limited to 'ncomp-sirius-manager-server/src/main/java/org/openecomp/ncomp/sirius/manager/ManagementServer.java')
-rw-r--r-- | ncomp-sirius-manager-server/src/main/java/org/openecomp/ncomp/sirius/manager/ManagementServer.java | 2528 |
1 files changed, 2528 insertions, 0 deletions
diff --git a/ncomp-sirius-manager-server/src/main/java/org/openecomp/ncomp/sirius/manager/ManagementServer.java b/ncomp-sirius-manager-server/src/main/java/org/openecomp/ncomp/sirius/manager/ManagementServer.java new file mode 100644 index 0000000..cdddcf2 --- /dev/null +++ b/ncomp-sirius-manager-server/src/main/java/org/openecomp/ncomp/sirius/manager/ManagementServer.java @@ -0,0 +1,2528 @@ + +/*- + * ============LICENSE_START========================================== + * OPENECOMP - DCAE + * =================================================================== + * Copyright (c) 2017 AT&T Intellectual Property. All rights reserved. + * =================================================================== + * 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. + * ============LICENSE_END============================================ + */ + +package org.openecomp.ncomp.sirius.manager; + +import static org.openecomp.ncomp.sirius.manager.ManagementServerUtils.printStackTrace; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.TimeZone; +import java.util.concurrent.atomic.AtomicLong; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.log4j.Logger; +import org.eclipse.emf.common.util.BasicEList; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EAnnotation; +import org.eclipse.emf.ecore.EAttribute; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EDataType; +import org.eclipse.emf.ecore.EEnum; +import org.eclipse.emf.ecore.EFactory; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EOperation; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EParameter; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.util.EDataTypeEList; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import org.openecomp.entity.EcompComponent; +import org.openecomp.entity.EcompSubComponent; +import org.openecomp.entity.EcompSubComponentInstance; +import org.openecomp.ncomp.component.Api; +import org.openecomp.ncomp.component.ApiRequestStatus; +import org.openecomp.ncomp.component.ComponentClass; +import org.openecomp.ncomp.component.ComponentFactory; +import org.openecomp.ncomp.component.DroolsObjectChange; +import org.openecomp.ncomp.core.HasOperationalState; +import org.openecomp.ncomp.core.NamedEntity; +import org.openecomp.ncomp.core.OperationalState; +import org.openecomp.ncomp.core.function.Function; +import org.openecomp.ncomp.sirius.manager.drools.DroolsRuntime; +import org.openecomp.ncomp.sirius.manager.logs.LogMessageManager; +import org.openecomp.ncomp.sirius.manager.metrics.MetricManager; +import org.openecomp.ncomp.sirius.manager.properties.PropertyManager; +import org.openecomp.ncomp.sirius.manager.server.AbstractManagementServer; +import org.openecomp.ncomp.sirius.manager.server.LoggerInfo; +import org.openecomp.ncomp.utils.PropertyUtil; +import org.openecomp.ncomp.utils.SortUtil; +import org.openecomp.ncomp.utils.StringUtil; +import org.openecomp.ncomp.webservice.utils.FileUtils; +import org.openecomp.ncomp.webservice.utils.JsonUtils; + +public class ManagementServer implements IRequestHandler, ISwaggerHandler { + public static final Logger logger = Logger.getLogger(ManagementServer.class); + private static final String PERSIST = "http://openecomp.org/sirius/persistence"; + private Jetty8Client jettyClient; + private Properties props; + private String directory; + private EObject root; + private IPolicyEngine pe = new SimplePolicyEngine(); + private DroolsRuntime droolsRuntime; + + private EFactory eFactory; + private String eClassName; + private String propertyFileName; + public LogMessageManager logs; + public MetricManager metrics; + public PropertyManager properties; + public boolean isSlave = false; + + public ManagementServer(EFactory eFactory, String eClassName, String directory, String propertyFileName) { + TimeZone.setDefault(TimeZone.getTimeZone("GMT")); + this.eFactory = eFactory; + this.eClassName = eClassName; + this.directory = directory; + this.propertyFileName = propertyFileName; + try { + props = PropertyUtil.getPropertiesFromClasspath(this.propertyFileName); + EcompComponent.initialize(props.getProperty("ecomp.component", "UNKNOWN_COMPONENT")); + EcompSubComponent.initialize(props.getProperty("ecomp.subcomponent", "UNKNOWN_SUBCOMPONENT")); + logs = new LogMessageManager(this); + metrics = new MetricManager(this); + properties = new PropertyManager(this); + } catch (Exception e) { + printStackTrace(e); + System.exit(1); + } + // logger.info("Starting Management Server"); + // jettyClient = new Jetty8Client(); + } + + public ManagementServer() { + // TODO Auto-generated constructor stub + } + + static AtomicLong requestId = new AtomicLong(); + + @Override + public Object handleJson(String userName, String action, String resourcePath, JSONObject json, JSONObject context) { + logger.debug("handleJson: " + userName + " " + action + " " + resourcePath + " " + context.get("remoteIp")); + long start = new Date().getTime(); + String reqId = Long.toString(start) + ":" + requestId.incrementAndGet(); + context.put("requestId", reqId); + Logger logger2 = findRequestLogger(userName, action, resourcePath, context); + if (logger2.isInfoEnabled()) { + JSONObject r = new JSONObject(); + r.put("id", reqId); + r.put("start", start); + r.put("user", userName); + r.put("action", action); + r.put("path", resourcePath); + r.put("req", json); + r.put("context", context); + logger2.info(r.toString()); + } + if (!pe.permit(userName, action, resourcePath)) { + handleJsonReportResult(reqId, start, null, "NOT_PERMITTED", logger2); + throw new RuntimeException("Action not permitted: " + userName + " " + action + " " + resourcePath); + } + Subject subject = find(resourcePath); + if (action.equals("UPDATE")) { + if (subject == null || subject.o == null) { + throw new RuntimeException("Unable to find to update: " + resourcePath); + } + boolean useNulls = false; + if (context != null && context.has("parameters")) { + JSONObject m = (JSONObject) context.get("parameters"); + useNulls = m.has("useNulls"); + } + try { + Object res = update(userName, subject, json, useNulls); + handleJsonReportResult(reqId, start, res, "OK", logger2); + return res; + } catch (RuntimeException e) { + handleJsonReportResult(reqId, start, null, "ERROR", logger2); + printStackTrace(e); + throw e; + } + } + if (action.equals("CREATE")) { + String id = null; + if (subject != null) { + if (subject.ref == null || subject.ref.isMany()) { + handleJsonReportResult(reqId, start, null, "CREATE_ON_EXISTING_RESOURCE", logger2); + throw new RuntimeException("resource already exists: " + resourcePath); + } + } else { + int index = resourcePath.lastIndexOf("/"); + id = resourcePath.substring(index + 1, resourcePath.length()); + subject = find(resourcePath.substring(0, index)); + if (subject == null || subject.o == null) { + throw new RuntimeException("unable to find resource"); + } + if (subject.ref == null) + subject.ref = findRefByName(subject.o, id); + else + json.put("name", id); + } + Object res = create(subject, json, !json.has("$nosave")); + handleJsonReportResult(reqId, start, res, "OK", logger2); + return res; + } + if (action.equals("DELETE")) { + if (subject == null || subject.o == null) { + throw new RuntimeException("Unable to find to delete: " + resourcePath); + } + Object res = delete(subject); + handleJsonReportResult(reqId, start, res, "OK", logger2); + return res; + } + if (action.equals("LIST")) { + int levels = 1; + if (context != null && context.has("parameters")) { + JSONObject m = (JSONObject) context.get("parameters"); + if (m.has("levels")) + levels = Integer.parseInt((String) m.get("levels")); + if (m.has("match")) { + JSONObject res = new JSONObject(); + res.put("list", list2jsonArray(findAll(resourcePath))); + handleJsonReportResult(reqId, start, res, "OK", logger2); + return res; + } + if (m.has("references")) { + boolean b = m.getBoolean("references"); + JSONObject res = new JSONObject(); + if (subject == null || subject.o == null) { + throw new RuntimeException("Unable to find object: " + resourcePath); + } + res.put("list", subjectList2jsonArray(findReferences(root, subject.o, b))); + handleJsonReportResult(reqId, start, res, "OK", logger2); + return res; + } + } + if (subject == null || subject.o == null) { + throw new RuntimeException("Unable to find to list: " + resourcePath); + } + Object res = list(subject, levels); + handleJsonReportResult(reqId, start, res, "OK", logger2); + return res; + } + if (subject == null || subject.o == null) { + throw new RuntimeException("Unable to find object for operation: " + resourcePath); + } + Object res = operation(subject, action, json, context); + transformResult(subject,action,res); + handleJsonReportResult(reqId, start, res, "OK", logger2); + return res; + } + + private void transformResult(Subject subject, String action, Object res) { + String a = (subject != null && subject.o != null) ? ( subject.o.eClass().getInstanceClassName() + "@" + action ) : action; +// System.out.println("KKKKKKK:" + subject + " " + action + " " + a); +// System.out.println("KKKKKKK:" + res + " " + props.getProperty(a)); + if ((res instanceof JSONObject) && props.getProperty(a + ".replace") != null) { + JSONObject json = (JSONObject) res; + String[] aa = props.getProperty(a + ".replace").split(","); + transformJsonValues(json,aa[0],aa[1]); + } + } + + private void transformJsonValues(JSONObject json, String string1, String string2) { + for (Iterator<String> i = json.keys(); i.hasNext();) { + String key = (String) i.next(); + Object o = json.get(key); + if (o instanceof String) { + json.put(key, ((String) o).replace(string1,string2)); +// System.out.println("KKKKKKK:" + o + " " + json.get(key)); + } + if (o instanceof JSONObject) { + transformJsonValues((JSONObject) o,string1,string2); + } + if (o instanceof JSONArray) { + transformJsonValues((JSONArray) o,string1,string2); + } + } + } + + private void transformJsonValues(JSONArray a, String string1, String string2) { + for (int i = 0; i < a.length(); i++) { + Object o = a.get(i); + if (o instanceof JSONObject) { + transformJsonValues((JSONObject) o,string1,string2); + } + if (o instanceof JSONArray) { + transformJsonValues((JSONArray) o,string1,string2); + } + } + } + + private Logger findRequestLogger(String userName, String action, String resourcePath, JSONObject context) { + String logdir = getProps().getProperty("requestlog.dir", "logs"); + if (root instanceof AbstractManagementServer) { + AbstractManagementServer a = (AbstractManagementServer) root; + LoggerInfo i = a.getRequestLogger(userName, action, resourcePath, context); + return ManagementServerUtils.createLogger("requests-" + i.getName(), "INFO", "%d %5p %m%n", logdir); + } + return ManagementServerUtils.createLogger("requests-" + action, "INFO", "%d %5p %m%n", logdir); + } + + private void handleJsonReportResult(String reqId, long start, Object res, String status, Logger logger2) { + if (logger2.isInfoEnabled()) { + JSONObject r = new JSONObject(); + long duration = new Date().getTime() - start; + r.put("id", reqId); + r.put("duration", duration); + r.put("status", status); + if (res instanceof JSONObject) { + JSONObject j = (JSONObject) res; + r.put("res", j); + } + logger2.info(r.toString()); + } + } + + public void start() throws IOException { + if (directory != null) + root = load(directory); + if (root instanceof IPolicyEngine) { + pe = (IPolicyEngine) root; + } + startRecursively(root); + } + + public static void startRecursively(EObject o) { + for (EReference ref : o.eClass().getEAllContainments()) { + if (ref.isMany()) { + @SuppressWarnings("unchecked") + EList<EObject> l = (EList<EObject>) o.eGet(ref); + for (EObject o1 : l) { + startRecursively(o1); + } + } else { + EObject o1 = (EObject) o.eGet(ref); + if (o1 != null) + startRecursively(o1); + } + } + if (o instanceof ISiriusPlugin) { + ISiriusPlugin p = (ISiriusPlugin) o; + p.start(); + } + } + + public EFactory addFactory(EFactory f) { + if (f.getEPackage() == null) { + throw new RuntimeException("Null Package: " + f); + } + String s = f.getEPackage().getNsURI(); + if (!string2factory.containsKey(s)) { + string2factory.put(f.getEPackage().getNsURI(), f); + logger.info("added factory: " + s); + } + return string2factory.get(s); + } + + public void addRuntimeFactories(ISiriusServer server) { + addRuntimeFactories(server, "runtime.properties"); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public void addRuntimeFactories(ISiriusServer server, String runtimepropertyfile) { + String v = null; + try { + Properties p = PropertyUtil.getPropertiesFromClasspath(runtimepropertyfile); + for (Object k : p.keySet()) { + String kk = (String) k; + v = p.getProperty(kk).trim(); + if (kk.startsWith("factory.")) { + try { + Class c = Class.forName(v); + if (v.endsWith("PackageImpl")) { + Method m = c.getMethod("init"); + EPackage p1 = (EPackage) m.invoke(null); + addFactory(p1.getEFactoryInstance()); + } else { + Constructor constructor = c.getConstructor(new Class[] { ISiriusServer.class }); + addFactory((EFactory) constructor.newInstance(server)); + } + logger.info("added runtime factory: " + v); + } catch (NoSuchMethodException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InstantiationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalAccessException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalArgumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InvocationTargetException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (ClassNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + } catch (IOException e) { + logger.info("No runtime propertyFile " + runtimepropertyfile); + } + } + + private EObject load(String directory) throws IOException { + return loadObjectFromDirectory(eFactory, eClassName, directory, true); + } + + private EObject loadObjectFromDirectory(EFactory eFactory, String eClassName, String directory, boolean b) + throws IOException { + List<Ref> refs = new ArrayList<ManagementServer.Ref>(); + EObject res = loadObjectFromDirectory(eFactory, eClassName, directory, true, refs); + updateRefs(res, refs); + return res; + } + + private EObject loadObjectFromDirectory(EFactory f, String cName, String directory, boolean isRoot, List<Ref> refs) + throws IOException { + String jsonFile = directory + (isRoot ? "/ROOT.json" : ".json"); + JSONObject json; + try { + File file = new File(jsonFile); + if (file.exists()) + json = JsonUtils.file2json(jsonFile); + else + json = new JSONObject(); + } catch (JSONException e) { + // printStackTrace(e,); + throw new RuntimeException("Invalid JSON: " + jsonFile + " " + e); + } + EObject res; + try { + res = loadObjectFromJson(f, cName, directory, json, refs); + handleReference(res, json, refs); + handleTransientAttributes(res, "server"); + } catch (Exception e) { + printStackTrace(e); + throw new RuntimeException("Serialization issue: " + jsonFile, e); + } + return res; + } + + private HashMap<String, EFactory> string2factory = new HashMap<String, EFactory>(); + + private EObject loadObjectFromJson(EFactory f, String cName, String directory, JSONObject json, List<Ref> refs) + throws IOException { + f = addFactory(f); + HashSet<String> used = new HashSet<String>(); + if (json.has("$ecore")) { + used.add("$ecore"); + String pp = json.getJSONObject("$ecore").getString("ePackage"); + if (pp == null) + throw new RuntimeException("Package not found: " + json.toString(2)); + f = string2factory.get(pp); + cName = json.getJSONObject("$ecore").getString("eClass"); + if (f == null) + throw new RuntimeException("Factory not found: " + pp); + } + if (json.has("$class")) { + used.add("$class"); + String v = SomfVersionUpgrade(json.getString("$class")); + int i = v.lastIndexOf("."); + String pp = v.substring(0, i); + f = string2factory.get(pp); + cName = v.substring(i + 1); + if (f == null) { + throw new RuntimeException("Factory not found: " + pp); + } + } + if (f == null) { + throw new RuntimeException("Null Factory: " + json.toString(2)); + } + if (f.getEPackage() == null) { + throw new RuntimeException("Null Package: " + f + " " + json.toString(2)); + } + EClass c = (EClass) f.getEPackage().getEClassifier(cName); + if (c == null) { + logger.error("unable to create class: " + cName + " using factory " + f.getEPackage().getName() + " " + + json.toString(2)); + throw new RuntimeException("Unable to create class " + cName + " using factory " + + f.getEPackage().getName()); + } + EObject o = f.create(c); + // if (json.has("$class")) { + // System.err.println("creating object: " + directory + " " + f + " " + + // c); + // System.err.println(cName + " " + json); + // } + for (EAttribute attr : o.eClass().getEAllAttributes()) { + if (!json.has(attr.getName())) + continue; + if (o instanceof NamedEntity && attr.getName().equals("lastChanged") || o instanceof NamedEntity + && attr.getName().equals("created")) { + used.add(attr.getName()); + continue; + } + used.add(attr.getName()); + Object oJson = json.get(attr.getName()); + if (attr.isMany()) { + if (!(oJson instanceof JSONArray)) { + throw new RuntimeException("expect array of value: " + attr.getName()); + } + JSONArray aJson = (JSONArray) oJson; + @SuppressWarnings("unchecked") + EList<Object> l = (EList<Object>) o.eGet(attr); + for (int i = 0; i < aJson.length(); i++) { + l.add(jsonValue2attrValue(attr.getEAttributeType(), aJson.get(i))); + } + } else { + Object oo = null; + try { + if (attr.getEType().getName().endsWith("MetricAttribute")) { + // metric: use the metric APIs and need to be done after + // object is in the main tree. + } else { + oo = jsonValue2attrValue(attr.getEAttributeType(), oJson); + o.eSet(attr, oo); + } + } catch (Exception e) { + logger.error("Unable to set attr: eClass " + o.eClass().getName() + "@" + attr.getName() + " " + e); + System.err.println("Unable to set attr: eClass " + o.eClass().getName() + "@" + attr.getName() + + " " + attr.getEType().getName() + " " + e + " value=" + oJson + " class=" + + oJson.getClass() + " oo=" + oo + " class=" + (oo != null ? oo.getClass() : "")); + printStackTrace(e); + } + } + } + for (EReference ref : o.eClass().getEAllContainments()) { + if (json.has(ref.getName()) && !jsonHasVersion(json.get(ref.getName()))) { + // use JSON + used.add(ref.getName()); + Object oJson = json.get(ref.getName()); + if (ref.isMany()) { + @SuppressWarnings("unchecked") + EList<EObject> l = (EList<EObject>) o.eGet(ref); + EAttribute namingAttr = namingAttribute(ref); + if (oJson instanceof JSONObject) { + if (namingAttr != null) { + JSONObject ooJson = (JSONObject) oJson; + for (Iterator<String> i = ooJson.keys(); i.hasNext();) { + String k = i.next(); + if (k.startsWith("$")) continue; + if (ooJson.get(k) instanceof JSONArray) { + JSONArray a = (JSONArray) ooJson.get(k); + } + if (! (ooJson.get(k) instanceof JSONObject)) { + throw new RuntimeException("expect json of value: " + o.eClass().getName() + "@" + + ref.getName() + "." + k + " " + ooJson.get(k)); + } + JSONObject json2 = (JSONObject) ooJson.get(k); + json2.put(namingAttr.getName(), k); + String dir = directory + "/" + ref.getName(); + l.add(loadObjectFromJson(ref2factory(ref), ref.getEReferenceType().getName(), dir, + json2, refs)); + } + continue; + } + + } + if (!(oJson instanceof JSONArray)) { + throw new RuntimeException("expect object or array of value: " + ref.getName()); + } + JSONArray aJson = (JSONArray) oJson; + for (int i = 0; i < aJson.length(); i++) { + if (aJson.get(i) instanceof JSONObject) { + JSONObject json2 = (JSONObject) aJson.get(i); + if (namingAttr != null && ! json2.has(namingAttr.getName())) { + json2.put(namingAttr.getName(),Integer.toString(i)); + } + String dir = directory + "/" + ref.getName(); + l.add(loadObjectFromJson(ref2factory(ref), ref.getEReferenceType().getName(), dir, json2, + refs)); + } else + throw new RuntimeException("expect json of value: " + o.eClass().getName() + "@" + + ref.getName()); + } + } else { + if (oJson instanceof JSONObject) { + JSONObject json2 = (JSONObject) oJson; + String dir = directory + "/" + ref.getName(); + EObject o2 = loadObjectFromJson(ref2factory(ref), ref.getEReferenceType().getName(), dir, + json2, refs); + o.eSet(ref, o2); + } else if (oJson == null || oJson.getClass().getCanonicalName().equals("org.json.JSONObject.Null")) { + // null + } else + throw new RuntimeException("expect json of value: " + f.getEPackage().getName() + "." + cName + + " " + ref.getName() + " " + oJson.getClass().getCanonicalName()); + } + } else if (directory != null) { + // Look in Directory + if (ref.isMany()) { + @SuppressWarnings("unchecked") + EList<EObject> l = (EList<EObject>) o.eGet(ref); + File file = new File(directory + "/" + ref.getName()); + if (file.isDirectory()) { + EAttribute f1 = namingAttribute(ref); + File[] files = file.listFiles(); + if (files == null) { + logger.error("directory listing failed IO error??: " + file); + continue; + } + for (File file1 : sortFiles(directory, ref, files, json, used)) { + if (file1.getName().endsWith(".json")) { + String name = file1.getName().replace(".json", ""); + String dir2 = directory + "/" + ref.getName() + "/" + name; + EObject oo = loadObjectFromDirectory(ref2factory(ref), ref.getEType().getName(), dir2, + false, refs); + if (f1 != null) + oo.eSet(f1, name); + l.add(oo); + } + } + } + } else { + File file = new File(directory + "/" + ref.getName() + ".json"); + if (file.exists()) { + EObject oo = loadObjectFromDirectory(ref2factory(ref), ref.getEType().getName(), directory + + "/" + ref.getName(), false, refs); + o.eSet(ref, oo); + } + } + } + } + for (Iterator<String> i = json.keys(); i.hasNext();) { + String k = i.next(); + if (used.contains(k)) + continue; + Object o1 = json.get(k); + if (o1 instanceof JSONObject) { + JSONObject json1 = (JSONObject) o1; + if (json1.has("$ref")) + continue; + } + if (o1 instanceof JSONArray) { + JSONArray a1 = (JSONArray) o1; + if (a1.length() == 0) + continue; + Object o2 = a1.get(0); + if (o2 instanceof JSONObject) { + JSONObject json2 = (JSONObject) o2; + if (json2.has("$ref")) + continue; + } + } + if (k.equals("$nosave")) + continue; + logger.warn("JSON value not used: " + k + " " + f.getEPackage().getName() + "." + cName + " " + json.get(k)); + } + return o; + } + + private String SomfVersionUpgrade(String className) { + if (className.equals("org.openecomp.ncomp.sirius.manager.model.StringMetric")) + return "org.openecomp.ncomp.core.metrics.StringMetric"; + if (className.equals("org.openecomp.ncomp.sirius.manager.model.DoubleMetric")) + return "org.openecomp.ncomp.core.metrics.DoubleMetric"; + if (className.equals("org.openecomp.ncomp.sirius.manager.model.LongMetric")) + return "org.openecomp.ncomp.core.metrics.LongMetric"; + if (className.equals("org.openecomp.ncomp.sirius.manager.model.ModuleProperty")) + return "org.openecomp.ncomp.sirius.manager.properties.ModuleProperty"; + return className; + } + + private List<File> sortFiles(String dir, EReference ref, File[] files, JSONObject json, HashSet<String> used) { + // boolean debug = dir.contains("metricOptions"); + List<File> res = new ArrayList<File>(); + Arrays.sort(files); + for (File f : files) { + if (f.getName().endsWith(".json")) + res.add(f); + } + // if (debug) System.err.println("HERE: " + json.toString(2)); + if (ref.isOrdered() && json.has("$order:" + ref.getName())) { + used.add("$order:" + ref.getName()); + try { + JSONArray a = json.getJSONArray("$order:" + ref.getName()); + List<File> files1 = new ArrayList<File>(); + HashMap<String, File> m = new HashMap<String, File>(); + for (File f : res) { + m.put(f.getName(), f); + } + for (int i = 0; i < a.length(); i++) { + String n = a.getString(i) + ".json"; + if (m.containsKey(n)) { + files1.add(m.remove(n)); + // if (debug) System.err.println("HERE: added1 " + + // files1.get(files1.size()-1)); + } else { + logger.warn("files does not contain key:" + n + " in " + dir); + } + } + for (String n : SortUtil.sort(m.keySet())) { + files1.add(m.get(n)); + // if (debug) System.err.println("HERE: added2 " + + // files1.get(files1.size()-1)); + logger.warn("order does not contain key:" + n + " in " + dir); + } + return files1; + } catch (Exception e) { + ManagementServerUtils.printStackTrace(e); + return res; + } + } else { + return res; + } + } + + private HashMap<String, Properties> name2properties = new HashMap<String, Properties>(); + + private void handleTransientAttributes(EObject o, String path) { + for (EAttribute attr : o.eClass().getEAllAttributes()) { + if (!attr.isTransient()) + continue; + EAnnotation anno = attr.getEAnnotation(PERSIST); + if (anno == null) + continue; + if (attr.isMany()) { + logger.warn("property persistence for list attributes not current supported: " + attr2name(attr)); + continue; + } + String propertyFile = anno.getDetails().get("propertyFile"); + if (propertyFile == null) { + logger.warn("Missing persistence detail propertyFile: " + attr2name(attr)); + continue; + } + Properties p; + if (name2properties.get(propertyFile) == null) { + p = new Properties(); + try { + p = PropertyUtil.getPropertiesFromClasspath(propertyFile); + } catch (IOException e) { + logger.warn("Missing persistence propertyFile: " + propertyFile + " " + e); + } + name2properties.put(propertyFile, p); + } + p = name2properties.get(propertyFile); + String path1 = path + "." + attr.getName(); + String s = p.getProperty(path1); + if (s == null) { + logger.warn("unable to determine value for: " + attr2name(attr) + " path: " + path1 + " file: " + + propertyFile); + } + o.eSet(attr, stringValue2attrValue(attr.getEAttributeType(), s)); + } + for (EReference ref : o.eClass().getEAllContainments()) { + if (ref.isMany()) { + @SuppressWarnings("unchecked") + EList<EObject> l = (EList<EObject>) o.eGet(ref); + for (EObject oo : l) { + EStructuralFeature f = oo.eClass().getEStructuralFeature("name"); + if (f instanceof EAttribute) { + EAttribute attr = (EAttribute) f; + Object nn = oo.eGet(attr); + if (!(nn instanceof String)) + continue; + String path1 = path + "." + ref.getName() + "." + nn; + handleTransientAttributes(oo, path1); + } + } + } else { + String path1 = path + "." + ref.getName(); + EObject oo = (EObject) o.eGet(ref); + if (oo != null) + handleTransientAttributes(oo, path1); + } + } + } + + private String attr2name(EAttribute attr) { + StringBuffer b = new StringBuffer(); + b.append(attr.getEContainingClass().getEPackage().getName()); + b.append("::"); + b.append(attr.getEContainingClass().getName()); + b.append("::"); + b.append(attr.getName()); + return b.toString(); + } + + private String ref2name(EReference ref) { + StringBuffer b = new StringBuffer(); + b.append(ref.getEContainingClass().getEPackage().getName()); + b.append("::"); + b.append(ref.getEContainingClass().getName()); + b.append("::"); + b.append(ref.getName()); + return b.toString(); + } + + int j = 0; + public boolean saveOnCreate = true; + + private EFactory ref2factory(EReference ref) { + return ref.getEReferenceType().getEPackage().getEFactoryInstance(); + } + + private EObject loadObjectFromJson(EFactory f, String cName, JSONObject json, List<Ref> refs) { + try { + return loadObjectFromJson(f, cName, null, json, refs); + } catch (IOException e) { + printStackTrace(e); + } + return null; + } + + static int id = 0; + + public Properties getProps() { + return props; + } + + private EReference findRefByName(EObject o, String name) { + return (EReference) o.eClass().getEStructuralFeature(name); + } + + @SuppressWarnings("unused") + private EAttribute findAttrByName(EObject o, String name) { + return (EAttribute) o.eClass().getEStructuralFeature(name); + } + + public Subject find(String resourcePath) { + return find(root, resourcePath); + } + + static public Subject find(EObject o, String resourcePath) { + return find(o, resourcePath, false); + } + + static public Subject find(EObject o, String resourcePath, boolean allowPartial) { + if (resourcePath.equals("/")) + return new Subject(o); + if (resourcePath.startsWith("../..")) + return (o.eContainer() == null) ? null : find(o.eContainer(), resourcePath.substring(3), allowPartial); + if (resourcePath.startsWith("../")) + return (o.eContainer() == null) ? null : find(o.eContainer(), resourcePath.substring(2), allowPartial); + return find(o, resourcePath.split("/"), 1, allowPartial); + } + + static private Subject find(EObject o, String[] l, int i, boolean allowPartial) { + if (o == null) + return null; + if (i == l.length) + return new Subject(o); + EStructuralFeature f = o.eClass().getEStructuralFeature(l[i]); + if (f instanceof EReference) { + EReference ref = (EReference) f; + if (ref.isMany()) { + if (i + 1 == l.length) + return new Subject(o, ref); + @SuppressWarnings("unchecked") + EList<EObject> ll = (EList<EObject>) o.eGet(ref); + for (EObject oo : ll) { + String s = ecoreId(oo); + if (s != null && s.equals(l[i + 1])) + return find(oo, l, i + 2, allowPartial); + } + if (allowPartial) + return new Subject(o, ref); + } else { + EObject oo = (EObject) o.eGet(ref); + if (oo == null && allowPartial) + return new Subject(o, ref); + return find(oo, l, i + 1, allowPartial); + } + } + if (f instanceof EAttribute && i + 1 == l.length) { + return new Subject(o, (EAttribute) f); + } + if (allowPartial) + return new Subject(o); + return null; + } + + public List<EObject> findAll(String resourcePath) { + return findAll(root, resourcePath); + } + + static public List<EObject> findAll(EObject o, String resourcePath) { + List<EObject> res = new ArrayList<EObject>(); + if (resourcePath.equals("/") || resourcePath.equals("")) { + res.add(o); + } else { + findAll(o, resourcePath.split("/"), resourcePath.startsWith("/") ? 1 : 0, res); + } + return res; + } + + static private void findAll(EObject o, String[] l, int i, List<EObject> res) { + if (o == null) + return; + if (i == l.length) { + res.add(o); + return; + } + EStructuralFeature f = o.eClass().getEStructuralFeature(l[i]); + if (f instanceof EReference) { + EReference ref = (EReference) f; + if (ref.isMany()) { + if (i + 1 == l.length) + return; + @SuppressWarnings("unchecked") + EList<EObject> ll = (EList<EObject>) o.eGet(ref); + for (EObject oo : ll) { + String s = ecoreId(oo); + if (s != null && s.matches(l[i + 1])) + findAll(oo, l, i + 2, res); + } + } else { + findAll((EObject) o.eGet(ref), l, i + 1, res); + } + } + } + + public static EList<Subject> findReferences(EObject root, EObject o, boolean recursive) { + EList<Subject> res = new BasicEList<Subject>(); + if (recursive) { + for (EObject o1 : object2containedObjects(o)) { + // System.err.println(object2ref(root) + " " + object2ref(o1)); + findReferences(root, o1, res); + } + } else + findReferences(root, o, res); + return res; + } + + private static void findReferences(EObject oo, EObject o, EList<Subject> res) { + if (oo == o) + return; + // if (object2ref(oo).startsWith("/con")) + // System.err.println("XYZZZ: " + object2ref(oo) + " " + object2ref(o)); + for (EReference ref : oo.eClass().getEAllReferences()) { + if (ref.isContainment()) { + for (EObject o1 : ref2objects(oo, ref)) { + findReferences(o1, o, res); + } + } else { + for (EObject o1 : ref2objects(oo, ref)) { + if (o1 == o) { + res.add(new Subject(oo, ref)); + } + } + } + } + + } + + @SuppressWarnings("unchecked") + private static EList<EObject> ref2objects(EObject o, EReference ref) { + EList<EObject> res = new BasicEList<EObject>(); + Object x = o.eGet(ref); + if (ref.isMany()) { + // Try 3 times to create list. + boolean done = false; + for (int i = 0; i < 3; i++) { + try { + res.clear(); + res.addAll((EList<EObject>) x); + done = true; + break; + } catch (ConcurrentModificationException e) { + if (i == 2) { + logger.error("Failing to create object list: " + object2ref(o) + " @ " + ref.getName(), e); + } + continue; + } + } + if (!done) { + System.err.println("unable to create object list: " + object2ref(o) + "@" + ref.getName()); + + logger.error("unable to create object list: " + object2ref(o) + "@" + ref.getName()); + } + } else { + if (x != null) + res.add((EObject) x); + } + return res; + } + + public static EList<EObject> object2containedObjects(EObject o) { + EList<EObject> res = new BasicEList<EObject>(); + object2containedObjects(o, res); + return res; + } + + private static void object2containedObjects(EObject o, EList<EObject> res) { + res.add(o); + for (EReference ref : o.eClass().getEAllReferences()) { + if (ref.isContainment()) { + for (EObject o2 : ref2objects(o, ref)) { + object2containedObjects(o2, res); + } + } + } + } + + private Object create(Subject subject, JSONObject json, boolean save) { + EObject o = subject.o; + EReference ref = subject.ref; + if (ref == null) + throw new RuntimeException("Need ref name"); + List<Ref> refs = new ArrayList<ManagementServer.Ref>(); + EObject oo = loadObjectFromJson(ref2factory(ref), ref.getEReferenceType().getName(), json, refs); + handleReference(oo, json, refs); + updateRefs(root, refs); + if (ref.isMany()) { + @SuppressWarnings("unchecked") + EList<EObject> ll = (EList<EObject>) o.eGet(ref); + ll.add(oo); + } else { + if (o.eGet(ref) != null) + throw new RuntimeException("Cannot create: object already exists"); + o.eSet(ref, oo); + } + String path = "server" + object2ref(oo); + handleTransientAttributes(oo, path.replace("/", ".")); + setCreated(oo); + if (save) { + save(); + } else { + if (logger.isDebugEnabled()) + logger.debug("create not saved: " + object2ref(oo)); + } + if (oo instanceof ISiriusPlugin) { + ISiriusPlugin oo2 = (ISiriusPlugin) oo; + oo2.start(); + } + return null; + } + + public EObject json2ecore(EClass eClass, JSONObject json) { + return json2ecore(eClass, json, true); + } + + public EObject json2ecore(EClass eClass, JSONObject json, boolean refRelativeToRoot) { + List<Ref> refs = new ArrayList<ManagementServer.Ref>(); + EObject oo = loadObjectFromJson(eClass.getEPackage().getEFactoryInstance(), eClass.getName(), json, refs); + handleReference(oo, json, refs); + updateRefs(refRelativeToRoot ? root : oo, refs); + return oo; + } + + public EObject findAndCreate(EObject o, String path) { + Subject s = findAndCreateSubject(o, path); + if (s.ref == null) + return s.o; + return (EObject) o.eGet(s.ref); + } + + public Subject findAndCreateSubject(EObject o, String path) { + Subject s = find(o, path); + if (s != null && s.o != null) { + return s; + } + int index = path.lastIndexOf("/"); + String id = path.substring(index + 1, path.length()); + if (id.length() == 0) { + throw new RuntimeException("empty string ID: " + object2ref(o) + " " + path); + } + String path1 = path.substring(0, index); + Subject s1 = findAndCreateSubject(o, path1); + if (s1 == null || s1.o == null) { + throw new RuntimeException("unable to find resource: " + object2ref(o) + " " + path); + } + s = find(o, path); + if (s == null) { + JSONObject json = new JSONObject(); + json.put("$nosave", true); // TODO + if (s1.ref != null && s1.ref.isMany()) { + json.put("name", id); + } + if (s1.ref == null) { + s1.ref = findRefByName(s1.o, id); + } + // System.err.println("PP creating: " + object2ref(o) + " " + path); + // Thread.dumpStack(); + create(s1, json, true); + return find(o, path); + } else + return s; + } + + public Object update(String userName, Subject subject, JSONObject json, boolean useNulls) { + EObject o = subject.o; + EReference ref = subject.ref; + if (json == null) + throw new RuntimeException("Need object to update"); + if (o == null || ref != null) + throw new RuntimeException("Need object to update"); + List<Ref> refs = new ArrayList<ManagementServer.Ref>(); + EObject oo = loadObjectFromJson(o.eClass().getEPackage().getEFactoryInstance(), o.eClass().getName(), json, + refs); + handleReference(oo, json, refs); + List<EObject> deleted = new ArrayList<EObject>(); + merge(o, oo, useNulls ? null : json, json.has("$updateEnumWithDefault"), deleted); + for (EObject o1 : deleted) { + if (!json.has("$forcedUpdate")) + checkIfDeleteIsAllowed(o1); + if (!pe.permit(userName, "DELETE", object2ref(o1))) { + throw new RuntimeException("Update Action results in DELETE not permitted: " + userName + " " + + object2ref(o1)); + } + } + if (deleted.size() > 0) + logger.warn("update deletes: " + objects2ref(deleted)); + updateRefs(root, refs); + merge(o, oo, useNulls ? null : json, json.has("$updateEnumWithDefault"), null); + updateMetricValues(o, json); + if (saveOnCreate && !json.has("$nosave")) + save(); + return null; + } + + private void updateMetricValues(EObject o, JSONObject json) { + // String xx = json == null ? "NULL" : json.toString(2); + // System.err.println("HERE: " + object2ref(o) + " " + (xx.length() > + // 1000 ? xx.subSequence(0, 500)+"...." : xx)); + if (json == null) + return; + NamedEntity o1 = (o instanceof NamedEntity) ? (NamedEntity) o : null; + boolean changed = false; + for (EAttribute attr : o.eClass().getEAllAttributes()) { + if (!attr.getEType().getName().endsWith("MetricAttribute")) + continue; + if (!json.has(attr.getName())) + continue; + metrics.updateMetric(o, attr, json.get(attr.getName())); + changed = true; + } + // handle containment references + for (EReference ref : o.eClass().getEAllReferences()) { + if (!ref.isContainment()) + continue; + Object o2 = o.eGet(ref); + if (o2 == null) + continue; + if (ref.isMany()) { + @SuppressWarnings("unchecked") + EList<EObject> l = (EList<EObject>) o2; + for (EObject o3 : l) { + if (o3 instanceof NamedEntity) + updateMetricValues(o3, findJsonInNamedList(o3, findJsonWithName(json, ref.getName()))); + } + } else { + EObject o3 = (EObject) o2; + updateMetricValues(o3, findJsonWithName(json, ref.getName())); + } + } + if (changed && o1 != null) + o1.setLastChanged(new Date()); + } + + public static void merge(EObject o, EObject oo, JSONObject json, boolean updateEnumWithDefault, + List<EObject> deleted) { + boolean makeChange = deleted == null; + NamedEntity o1 = (o instanceof NamedEntity) ? (NamedEntity) o : null; + boolean changed = false; + if (json != null && json.has("$useNull")) + json = null; + for (EAttribute attr : oo.eClass().getEAllAttributes()) { + if (!makeChange) + continue; // TODO verify errors + EStructuralFeature f = o.eClass().getEStructuralFeature(attr.getName()); + if (!(f instanceof EAttribute)) + continue; + EAttribute attr1 = (EAttribute) f; + if (attr.getEType() != attr1.getEType()) + continue; + if (attr.getName().equals("name")) + continue; // for now. do not merge name. + Object o2 = oo.eGet(attr); + if (json != null && !json.has(attr.getName())) + continue; + // TODO handle EEnums better. If o2 is the default value do not + // update + if (!updateEnumWithDefault && attr1.getEType() instanceof EEnum) { + EEnum enum1 = (EEnum) attr1.getEType(); + if (enum1.getDefaultValue() == o2) + continue; + } + Object o3 = o.eGet(attr1); + if (!objectEquals(o2, o3)) { + o.eSet(attr1, o2); + if (o1 != null) + changed = true; + } + } + // handle non-containment references + for (EReference ref : oo.eClass().getEAllReferences()) { + if (!makeChange) + continue; // TODO verify errors + if (ref.isContainment() || ref.isContainer()) + continue; + EStructuralFeature f = o.eClass().getEStructuralFeature(ref.getName()); + if (!(f instanceof EReference)) + continue; + EReference ref1 = (EReference) f; + if (ref.getEType() != ref1.getEType()) { + logger.warn("merge cannot handle different type: " + ref.getEType() + " " + ref1.getEType()); + continue; + } + Object o2 = oo.eGet(ref); + if (json != null && !json.has(ref.getName())) + continue; + if (ref.isMany() && json != null && !json.has(ref.getName())) { + @SuppressWarnings("unchecked") + EList<EObject> l = (EList<EObject>) o2; + if (l.size() == 0) + continue; + } + Object o3 = o.eGet(ref1); + if (!objectEquals(o2, o3)) { + o.eSet(ref1, o2); + if (o1 != null) + changed = true; + } + } + // handle containment references + for (EReference ref : oo.eClass().getEAllReferences()) { + if (!ref.isContainment()) + continue; + EStructuralFeature f = o.eClass().getEStructuralFeature(ref.getName()); + if (!(f instanceof EReference)) + continue; + EReference ref1 = (EReference) f; + if (ref.getEType() != ref1.getEType()) { + logger.warn("merge containment cannot handle different type: " + ref.getEType() + " " + ref1.getEType()); + throw new RuntimeException("merge containment cannot handle different type: " + ref.getEType() + " " + + ref1.getEType()); + } + Object o2 = oo.eGet(ref); + if (json != null && !json.has(ref.getName())) + continue; + if (ref.isMany() && json != null && !json.has(ref.getName())) { + @SuppressWarnings("unchecked") + EList<EObject> l = (EList<EObject>) o2; + if (l.size() == 0) + continue; + } + Object o3 = o.eGet(ref1); + if (ref.isMany()) { + @SuppressWarnings("unchecked") + EList<EObject> l2 = (EList<EObject>) o2; + @SuppressWarnings("unchecked") + EList<EObject> l3 = (EList<EObject>) o3; + EList<EObject> l4 = new BasicEList<EObject>(); + if (l2.size() != l3.size()) + changed = true; + for (EObject oo2 : l2) { + EObject oo3 = findInNamedList(l3, oo2); + if (oo3 != null) + merge(oo3, oo2, findJsonInNamedList(oo3, findJsonWithName(json, ref.getName())), + updateEnumWithDefault, deleted); + else { + if (makeChange) { + oo3 = EcoreUtil.copy(oo2); + setCreated(oo3); + changed = true; + } + } + l4.add(oo3); + } + for (EObject oo3 : l3) { + // System.err.println("XXYYZZ: " + objects2ref(l4) + " " + + // object2ref(oo3) + " " + + // objects2ref(l4).contains(object2ref(oo3)) + " " + + // l4.contains(oo3)); + if (l4.contains(oo3)) + continue; + // oo3 deleted + if (makeChange) + changed = true; + else + deleted.add(oo3); + } + if (makeChange) { + l3.clear(); + l3.addAll(l4); + } + } else { + if (o3 == null && o2 == null) + continue; + if (o3 == null && o2 != null) { + if (makeChange) { + EObject o4 = EcoreUtil.copy((EObject) o2); + if (o2.getClass() != o4.getClass()) { + // TODO issue when o2 is a SOMF provided object. The + // Type of o4 is not done right. + System.err.println("Object copy does not preserve class: " + o2.getClass() + " -> " + + o4.getClass()); + } + setCreated(o4); + o.eSet(ref1, o4); + changed = true; + } + continue; + } + if (o3 != null && o2 == null) { + if (makeChange) { + o.eSet(ref1, null); + changed = true; + } else + deleted.add((EObject) o3); + continue; + } + merge((EObject) o3, (EObject) o2, findJsonWithName(json, ref.getName()), updateEnumWithDefault, deleted); + } + } + if (changed && o1 != null) + o1.setLastChanged(new Date()); + } + + private static void setCreated(EObject o) { + if (o == null) + return; + if (o instanceof NamedEntity) { + NamedEntity n = (NamedEntity) o; + n.setCreated(new Date()); + } + // handle containment references + for (EReference ref : o.eClass().getEAllReferences()) { + if (!ref.isContainment()) + continue; + Object o1 = o.eGet(ref); + if (ref.isMany()) { + @SuppressWarnings("unchecked") + EList<EObject> l = (EList<EObject>) o1; + for (EObject o2 : l) + setCreated(o2); + } else + setCreated((EObject) o1); + } + } + + private static JSONObject findJsonWithName(JSONObject json, String name) { + return (json != null && json.has(name)) ? json.getJSONObject(name) : null; + } + + private static JSONObject findJsonInNamedList(EObject o, Object json) { + if (o instanceof NamedEntity) { + NamedEntity o1 = (NamedEntity) o; + if (json instanceof JSONObject) { + JSONObject json1 = (JSONObject) json; + if (json1.has(o1.getName())) { + return json1.getJSONObject(o1.getName()); + } + } + } + return null; + } + + public static EObject findInNamedList(EList<? extends EObject> l, String name) { + if (name == null) + return null; + for (EObject o2 : l) { + NamedEntity n2 = (o2 instanceof NamedEntity) ? (NamedEntity) o2 : null; + if (n2 != null && name.equals(n2.getName())) + return o2; + } + return null; + } + + private static EObject findInNamedList(EList<EObject> l, EObject o) { + if (o instanceof NamedEntity) + return findInNamedList(l, ((NamedEntity) o).getName()); + return null; + } + + private static boolean objectEquals(Object o1, Object o2) { + if (o1 == null && o2 == null) + return true; + if (o1 != null && o2 == null) + return false; + if (o2 == null && o1 != null) + return false; + return o2.equals(o1); + } + + private Object delete(Subject subject) { + if (subject == null || subject.o == null) + throw new RuntimeException("Object does not exists"); + if (subject.ref != null) { + for (EObject o : ref2objects(subject.o, subject.ref)) { + checkIfDeleteIsAllowed(o); + } + if (subject.ref.isMany()) { + @SuppressWarnings("unchecked") + EList<EObject> ll = (EList<EObject>) subject.o.eGet(subject.ref); + ll.clear(); + } else { + subject.o.eSet(subject.ref, null); + } + return null; + } + if (subject.o.eContainmentFeature() == null) + throw new RuntimeException("Cannot delete root object"); + checkIfDeleteIsAllowed(subject.o); + if (subject.o.eContainmentFeature() instanceof EReference) { + EReference ref = subject.o.eContainmentFeature(); + if (ref.isMany()) { + @SuppressWarnings("unchecked") + EList<EObject> ll = (EList<EObject>) subject.o.eContainer().eGet(ref); + ll.remove(subject.o); + } else { + subject.o.eContainer().eSet(ref, null); + } + } + if (saveOnCreate) + save(); + return null; + } + + private void checkIfDeleteIsAllowed(EObject o) { + // System.err.println("checkIfDeleteIsAllowed: " + o + " size=" + + // findReferences(root, o, true).size()); + if (findReferences(root, o, true).size() > 0) { + throw new RuntimeException("Unable to delete object (references exists): " + object2ref(o)); + } + } + + private Object list(Subject subject, int levels) { + if (subject == null) { + return null; + } + if (subject.ref == null) { + return ecore2json(subject.o, levels, null, true); + } + + // isMany ref need to return a list of IDs + JSONObject json = new JSONObject(); + json.put(subject.ref.getName(), ecorelist2jsonArray(subject.o, subject.ref)); + return json; + } + + private static Object ecorelist2jsonArray(EObject o, EReference ref) { + JSONArray a = new JSONArray(); + @SuppressWarnings("unchecked") + EList<EObject> ll = (EList<EObject>) o.eGet(ref); + for (EObject oo : ll) { + a.put(ecoreId(oo)); + } + return a; + } + + private static Object ecorelist2jsonNodeArray(EObject o, EReference ref) { + JSONObject json = new JSONObject(); + JSONArray a = new JSONArray(); + json.put("$children", a); + json.put("$ordered", ref.isOrdered()); + @SuppressWarnings("unchecked") + EList<EObject> ll = (EList<EObject>) o.eGet(ref); + for (EObject oo : ll) { + a.put(ecoreId(oo)); + } + return json; + } + + private static Object ecore2jsonNode(EObject o, EReference ref) { + JSONObject json = new JSONObject(); + json.put("$isNull", o == null); + json.put("$child", ref.getName()); + json.put("$required", ref.isRequired()); + return json; + } + + private static JSONArray list2jsonArray(List<EObject> ll) { + JSONArray a = new JSONArray(); + for (EObject oo : ll) { + a.put(object2ref(oo)); + } + return a; + } + + private static JSONArray subjectList2jsonArray(List<Subject> ll) { + JSONArray a = new JSONArray(); + for (Subject subject : ll) { + JSONObject o = new JSONObject(); + o.put("path", object2ref(subject.o)); + o.put("ref", subject.ref.getName()); + a.put(o); + } + return a; + } + + public static JSONObject ecore2json(EObject o, int levels, EClass defaultClass, boolean showTransient) { + return ecore2json(o, levels, defaultClass, showTransient, false, true); + } + + public static JSONObject ecore2json(EObject o, int levels, EClass defaultClass, boolean showTransient, + boolean showNaming, boolean showEmptyLists) { + JSONObject json = new JSONObject(); + if (defaultClass == null && o.eContainer() != null) + defaultClass = (EClass) o.eContainingFeature().getEType(); + if (levels == -2000) { + json.put("$name", o.eContainer() == null ? "/" : object2ref(o)); + json.put("$class", o.eClass().getEPackage().getNsURI() + "." + o.eClass().getName()); + json.put("$time", new Date().getTime()); + json.put("$version", "1.10.0"); + } else if (o.eClass() != defaultClass) { + // object class id not default class + json.put("$class", o.eClass().getEPackage().getNsURI() + "." + o.eClass().getName()); + } + // json.put("$implClass", o.getClass().getName()); + EAttribute namingAttr = namingAttribute(o.eContainmentFeature()); + for (EAttribute attr : o.eClass().getEAllAttributes()) { + if (!showTransient && attr.isTransient()) + continue; + if (attr.getEAnnotation(PERSIST) != null) + continue; + if (!showNaming && attr == namingAttr) + continue; + // if (o instanceof NamedEntity && + // attr.getName().equals("lastChanged")) + // continue; + // if (o instanceof NamedEntity && attr.getName().equals("created")) + // continue; + if (attr.isMany()) { + if (attr.getEType().getInstanceTypeName().equals("org.eclipse.emf.ecore.util.FeatureMap$Entry")) + continue; + JSONArray a = new JSONArray(); + json.put(attr.getName(), a); + @SuppressWarnings("unchecked") + EList<Object> l = (EList<Object>) o.eGet(attr); + if (l == null) { + logger.warn("attribute list returned null: " + object2ref(o) + " " + attr.getName()); + continue; + } + for (Object oo : l) { + a.put(attr2jsonValue(levels, oo, attr.getEType())); + } + } else { + // System.out.println("HERE 99: " + o + " " + attr + " " + + // o.eGet(attr)); + json.put(attr.getName(), attr2jsonValue(levels, o.eGet(attr), attr.getEType())); + } + } + for (EReference ref : o.eClass().getEAllReferences()) { + if (ref.isContainment() || ref.isContainer()) + continue; + if (ref.isMany()) { + @SuppressWarnings("unchecked") + EList<EObject> l = (EList<EObject>) o.eGet(ref); + JSONArray a = new JSONArray(); + for (EObject oo : l) { + JSONObject json1 = new JSONObject(); + json1.put("$ref", oo == null ? "NULL" : object2ref(oo)); + a.put(json1); + } + json.put(ref.getName(), a); + } else { + EObject oo = (EObject) o.eGet(ref); + if (oo == null) + continue; + JSONObject json1 = new JSONObject(); + json1.put("$ref", object2ref(oo)); + json.put(ref.getName(), json1); + } + } + for (EReference ref : o.eClass().getEAllContainments()) { + if (ref.isMany()) { + if (levels == 0) { + json.put(ref.getName(), ecorelist2jsonArray(o, ref)); + continue; + } + if (levels < -1000) { + json.put(ref.getName(), ecorelist2jsonNodeArray(o, ref)); + continue; + } + if (levels < 0) + continue; + @SuppressWarnings("unchecked") + EList<EObject> l = (EList<EObject>) o.eGet(ref); + if (!showEmptyLists && l.size() == 0) + continue; + EAttribute f = namingAttribute(ref); + if (f != null) { + JSONObject json1 = new JSONObject(); + json.put(ref.getName(), json1); + for (EObject oo : l) { + String nn; + if (oo.eGet(f) instanceof EDataTypeEList) { + @SuppressWarnings("rawtypes") + EDataTypeEList xx = (EDataTypeEList) oo.eGet(f); + nn = xx.toString(); + System.err.println(oo.eClass().getName() + " " + f.getName() + " " + xx); + continue; + } else + nn = (String) oo.eGet(f); + if (nn == null) { + logger.warn("name is null " + oo + " " + f); + continue; + } + if (json1.has(nn)) { + System.err.println("name is already used " + nn + " " + object2ref(o) + "@" + f.getName()); + continue; + } + json1.put( + nn, + ecore2json(oo, levels - 1, ref.getEReferenceType(), showTransient, showNaming, + showEmptyLists)); + } + } else { + JSONArray a = new JSONArray(); + json.put(ref.getName(), a); + for (EObject oo : l) { + a.put(ecore2json(oo, levels - 1, ref.getEReferenceType(), showTransient)); + } + } + } else { + EObject oo = (EObject) o.eGet(ref); + if (oo != null || levels < -1) { + if (levels == 0) + json.put(ref.getName(), new JSONObject()); + else if (levels < -1000) + json.put(ref.getName(), ecore2jsonNode(oo, ref)); + else if (levels > 0) + json.put( + ref.getName(), + ecore2json(oo, levels - 1, ref.getEReferenceType(), showTransient, showNaming, + showEmptyLists)); + } + + } + } + return json; + } + + private static EAttribute namingAttribute(EReference ref) { + if (ref == null || !ref.isMany()) + return null; + EStructuralFeature f = ref.getEReferenceType().getEStructuralFeature("name"); + if (f instanceof EAttribute) { + EAttribute ff = (EAttribute) f; + if (ff.getEType().getInstanceClass().getName().equals("java.lang.String")) { + return ff; + } + } + return null; + } + + public static String object2ref(EObject oo) { + if (oo.eContainer() == null) { + return ""; + } + if (!(oo.eContainingFeature() instanceof EReference)) { + System.err.println("XXXX: oo=" + oo + " fea=" + oo.eContainingFeature()); + throw new RuntimeException("eContainingFeature not an reference: " + oo); + } + EReference ref = (EReference) oo.eContainingFeature(); + StringBuffer b = new StringBuffer(); + b.append(object2ref(oo.eContainer())); + b.append("/"); + b.append(ref.getName()); + if (ref.isMany()) { + b.append("/"); + b.append(ecoreId(oo)); + } + return b.toString(); + } + + public static List<String> objects2ref(Collection<EObject> l) { + List<String> res = new ArrayList<String>(); + for (EObject o : l) { + res.add(object2ref(o)); + } + return res; + } + + public static String relativeObject2ref(EObject o1, EObject oo) { + if (o1 == oo) + return ""; + if (oo.eContainer() == null) { + return null; + } + EReference ref = (EReference) oo.eContainingFeature(); + StringBuffer b = new StringBuffer(); + b.append(relativeObject2ref(o1, oo.eContainer())); + b.append("/"); + b.append(ref.getName()); + if (ref.isMany()) { + b.append("/"); + b.append(ecoreId(oo)); + } + return b.toString(); + } + + @SuppressWarnings({ "rawtypes" }) + private Object operation(Subject subject, String action, JSONObject json, JSONObject context) { + EObject o = subject.o; + EClass eClass = o.eClass(); + EOperation op = null; + for (EOperation op1 : eClass.getEAllOperations()) { + if (op1.getName().equals(action)) { + op = op1; + break; + } + } + if (op == null) + throw new RuntimeException("No such operation:" + action); + try { + List<Class> argTypes = new ArrayList<Class>(); + List<Object> args = new ArrayList<Object>(); + for (EParameter p : op.getEParameters()) { + if (p.getEType().getName().equals("RemoteContext")) { + // special case for getting context information (e.g. remote + // IP) to operations. + if (json.has(p.getName())) + context.put("remote", json.get(p.getName())); + args.add(context); + argTypes.add(JSONObject.class); + continue; + } + if (!json.has(p.getName())) { + logger.warn("Operation " + PropertyUtil.replaceForLogForcingProtection(action) + " has missing parameter:" + p.getName()); + } + Object oo = null; + if (p.isMany()) { + EList<Object> l = new BasicEList<Object>(); + oo = l; + if (json.has(p.getName())) { + Object o2 = json.get(p.getName()); + if (!(o2 instanceof JSONArray)) { + throw new RuntimeException("parameter need to be a Json array:" + p.getName()); + } + JSONArray a = (JSONArray) o2; + for (int i = 0; i < a.length(); i++) { + Object o3 = a.get(i); + if (p.getEType() instanceof EClass) { + EClass eClass1 = (EClass) p.getEType(); + if (!(o3 instanceof JSONObject)) + throw new RuntimeException("parameter need to be a Json object:" + p.getName()); + EObject ooo = parameterObjectFromJson(eClass1, (JSONObject) o3); + l.add(ooo); + } + if (p.getEType() instanceof EDataType) { + l.add(jsonValue2attrValue((EDataType) p.getEType(), o3)); + } + } + } + args.add(oo); + argTypes.add(EList.class); + } else { + if (json.has(p.getName())) { + Object o2 = json.get(p.getName()); + if (p.getEType() instanceof EClass) { + EClass eClass1 = (EClass) p.getEType(); + if (!(o2 instanceof JSONObject)) + throw new RuntimeException("parameter need to be a Json object:" + p.getName()); + EObject ooo = parameterObjectFromJson(eClass1, (JSONObject) o2); + oo = ooo; + } + if (p.getEType() instanceof EDataType) { + EDataType eType = (EDataType) p.getEType(); + oo = jsonValue2attrValue(eType, o2); + } + + } + args.add(oo); + argTypes.add(p.getEType().getInstanceClass()); + } + } + Class<? extends EObject> c = subject.o.getClass(); + Method m = c.getMethod(action, argTypes.toArray(new Class[argTypes.size()])); + // System.err.println("YYYY: " + o + " " + subject + " " + action + + // " " + m + " " + argTypes); + Object oo = m.invoke(o, args.toArray(new Object[args.size()])); + JSONObject res = new JSONObject(); + if (oo instanceof EList) { + EList l = (EList) oo; + JSONArray a = new JSONArray(); + for (Object ooo : l) { + if (ooo instanceof EObject) { + EObject eo = (EObject) ooo; + a.put(ecore2json(eo, 100, (EClass) op.getEType(), true, true, true)); + } else { + a.put(attr2jsonValue(0, ooo, op.getEType())); + } + } + res.put("returns", a); + } else if (oo instanceof EObject) { + EObject eo = (EObject) oo; + res.put("returns", ecore2json(eo, 100, (EClass) op.getEType(), true, true, true)); + } else { + res.put("returns", oo == null ? null : attr2jsonValue(0, oo, op.getEType())); + } + return res; + } catch (Exception e) { + JSONObject res = new JSONObject(); + if (e instanceof InvocationTargetException && e.getCause() instanceof Exception) { + e = (Exception) e.getCause(); + } + res.put("exception", e.toString()); + // res.put("location", e.getStackTrace()[1].toString()); + res.put("directory", props.get("user.dir")); + res.put("user", props.get("user.name")); + res.put("hostname", props.get("user.hostname")); + res.put("port", props.get("server.port")); + res.put("class", eClassName); + res.put("action", action); + res.put("request", json); + res.put("context", context); + if (e instanceof ManagementServerError) { + ManagementServerError ee = (ManagementServerError) e; + res.put("remote", ee.getJson()); + } else + printStackTrace(e); + List<String> args = new ArrayList<String>(); + for (EParameter p : op.getEParameters()) { + args.add(p.getEType().getName()); + } + logger.error(PropertyUtil.replaceForLogForcingProtection("operation " + action + "(" + StringUtil.join(args, ",") + ") failed requestId: " + + context.getString("requestId") + " " + e)); + throw new ManagerException(500, "operation failed: " + action + "\n" + res.toString(2)); + } + } + + private EObject parameterObjectFromJson(EClass eClass1, JSONObject json) { + if (json.has("$ref")) { + String path = (String) json.get("$ref"); + if (path.equals("NULL")) + return null; + if (path.equals("")) + return null; + Subject s = find(root, path); + if (s.o == null) + return null; + if (!eClass1.isInstance(s.o)) { + throw new RuntimeException("Bad type expected: " + eClass1.getName() + " " + path); + } + return s.o; + } + List<Ref> refs = new ArrayList<ManagementServer.Ref>(); + EObject ooo = loadObjectFromJson(eClass1.getEPackage().getEFactoryInstance(), eClass1.getName(), json, refs); + updateRefs(ooo, refs); + return ooo; + } + + @Override + public Object handleBinary(String userName, String action, String resourcePath, InputStream in) { + if (!pe.permit(userName, action, resourcePath)) + throw new RuntimeException("Action not permitted: " + userName + " " + action + " " + resourcePath); + return null; + } + + public Jetty8Client getJettyClient() { + return jettyClient; + } + + public void shutdown() { + // TODO Auto-generated method stub + + } + + public EObject getObject() { + return root; + } + + public void setObject(EObject root) { + this.root = root; + } + + int i = 0; + + public void save() { + int j = i++; + // System.err.println("XXXX save start:" + j); + save(root, "ROOT", directory, true, root.eClass()); + // System.err.println("XXXX save done:" + j); + lastSave = new Date(); + } + + private Date lastSave = null; + + public synchronized void save(long ms) { + Date now = new Date(); + if (lastSave == null || lastSave.getTime() + ms < now.getTime()) + save(); + } + + public void save(EObject o, String id, String directory, boolean singleton, EClass defClass) { + JSONObject json = ecore2json(o, -1, defClass, false); + String fname = directory + (o.eContainer() == null ? "/ROOT" : "") + ".json"; + for (EReference ref : o.eClass().getEAllContainments()) { + if (ref.isMany()) { + HashSet<String> names = new HashSet<String>(); + // Try 3 times to save list. + boolean saved = false; + for (int i = 0; i < 3; i++) { + try { + @SuppressWarnings("unchecked") + EList<EObject> l = (EList<EObject>) o.eGet(ref); + JSONArray a = new JSONArray(); + for (EObject oo : l) { + String n = ecoreId(oo); + if (names.contains(n)) { + System.err.println("name is already used " + n + " " + object2ref(o) + "@" + + ref.getName()); + } + names.add(n); + a.put(n); + String dir2 = directory + "/" + ref.getName() + "/" + n; + save(oo, null, dir2, false, ref.getEReferenceType()); + } + if (ref.isOrdered()) + json.put("$order:" + ref.getName(), a); + saved = true; + break; + } catch (ConcurrentModificationException e) { + // ManagementServerUtils.printStackTrace(e); + // logger.error("ConcurrentModificationException: " + + // o.eClass().getName() + "@" + ref.getName()); + continue; + } + } + if (!saved) { + System.err.println("unable to save object list: " + object2ref(o) + "@" + ref.getName()); + logger.error("unable to save object list: " + object2ref(o) + "@" + ref.getName()); + } + // delete no longer existing objects. + File dir = new File(directory + "/" + ref.getName()); + File[] files = dir.listFiles(); + if (files == null) + continue; + for (File f : files) { + if (f.isDirectory() && !names.contains(f.getName())) { + FileUtils.deleteDirectory(f); + } + if (f.getName().endsWith(".json")) { + String n = f.getName().substring(0, f.getName().length() - 5); + if (!names.contains(n)) { + f.delete(); + } + } + } + } else { + String dir2 = directory + "/" + ref.getName(); + EObject oo = (EObject) o.eGet(ref); + if (oo == null) { + File f = new File(dir2); + if (f.exists()) + FileUtils.deleteDirectory(f); + f = new File(dir2 + ".json"); + if (f.exists()) + f.delete(); + } else + save(oo, ecoreId(oo), dir2, true, ref.getEReferenceType()); + } + } + storeJson(fname, json); + } + + HashMap<String, String> cache = new HashMap<String, String>(); + + private synchronized void storeJson(String fname, JSONObject json) { + // TODO cache the data so we do no need to write the same all the time + // but need to support deletion of files and directory. See save(..) + // above. + // String s = json.toString(); + // if (s.equals(cache.get(fname))) return; + try { + OutputStreamWriter w = FileUtils.filename2writer(fname + ".tmp"); + w.append(json.toString(2)); + w.close(); + File f1 = new File(fname); + File f2 = new File(fname + ".tmp"); + f2.renameTo(f1); + } catch (IOException e) { + // TODO Auto-generated catch block + printStackTrace(e); + } + } + + private static String ecoreId(EObject oo) { + EStructuralFeature f = oo.eClass().getEStructuralFeature("name"); + if (f instanceof EAttribute) { + EAttribute attr = (EAttribute) f; + return (String) oo.eGet(attr); + } + if (oo.eContainer() != null) { + if (oo.eContainmentFeature().isMany()) { + @SuppressWarnings("unchecked") + EList<EObject> l = (EList<EObject>) oo.eContainer().eGet(oo.eContainmentFeature()); + return Integer.toString(l.indexOf(oo)); + } else { + return oo.eContainmentFeature().getName(); + } + } + return "id" + id++; + } + + // private String jsonId(JSONObject json2) { + // if (json2.has("name")) + // return json2.getString("name"); + // return "id" + id++; + // } + + public static Object attr2jsonValue(int levels, Object o, EClassifier eClassifier) { + if (!(eClassifier instanceof EDataType)) + return null; + EDataType t = (EDataType) eClassifier; + EFactory f = t.getEPackage().getEFactoryInstance(); + // TODO handle int and doubles. + if (levels == -3 && o == null) { + JSONObject json = new JSONObject(); + json.put("$isNull", true); + return json; + } + return f.convertToString(t, o); + } + + public static Object jsonValue2attrValue(EDataType t, Object value) { + EFactory f = t.getEPackage().getEFactoryInstance(); + // System.err.println("XXXYYZZ: " + t + " value=" + value + " " + + // value.getClass()); + if (value instanceof String && t.getInstanceClass().equals(Date.class)) { + try { + return new Date(Long.parseLong((String) value)); + } catch (NumberFormatException e) { + } + } + if (value instanceof String) { + String s = (String) value; + return f.createFromString(t, s); + } + if (value instanceof Long && t.getInstanceClass().equals(Date.class)) { + Long l = (Long) value; + return new Date(l); + } + if (value instanceof Integer && t.getInstanceClass().equals(Date.class)) { + long l = (Integer) value; + return new Date(l); + } + if (t.getInstanceClass().equals(Long.class) && value instanceof Integer) { + return Long.valueOf((Integer) value); + } + if (t.getInstanceClass().equals(long.class) && value instanceof Integer) { + return Long.valueOf((Integer) value); + } + if (t.getInstanceClass().equals(Long.class) && value instanceof Integer) { + return Long.valueOf((Integer) value); + } + if (t.getInstanceClass().equals(long.class) && value instanceof Integer) { + return Long.valueOf((Integer) value); + } + if (t.getInstanceClass().equals(String.class) && value instanceof Integer) { + return Integer.toString((int) value); + } + if (t.getInstanceClass().equals(String.class) && value instanceof Double) { + return Double.toString((double) value); + } + if (t.getInstanceClass().equals(String.class) && value instanceof Long) { + return Long.toString((long) value); + } + if (t.getInstanceClass().equals(String.class) && value instanceof Boolean) { + return Boolean.toString((boolean) value); + } + if (value instanceof Integer || value instanceof Double || value instanceof Long || value instanceof Boolean) { + return value; + } + return null; + } + + private Object stringValue2attrValue(EDataType t, String s) { + EFactory f = t.getEPackage().getEFactoryInstance(); + return f.createFromString(t, s); + } + + class Ref { + public Ref(EObject o, EReference ref, Object object) { + super(); + this.o = o; + this.ref = ref; + this.json = (JSONObject) object; // TODO handle error cases + } + + EObject o; + EReference ref; + JSONObject json; + + @Override + public String toString() { + return "Ref [o=" + o + ", ref=" + ref + ", json=" + json + "]"; + } + } + + private void handleReference(EObject o, JSONObject json, List<Ref> refs) { + // System.out.println ("AAAAupdate : " + object2ref(o) + " " + + // json.toString(2)); + for (EReference ref : o.eClass().getEAllReferences()) { + if (!json.has(ref.getName())) + continue; + if (ref.isContainer()) + continue; + if (ref.isContainment()) { + if (json.has("$version") || jsonHasVersion(json.get(ref.getName()))) + continue; + if (ref.isMany()) { + Object x = json.get(ref.getName()); + @SuppressWarnings("unchecked") + EList<EObject> l = (EList<EObject>) o.eGet(ref); + if (x instanceof JSONObject) { + EAttribute f = namingAttribute(ref); + JSONObject o1 = (JSONObject) x; + for (EObject oo : l) { + handleReference(oo, o1.getJSONObject((String) oo.eGet(f)), refs); + } + } else { + JSONArray a = (JSONArray) x; + int i = 0; + for (EObject oo : l) { + handleReference(oo, a.getJSONObject(i), refs); + i++; + } + } + } else { + EObject oo = (EObject) o.eGet(ref); + if (oo == null) continue; + Object oo1 = json.get(ref.getName()); + if (oo1 != null && oo1.getClass().getCanonicalName().equals("org.json.JSONObject.Null")) { + oo1 = null; + } + if (oo1 instanceof JSONObject || oo1 == null) { + handleReference(oo, (JSONObject) oo1, refs); + continue; + } + throw new RuntimeException("Unable to handle reference: " + ref.getName() + + " " + oo1.getClass().getCanonicalName()); + } + continue; + } + // is reference + if (ref.isMany()) { + Object aa = json.get(ref.getName()); + if (aa instanceof JSONArray) { + JSONArray a = (JSONArray) aa; + for (int i = 0; i < a.length(); i++) { + refs.add(new Ref(o, ref, a.get(i))); + } + } + } else { + refs.add(new Ref(o, ref, json.get(ref.getName()))); + } + + } + // System.out.println ("AAAAupdate : " + object2ref(o) + " " + refs); + } + + private boolean jsonHasVersion(Object object) { + if (object instanceof JSONObject) { + JSONObject json = (JSONObject) object; + if (json.has("$version") || json.has("$child") || json.has("$children")) + return true; + for (Iterator<String> i = json.keys(); i.hasNext();) { + String s = i.next(); + if (jsonHasVersion(json.get(s))) + return true; + } + } + if (object instanceof JSONArray) { + JSONArray a = (JSONArray) object; + for (int i = 0; i < a.length(); i++) { + if (jsonHasVersion(a.get(i))) + return true; + } + } + return false; + } + + private void updateRefs(EObject res, List<Ref> refs) { + for (Ref x : refs) { + // System.out.println("REF: " + ref2name(x.ref) + " " + x.json); + // TODO handle error better. + if (!x.json.has("$ref")) + continue; + String path = (String) x.json.get("$ref"); + if (path.equals("NULL")) + continue; + if (path.equals("")) + continue; + EObject root1 = res; + if (x.json.has("$refroot")) { + // Not tested + String rootpath = (String) x.json.get("$refroot"); + System.err.println("XXXX using new root: " + rootpath); + if (!rootpath.equals("NULL") && !rootpath.equals("")) { + Subject s1 = find(root, rootpath); + System.err.println("XXXX using new root: " + s1); + if (s1 == null || s1.o != null) { + root1 = s1.o; + System.err.println("XXXX using new root: " + root1); + } + } + } + Subject s = find(root1, path); + if (s == null || s.ref != null) { + logger.warn("Unable to determine reference for:" + PropertyUtil.replaceForLogForcingProtection(path)); + continue; + } + if (x.ref.isMany()) { + @SuppressWarnings("unchecked") + EList<EObject> l = (EList<EObject>) x.o.eGet(x.ref); + l.add(s.o); + } else { + try { + // System.out.println("XXX:" + object2ref(x.o) + " " + + // object2ref(s.o)); + x.o.eSet(x.ref, s.o); + } catch (Exception e) { + // System.out.println("Bad Reference:" + x.o); + // System.out.println("Bad Reference:" + x.ref + " " + + // x.ref.getEContainingClass()); + // System.out.println("Bad Reference:" + s.o); + logger.warn("Bad Reference:" + path + " " + x.json + " " + e); + } + } + } + } + + public static JSONObject params2json(EOperation operation, Object[] params) { + if (params.length != operation.getEParameters().size()) { + String n = operation.getEContainingClass().getName() + "@" + operation.getName(); + throw new RuntimeException("Wrong number of arguments for " + n + " got " + params.length + " expected " + + operation.getEParameters().size()); + } + JSONObject json = new JSONObject(); + for (int i = 0; i < params.length; i++) { + EParameter p = operation.getEParameters().get(i); + if (p.getEType() instanceof EClass) { + EClass eClass = (EClass) p.getEType(); + if (p.isMany()) { + @SuppressWarnings("unchecked") + List<Object> l = (List<Object>) params[i]; + JSONArray a = new JSONArray(); + for (Object oo : l) { + a.put(object2json(oo, 100, eClass, true)); + } + json.put(p.getName(), a); + } else { + json.put(p.getName(), object2json(params[i], 100, eClass, true)); + } + + } else { + if (p.isMany()) { + JSONArray a = new JSONArray(); + json.put(p.getName(), a); + @SuppressWarnings("unchecked") + List<Object> l = (List<Object>) params[i]; + for (Object oo : l) { + a.put(attr2jsonValue(0, oo, p.getEType())); + } + } else + json.put(p.getName(), attr2jsonValue(0, params[i], p.getEType())); + } + } + return json; + } + + private static JSONObject object2json(Object o, int i, EClass eClass, boolean b) { + if (o instanceof EObject) { + return ecore2json((EObject) o, i, eClass, b); + } + if (o instanceof JSONObject) { + return (JSONObject) o; + } + if (o == null) + return null; + throw new RuntimeException("Unable to convert object to json: " + o); + } + + static ManagementServer staticServer = new ManagementServer(); + + public static Object json2response(EOperation operation, JSONObject res) { + if (res == null) + return null; + if (res.length() == 0) + return null; // TODO Handle this better. + if (res.has("returns")) { + if (operation.getEType() instanceof EClass) { + EClass eClass = (EClass) operation.getEType(); + if (operation.isMany()) { + EList<EObject> l = new BasicEList<EObject>(); + JSONArray a = res.getJSONArray("returns"); + for (int i = 0; i < a.length(); i++) { + l.add(staticServer.json2ecore(eClass, a.getJSONObject(i))); + } + return l; + } else { + return staticServer.json2ecore(eClass, res.getJSONObject("returns")); + } + } else { + EDataType eType = (EDataType) operation.getEType(); + if (operation.isMany()) { + EList<Object> l = new BasicEList<Object>(); + JSONArray a = res.getJSONArray("returns"); + for (int i = 0; i < a.length(); i++) { + l.add(jsonValue2attrValue(eType, a.get(i))); + } + return l; + } else { + return jsonValue2attrValue(eType, res.get("returns")); + } + } + } + throw new ManagementServerError("remote error", res); + } + + public static String expandPath(EObject o, String pattern, String prefix) { + // E.g. "foobar/${@name}" + String x = prefix.equals("$") ? "\\" : ""; + Pattern p = Pattern.compile("(" + x + prefix + "\\{.*?})"); + Matcher m = p.matcher(pattern); + StringBuffer s = new StringBuffer(); + while (m.find()) { + String k = m.group(1); + String k1 = k.substring(2, k.length() - 1); + try { + Subject subject = find(o, k1); + if (subject == null || subject.o == null || subject.attr == null) + throw new RuntimeException("unable to resolve path: " + k1 + " on " + o); + m.appendReplacement(s, (String) subject.o.eGet(subject.attr)); + } catch (Exception e) { + logger.warn("bad expansion: " + e); + m.appendReplacement(s, x + k); + } + } + m.appendTail(s); + return s.toString(); + } + + public static OperationalState getOperationalState(EObject a) { + if (a instanceof HasOperationalState) { + HasOperationalState o1 = (HasOperationalState) a; + if (o1.getOperationalState() == OperationalState.SUSPENDED) + return OperationalState.SUSPENDED; + } + if (a.eContainer() != null) { + if (getOperationalState(a.eContainer()) == OperationalState.SUSPENDED) + return OperationalState.SUSPENDED; + } + return OperationalState.OPERATIONAL; + } + + public static boolean isSuspended(EObject o, String message) { + if (getOperationalState(o) == OperationalState.SUSPENDED) { + logger.warn("Suspended: " + message); + return true; + } + return false; + } + + public static boolean refIsNamed(EReference ref) { + // System.err.println("ZZZ : " + ref + " " + ref.getEReferenceType() + // + " " + + // ref.getEReferenceType().isSuperTypeOf(ModelPackage.eINSTANCE.getNamedEntity()) + // + " " + + // ModelPackage.eINSTANCE.getNamedEntity().isSuperTypeOf(ref.getEReferenceType()) + // ); + return true; + } + + public DroolsRuntime getDroolsRuntime() { + return droolsRuntime; + } + + public void setDroolsRuntime(DroolsRuntime droolsRuntime) { + this.droolsRuntime = droolsRuntime; + } + + // ECOMP on ECOMP + public void recordApi(String parentTransactionId, EObject o, String action, ApiRequestStatus status, long duration, + Object... params) { + if (!(root instanceof AbstractManagementServer)) + return; + Api api = findApi(o, action); + switch (status) { + case ERROR: + metrics.addIncreasingULongMetric(api, "numberOfErrorRequests", 1L, false); + break; + case START: + metrics.addIncreasingULongMetric(api, "numberOfRequests", 1L, false); + break; + case OKAY: + metrics.addIncreasingULongMetric(api, "numberOfCompletedRequests", 1L, false); + metrics.setLongMetric(api, "lastRequestDuration", duration, false); + break; + case INPROGRESS: + break; + default: + break; + } + } + + public void recordPolicyFire(String droolsRuntime, String ruleName) { + } + + public void recordPolicyObjectChange(String droolsRuntime, Object o, DroolsObjectChange changeType) { + } + + private synchronized Api findApi(EObject o, String action) { + AbstractManagementServer a = (AbstractManagementServer) root; + if (a.getComponent() == null) { + a.setComponent(ComponentFactory.eINSTANCE.createComponent()); + } + String n = o.eClass().getInstanceClassName(); + ComponentClass c = (ComponentClass) findWithName(a.getComponent().getClasses(), n); + if (c == null) { + c = ComponentFactory.eINSTANCE.createComponentClass(); + c.setName(n); + a.getComponent().getClasses().add(c); + } + Api api = (Api) findWithName(c.getApis(), action); + if (api == null) { + api = ComponentFactory.eINSTANCE.createApi(); + api.setName(action); + c.getApis().add(api); + } + return api; + } + + public static EObject findWithName(EList<? extends NamedEntity> l, String name) { + for (NamedEntity n : l) { + if (n.getName().equals(name)) + return n; + } + return null; + } + + @SuppressWarnings("unchecked") + public static void copy(EObject o, EObject o1) { + for (EAttribute attr1 : o1.eClass().getEAllAttributes()) { + EStructuralFeature f = o.eClass().getEStructuralFeature(attr1.getName()); + System.out.println("DDDDD " + attr1 + " f=" + f); + if (f instanceof EAttribute) { + EAttribute attr = (EAttribute) f; + System.out.println("DDDDD " + attr + " " + o.eGet(attr)); + o1.eSet(attr1, o.eGet(attr)); + } + } + for (EReference ref1 : o1.eClass().getEAllContainments()) { + EStructuralFeature f = o.eClass().getEStructuralFeature(ref1.getName()); + if (f instanceof EReference) { + EReference ref = (EReference) f; + if (ref1.isMany()) + o1.eSet(ref1, EcoreUtil.copyAll((EList<EObject>) o.eGet(ref))); + else + o1.eSet(ref1, EcoreUtil.copy((EObject) o.eGet(ref))); + } + } + + } + + public static JSONObject ensureHardUpdate(EObject o2, int levels) { + JSONObject json = ManagementServer.ecore2json(o2, 1000, null, true); + ensureHardUpdate(json, levels); + return json; + } + + private static void ensureHardUpdate(JSONObject json, int levels) { + if (levels <= 0) { + json.put("$useNull", 1); + return; + } + for (Iterator<String> i = json.keys(); i.hasNext();) { + Object o = json.get(i.next()); + if (o instanceof JSONObject) { + ensureHardUpdate((JSONObject) o, levels - 1); + } + if (o instanceof JSONArray) { + JSONArray a = (JSONArray) o; + for (int j = 0; j < a.length(); j++) { + if (a.get(j) instanceof JSONObject) { + ensureHardUpdate((JSONObject) a.get(j), levels - 1); + } + } + } + + } + } + + public static void decryptPasswords(EObject o) { + for (EAttribute attr : o.eClass().getEAllAttributes()) { + if (! attr.getEType().getName().equals("EString")) continue; + if (attr.isMany()) continue; + String v = (String) o.eGet(attr); + if (v != null && v.startsWith("rsa:")) { + o.eSet(attr, JavaHttpClient.decryptPassword(v)); + } + } + for (EReference ref : o.eClass().getEAllContainments()) { + if (ref.isMany()) { + @SuppressWarnings("unchecked") + EList<EObject> l = (EList<EObject>) o.eGet(ref); + for (EObject oo : l) { + decryptPasswords(oo); + } + } else { + EObject oo = (EObject) o.eGet(ref); + decryptPasswords(oo); + } + } + } + + public JSONObject getSwaggerJson() { + try { + SwaggerUtils swagger = new SwaggerUtils(); + ISwaggerHandler handler = this; + if (root instanceof ISwaggerHandler) { + handler = (ISwaggerHandler) root; + } + System.err.println("SWAGGER: Start"); + handler.updateSwagger("/resources", swagger); + System.err.println("SWAGGER: Done"); + JSONObject json = swagger.toJson(); + System.err.println("SWAGGER: " + json.toString(2)); + return json; + } catch (Exception e) { + System.err.println("SWAGGER: Error" + e); + e.printStackTrace(); + throw e; + } + } + + @Override + public void updateSwagger(String path, SwaggerUtils swagger) { + swagger.addTag(path, "Server Configuration",root); + } +} |