blob: 370e9cc854f0228ea5a3131ed87012dc77d89b24 [file] [log] [blame]
Bharat saraswalf53b29a2016-09-27 15:35:15 +05301/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.yms.app.ysr;
18
19import org.onosproject.event.ListenerService;
20import org.onosproject.yangutils.datamodel.RpcNotificationContainer;
21import org.onosproject.yangutils.datamodel.YangInclude;
22import org.onosproject.yangutils.datamodel.YangModule;
23import org.onosproject.yangutils.datamodel.YangNode;
24import org.onosproject.yangutils.datamodel.YangSchemaNode;
25import org.onosproject.yangutils.datamodel.YangSubModule;
26import org.onosproject.yangutils.datamodel.exceptions.DataModelException;
27import org.onosproject.yms.app.ynh.YangNotificationExtendedService;
28import org.onosproject.yms.ysr.YangModuleIdentifier;
29import org.onosproject.yms.ysr.YangModuleInformation;
30import org.onosproject.yms.ysr.YangModuleLibrary;
31import org.osgi.framework.BundleContext;
32import org.slf4j.Logger;
33import org.slf4j.LoggerFactory;
34
35import java.io.File;
36import java.io.FileInputStream;
37import java.io.IOException;
38import java.io.ObjectInputStream;
39import java.text.SimpleDateFormat;
40import java.util.ArrayList;
41import java.util.Collections;
42import java.util.HashSet;
43import java.util.Iterator;
44import java.util.List;
45import java.util.Set;
46import java.util.concurrent.ConcurrentHashMap;
47import java.util.concurrent.ConcurrentMap;
48import java.util.regex.Pattern;
49
50import static org.apache.commons.io.FileUtils.deleteDirectory;
51import static org.onosproject.yangutils.datamodel.utils.DataModelUtils.parseJarFile;
52import static org.onosproject.yangutils.utils.UtilConstants.DEFAULT;
53import static org.onosproject.yangutils.utils.UtilConstants.EMPTY_STRING;
54import static org.onosproject.yangutils.utils.UtilConstants.EVENT_STRING;
55import static org.onosproject.yangutils.utils.UtilConstants.OP_PARAM;
56import static org.onosproject.yangutils.utils.UtilConstants.PERIOD;
57import static org.onosproject.yangutils.utils.io.impl.YangIoUtils.getCapitalCase;
58import static org.osgi.framework.FrameworkUtil.getBundle;
59
60
61/**
62 * Representation of default YANG schema registry. Yang schema registry
63 * provides interface to an application to register its YANG schema
64 * with YMS. It provides YANG schema nodes to YDT, YNB and YSB.
65 */
66public class DefaultYangSchemaRegistry
67 implements YangSchemaRegistry {
68
69 private static final String SYSTEM = File.separator + "system" +
70 File.separator;
71 private static final String MAVEN = "mvn:";
72 private static final String HYPHEN = "-";
73 private static final String DELIMITER = ".";
74 private static final String SERVICE = "Service";
75 private static final String JAR = ".jar";
76 private static final String USER_DIRECTORY = "user.dir";
77 private static final String SLASH = File.separator;
78 private static final String AT = "@";
79 private static final String DATE_FORMAT = "yyyy-mm-dd";
80 private static final Logger log =
81 LoggerFactory.getLogger(DefaultYangSchemaRegistry.class);
82
83 /*
84 * Map for storing app objects.
85 */
86 private final ConcurrentMap<String, YsrAppContext> appObjectStore;
87
88 /*
89 * Map for storing YANG schema nodes.
90 */
91 private final ConcurrentMap<String, YsrAppContext> yangSchemaStore;
92
93 /*
94 * Map for storing YANG schema nodes with respect to root's generated
95 * interface file name.
96 */
97 private final ConcurrentMap<String, YsrAppContext>
98 yangSchemaStoreForRootInterface;
99
100 /*
101 * Map for storing YANG schema nodes root's generated op param file name.
102 */
103 private final ConcurrentMap<String, YsrAppContext>
104 yangSchemaStoreForRootOpParam;
105
106 /*
107 * Map for storing YANG schema nodes with respect to notifications.
108 */
109 private final ConcurrentMap<String, YsrAppContext>
110 yangRootSchemaStoreForNotification;
111
112 /*
113 * Map for storing registered classes.
114 */
115 private final ConcurrentMap<String, Class<?>> registerClassStore;
116
117 /*
118 * Map for storing YANG file details.
119 */
120 private final ConcurrentMap<YangModuleIdentifier, String> yangFileStore;
121
122 /*
123 * Context of application which is registering with YMS.
124 */
125 private YsrAppContext ysrAppContext;
126
127 /*
128 * Context of application which is registering with YMS with multiple
129 * revision.
130 */
131 private YsrAppContext ysrContextForSchemaStore;
132
133 /*
134 * Context of application which is registering with YMS with multiple
135 * manager object.
136 */
137 private YsrAppContext ysrContextForAppStore;
138
139 /*
140 * Class loader of service application.
141 */
142 private ClassLoader classLoader;
143
144 /**
145 * YANG module library.
146 */
147 private final YangModuleLibrary library;
148
149 /**
150 * Creates an instance of default YANG schema registry.
151 *
152 * @param moduleId module set id of YSR module library
153 */
154 public DefaultYangSchemaRegistry(String moduleId) {
155 appObjectStore = new ConcurrentHashMap<>();
156 yangSchemaStore = new ConcurrentHashMap<>();
157 yangSchemaStoreForRootInterface = new ConcurrentHashMap<>();
158 yangSchemaStoreForRootOpParam = new ConcurrentHashMap<>();
159 yangRootSchemaStoreForNotification = new ConcurrentHashMap<>();
160 registerClassStore = new ConcurrentHashMap<>();
161 yangFileStore = new ConcurrentHashMap<>();
162 library = new DefaultYangModuleLibrary(moduleId);
163 }
164
165
166 @Override
167 public void registerApplication(Object appObject, Class<?> serviceClass,
168 YangNotificationExtendedService
169 notificationExtendedService) {
170
171 BundleContext bundleContext = getBundle(serviceClass)
172 .getBundleContext();
173 String jarPath = getJarPathFromBundleLocation(
174 bundleContext.getBundle().getLocation(),
175 bundleContext.getProperty(USER_DIRECTORY));
176 // process application registration.
177 processRegistration(serviceClass, appObject, jarPath);
178 //process notification registration.
179 processNotificationRegistration(serviceClass, appObject,
180 notificationExtendedService);
181 }
182
183 /**
184 * Process application registration.
185 *
186 * @param serviceClass service class
187 * @param appObject application object
188 * @param jarPath jar path
189 */
190 void processRegistration(Class<?> serviceClass, Object appObject,
191 String jarPath) {
192
193 // set class loader for service class.
194 setClassLoader(serviceClass.getClassLoader());
195
196 //Check if service should be registered?
197 if (appObject != null) {
198 verifyApplicationRegistration(appObject, serviceClass);
199 }
200 //Add app class to registered service store.
201 if (!registerClassStore.containsKey(serviceClass.getName())) {
202 updateServiceClass(serviceClass);
203 }
204
205 // process storing operations.
206 if (!verifyIfApplicationAlreadyRegistered(serviceClass)) {
207 List<YangNode> curNodes =
208 processJarParsingOperations(jarPath);
209
210 if (curNodes != null) {
211 for (YangNode schemaNode : curNodes) {
212 //Process application context for registrations.
213 processApplicationContext(schemaNode);
214 //Update YANG file store.
215 updateYangFileStore(schemaNode, jarPath);
216 //Process module library operation for current node list.
217 processModuleLibrary(schemaNode);
218 }
219 //Set jar path for app context.
220 ysrAppContext.jarPath(jarPath);
221 ysrContextForSchemaStore.jarPath(jarPath);
222 ysrContextForAppStore.jarPath(jarPath);
223 }
224 }
225
226 //Verifies if object is updated for app store.
227 updateApplicationObject(appObject, serviceClass);
228 }
229
230 /**
231 * Verifies if service class should be registered or not.
232 *
233 * @param appObject application object
234 * @param appClass application class
235 */
236 private void verifyApplicationRegistration(Object appObject,
237 Class<?> appClass) {
238 Class<?> managerClass = appObject.getClass();
239 Class<?>[] services = managerClass.getInterfaces();
240 List<Class<?>> classes = new ArrayList<>();
241 Collections.addAll(classes, services);
242 if (!classes.contains(appClass)) {
243 throw new RuntimeException("service class " + appClass.getName() +
244 "is not being implemented by " +
245 managerClass.getName());
246 }
247 }
248
249 /**
250 * Verifies if application is already registered with YMS.
251 *
252 * @param appClass application class
253 * @return true if application already registered
254 */
255 private boolean verifyIfApplicationAlreadyRegistered(Class<?> appClass) {
256 String simpleName = appClass.getSimpleName();
257 String appName = appClass.getName();
258 if (!appObjectStore.containsKey(appName)) {
259 if (simpleName.contains(OP_PARAM)) {
260 return yangSchemaStoreForRootOpParam
261 .containsKey(appName);
262 } else {
263 return yangSchemaStoreForRootInterface
264 .containsKey(appName);
265 }
266 }
267 return true;
268 }
269
270 /**
271 * Verifies if service is being implemented by some new object.
272 *
273 * @param appObject application's object
274 * @param appClass application's class
275 */
276 private void updateApplicationObject(Object appObject, Class<?> appClass) {
277 YsrAppContext appContext =
278 appObjectStore.get(appClass.getName());
279 if (appContext != null) {
280 YangSchemaNode schemaNode = appContext.curNode();
281 String name = getInterfaceClassName(schemaNode);
282 if (appContext.appObject() == null) {
283 //update in application store.
284 appContext.appObject(appObject);
285 //Update app object for schema store for root interface.
286 appContext = yangSchemaStoreForRootInterface.get(name);
287 if (appContext != null) {
288 appContext.appObject(appObject);
289 }
290 // Update app object for schema store for root op param
291 appContext = yangSchemaStoreForRootOpParam.get(name + OP_PARAM);
292 if (appContext != null) {
293 appContext.appObject(appObject);
294 }
295 }
296 }
297 }
298
299 @Override
300 public void unRegisterApplication(Object managerObject,
301 Class<?> serviceClass) {
302 YangSchemaNode curNode = null;
303 String serviceName = serviceClass.getName();
304
305 //Check if service should be unregistered?
306 if (managerObject != null) {
307 verifyApplicationRegistration(managerObject, serviceClass);
308 }
309 //Remove registered class from store.
310 registerClassStore.remove(serviceName);
311
312 //check if service is in app store.
313 if (appObjectStore.containsKey(serviceName)) {
314 curNode = retrieveNodeForUnregister(serviceName, appObjectStore,
315 managerObject);
316 } else if (yangSchemaStoreForRootInterface.containsKey(serviceName)) {
317 //check if service is in interface store.
318 curNode = retrieveNodeForUnregister(serviceName,
319 yangSchemaStoreForRootInterface,
320 managerObject);
321 } else if (yangSchemaStoreForRootOpParam.containsKey(serviceName)) {
322 //check if service is in op param store.
323 curNode = retrieveNodeForUnregister(serviceName,
324 yangSchemaStoreForRootOpParam,
325 managerObject);
326 }
327 if (curNode != null) {
328 String javaName = getInterfaceClassName(curNode);
329 removeFromYangSchemaStore(curNode);
330 removeFromYangNotificationStore(curNode);
331 removeFromAppSchemaStore(serviceName);
332 removeFromYangSchemaNodeForRootInterface(javaName);
333 removeFromYangSchemaNodeForRootOpParam(javaName);
334 removeYangFileInfoFromStore(curNode);
335 log.info(" service {} is unregistered.",
336 serviceClass.getSimpleName());
337 } else {
338 throw new RuntimeException(serviceClass.getSimpleName() +
339 " service was not registered.");
340 }
341 }
342
343 @Override
344 public Object getRegisteredApplication(YangSchemaNode schemaNode) {
345 if (schemaNode != null) {
346 String name = getInterfaceClassName(schemaNode);
347 if (yangSchemaStoreForRootInterface.containsKey(name)) {
348 return yangSchemaStoreForRootInterface.get(name)
349 .appObject();
350 }
351 log.error("{} not found.", name);
352 }
353 return null;
354 }
355
356 @Override
357 public YangSchemaNode getYangSchemaNodeUsingSchemaName(String schemaName) {
358 return getSchemaNodeUsingSchemaNameWithRev(schemaName);
359 }
360
361 @Override
362 public YangSchemaNode getYangSchemaNodeUsingAppName(String appName) {
363 YsrAppContext appContext = appObjectStore.get(appName);
364 if (appContext != null) {
365 return appContext.curNode();
366 }
367 log.error("{} not found.", appName);
368 return null;
369 }
370
371 @Override
372 public YangSchemaNode
373 getYangSchemaNodeUsingGeneratedRootNodeInterfaceFileName(String name) {
374 YsrAppContext appContext = yangSchemaStoreForRootInterface.get(name);
375 if (appContext != null) {
376 return appContext.curNode();
377 }
378 log.error("{} not found.", name);
379 return null;
380 }
381
382 @Override
383 public YangSchemaNode getYangSchemaNodeUsingGeneratedRootNodeOpPramFileName(
384 String name) {
385 YsrAppContext appContext = yangSchemaStoreForRootOpParam.get(name);
386 if (appContext != null) {
387 return appContext.curNode();
388 }
389 log.error("{} not found.", name);
390 return null;
391 }
392
393 @Override
394 public YangSchemaNode getRootYangSchemaNodeForNotification(String name) {
395 YsrAppContext appContext = yangRootSchemaStoreForNotification.get(name);
396 if (appContext != null) {
397 return appContext.curNode();
398 }
399 log.error("{} not found.", name);
400 return null;
401 }
402
403 @Override
404 public Class<?> getRegisteredClass(YangSchemaNode schemaNode,
405 String appName) {
406 String interfaceName = getInterfaceClassName(schemaNode);
407 String serviceName = getServiceName(schemaNode);
408 String defaultClass;
409 if (schemaNode instanceof RpcNotificationContainer) {
410 defaultClass = getOpParamClassName(schemaNode);
411 } else {
412 defaultClass = getDefaultClassName(schemaNode);
413 }
414 //If application class is registered.
415 if (registerClassStore.containsKey(appName)) {
416 return registerClassStore.get(appName);
417 } else if (registerClassStore.containsKey(interfaceName)) {
418 //If interface class is registered.
419 return registerClassStore.get(interfaceName);
420 } else if (registerClassStore.containsKey(serviceName)) {
421 //If service class is registered.
422 return registerClassStore.get(serviceName);
423 } else if (registerClassStore.containsKey(defaultClass)) {
424 //If default class is registered.
425 return registerClassStore.get(defaultClass);
426 }
427 return null;
428 }
429
430 /**
431 * Returns YANG file path for module identifier.
432 *
433 * @param moduleIdentifier module identifier
434 * @return YANG file path for module identifier
435 */
436 public String getYangFile(YangModuleIdentifier moduleIdentifier) {
437 if (yangFileStore.containsKey(moduleIdentifier)) {
438 return yangFileStore.get(moduleIdentifier);
439 }
440 log.error("YANG files for corresponding module identifier {} not " +
441 "found", moduleIdentifier);
442 return null;
443 }
444
445 /**
446 * Updates service class store.
447 *
448 * @param serviceClass service class
449 */
450 void updateServiceClass(Class<?> serviceClass) {
451 registerClassStore.put(serviceClass.getName(), serviceClass);
452 }
453
454 /**
455 * Updates application object store.
456 *
457 * @param appName application name
458 */
459 private void updateAppObjectStore(String appName) {
460 if (verifyClassExistence(appName)) {
461 appObjectStore.put(appName, ysrContextForAppStore);
462 }
463 }
464
465 /**
466 * Updates YANG schema object store.
467 *
468 * @param schemaNode application's schema node
469 */
470 private void updateYangSchemaStore(YangSchemaNode schemaNode) {
471 addSchemaNodeUsingSchemaNameWithRev(schemaNode);
472 }
473
474 /**
475 * Updates YANG schema notification object store.
476 *
477 * @param name application's notification name
478 */
479 private void updateYangNotificationStore(String name) {
480 if (verifyClassExistence(name)) {
481 yangRootSchemaStoreForNotification.put(name, ysrAppContext);
482 }
483 }
484
485 /**
486 * Updates YANG schema object store for root interface file name.
487 *
488 * @param name name of generated interface file for root
489 * node
490 */
491 private void updateYangSchemaForRootInterfaceFileNameStore(String name) {
492 if (verifyClassExistence(name)) {
493 yangSchemaStoreForRootInterface.put(name, ysrAppContext);
494 }
495 }
496
497 /**
498 * Updates YANG schema object store for root op param file name.
499 *
500 * @param name name of generated op param file for root node
501 */
502 private void updateYangSchemaForRootOpParamFileNameStore(String name) {
503 if (verifyClassExistence(name)) {
504 yangSchemaStoreForRootOpParam.put(name, ysrAppContext);
505 }
506 }
507
508 /**
509 * Updates yang file store for YANG node.
510 *
511 * @param node YANG node
512 * @param jarPath jar file path
513 */
514 private void updateYangFileStore(YangNode node, String jarPath) {
515 //FIXME: fix when yang tools support for file name.
516 //yangFileStore.put(getModuleIdentifier(node),
517 // getYangFilePath(jarPath, node.getFileName()));
518 }
519
520 /**
521 * Returns yang file path.
522 *
523 * @param jarPath jar path
524 * @param metaDataFileName name of yang file from metadata
525 * @return yang file path
526 */
527 private String getYangFilePath(String jarPath, String metaDataFileName) {
528 String[] metaData = metaDataFileName.split(SLASH);
529 return jarPath + SLASH + metaData[metaData.length - 1];
530 }
531
532 /**
533 * Process jar file for fetching YANG nodes.
534 *
535 * @param path jar file path
536 * @return YANG schema nodes
537 */
538 private List<YangNode> processJarParsingOperations(String path) {
539 //Deserialize data model and get the YANG node set.
540 try {
541 return parseJarFile(path + JAR, path);
542 } catch (IOException e) {
543 log.error(" failed to parse the jar file in path {} : {} ", path,
544 e.getMessage());
545 }
546 return null;
547 }
548
549 /**
550 * Process an application an updates the maps for YANG schema registry.
551 *
552 * @param appNode application YANG schema nodes
553 */
554 void processApplicationContext(YangSchemaNode appNode) {
555
556 String appName = getInterfaceClassName(appNode);
557
558 //Create a new instance of ysr app context for each node.
559 ysrAppContext = new YsrAppContext();
560 ysrContextForSchemaStore = new YsrAppContext();
561 ysrContextForAppStore = new YsrAppContext();
562
563 //add cur node to app context.
564 ysrAppContext.curNode(appNode);
565 ysrContextForAppStore.curNode(appNode);
566
567 //Updates maps wih schema nodes.
568 updateAppObjectStore(getServiceName(appNode));
569
570 // Updates schema store.
571 updateYangSchemaStore(appNode);
572 // update interface store.
573 updateYangSchemaForRootInterfaceFileNameStore(appName);
574 //update op param store.
575 updateYangSchemaForRootOpParamFileNameStore(getOpParamClassName(appNode));
576 //Checks if notification is present then update notification store map.
577 String eventSubject = null;
578 try {
579 if (appNode.isNotificationPresent()) {
580 eventSubject = getEventClassName(appNode);
581 }
582 } catch (DataModelException e) {
583 log.error("failed to search notification from schema map : {}",
584 e.getLocalizedMessage());
585 }
586 if (eventSubject != null) {
587 updateYangNotificationStore(eventSubject);
588 }
589 log.info("successfully registered this application {}{}", appName,
590 SERVICE);
591
592 }
593
594 /**
595 * Returns jar path from bundle mvnLocationPath.
596 *
597 * @param mvnLocationPath mvnLocationPath of bundle
598 * @return path of jar
599 */
600 private String getJarPathFromBundleLocation(String mvnLocationPath,
601 String currentDirectory) {
602 String path = currentDirectory + SYSTEM;
603 String[] strArray = mvnLocationPath.split(MAVEN);
604 String[] split = strArray[1].split(File.separator);
605 String[] groupId = split[0].split(Pattern.quote(DELIMITER));
606
607 return path + groupId[0] + SLASH + groupId[1] + SLASH + split[1] +
608 SLASH + split[2] + SLASH + split[1] + HYPHEN + split[2];
609 }
610
611 /**
612 * Returns de-serializes YANG data-model nodes.
613 *
614 * @param serializedFileInfo serialized File Info
615 * @return de-serializes YANG data-model nodes
616 */
617 Set<YangSchemaNode> deSerializeDataModel(String serializedFileInfo) {
618
619 Set<YangSchemaNode> nodes = new HashSet<>();
620 Object readValue;
621 try {
622 FileInputStream fileInputStream =
623 new FileInputStream(serializedFileInfo);
624 ObjectInputStream objectInputStream =
625 new ObjectInputStream(fileInputStream);
626 readValue = objectInputStream.readObject();
627 if (readValue instanceof Set<?>) {
628 for (Object obj : (Set<?>) readValue) {
629 if (obj instanceof YangSchemaNode) {
630 nodes.add((YangSchemaNode) obj);
631 } else {
632 throw new RuntimeException(
633 "deserialize object is not an instance of " +
634 "YANG schema node" + obj);
635 }
636 }
637 } else {
638 throw new RuntimeException(
639 "deserialize object is not an instance of set of" +
640 "YANG schema node" + readValue);
641 }
642 objectInputStream.close();
643 fileInputStream.close();
644 } catch (IOException | ClassNotFoundException e) {
645 log.error(" {} not found.: {}", serializedFileInfo,
646 e.getLocalizedMessage());
647 }
648
649 return nodes;
650 }
651
652 /**
653 * Returns ysr app context.
654 *
655 * @return ysr app context
656 */
657 YsrAppContext ysrAppContext() {
658 return ysrAppContext;
659 }
660
661 /**
662 * Returns schema node based on the revision.
663 *
664 * @param name name of the schema node
665 * @return schema node based on the revision
666 */
667 private YangSchemaNode getSchemaNodeUsingSchemaNameWithRev(String name) {
668 YsrAppContext appContext;
669 YangSchemaNode schemaNode;
670 if (name.contains(AT)) {
671 String[] revArray = name.split(AT);
672 appContext = yangSchemaStore.get(revArray[0]);
673 schemaNode = appContext.getSchemaNodeForRevisionStore(name);
674 if (schemaNode != null) {
675 return schemaNode;
676 }
677 return appContext.curNode();
678 }
679 if (yangSchemaStore.containsKey(name)) {
680 appContext = yangSchemaStore.get(name);
681 if (appContext != null) {
682 Iterator<YangSchemaNode> iterator = appContext
683 .getYangSchemaNodeForRevisionStore().values()
684 .iterator();
685 if (iterator.hasNext()) {
686 return appContext.getYangSchemaNodeForRevisionStore()
687 .values().iterator().next();
688 } else {
689 return null;
690 }
691 }
692 }
693 log.error("{} not found.", name);
694 return null;
695 }
696
697 /**
698 * Adds schema node when different revision of node has received.
699 *
700 * @param schemaNode schema node
701 */
702 private void addSchemaNodeUsingSchemaNameWithRev(
703 YangSchemaNode schemaNode) {
704
705 String date = getDateInStringFormat(schemaNode);
706 String name = schemaNode.getName();
707 if (!date.equals(EMPTY_STRING)) {
708 name = name + AT + date;
709 }
710 //check if already present.
711 if (!yangSchemaStore.containsKey(schemaNode.getName())) {
712 ysrContextForSchemaStore.curNode(schemaNode);
713 //if revision is not present no need to add in revision store.
714 ysrContextForSchemaStore
715 .addSchemaNodeWithRevisionStore(name, schemaNode);
716 yangSchemaStore.put(schemaNode.getName(),
717 ysrContextForSchemaStore);
718 } else {
719 YsrAppContext appContext =
720 yangSchemaStore.get(schemaNode.getName());
721 appContext.addSchemaNodeWithRevisionStore(name, schemaNode);
722 appContext.curNode(schemaNode);
723 }
724 }
725
726 /**
727 * Returns date in string format.
728 *
729 * @param schemaNode schema node
730 * @return date in string format
731 */
732 String getDateInStringFormat(YangSchemaNode schemaNode) {
733 if (schemaNode != null) {
734 if (((YangNode) schemaNode).getRevision() != null) {
735 return new SimpleDateFormat(DATE_FORMAT)
736 .format(((YangNode) schemaNode).getRevision()
737 .getRevDate());
738 }
739 }
740 return EMPTY_STRING;
741 }
742
743 /**
744 * Removes schema node from schema map.
745 *
746 * @param removableNode schema node which needs to be removed
747 */
748 private void removeSchemaNode(YangSchemaNode removableNode) {
749
750 String name = removableNode.getName();
751 String date = getDateInStringFormat(removableNode);
752
753 if (!date.isEmpty()) {
754 name = removableNode.getName() + AT +
755 getDateInStringFormat(removableNode);
756 }
757 YsrAppContext appContext = yangSchemaStore
758 .get(removableNode.getName());
759 if (appContext != null &&
760 !appContext.getYangSchemaNodeForRevisionStore().isEmpty() &&
761 appContext.getYangSchemaNodeForRevisionStore().size() != 1) {
762 appContext.removeSchemaNodeForRevisionStore(name);
763 } else {
764 yangSchemaStore.remove(removableNode.getName());
765 }
766 }
767
768 /**
769 * Verifies if the manager object is already registered with notification
770 * handler.
771 *
772 * @param serviceClass service class
773 * @return true if the manager object is already registered with
774 * notification handler
775 */
776 boolean verifyNotificationObject(Class<?> serviceClass) {
777 YangSchemaNode schemaNode = null;
778 String serviceName = serviceClass.getName();
779 if (appObjectStore.containsKey(serviceName)) {
780 schemaNode = getYangSchemaNodeUsingAppName(serviceName);
781 } else if (yangSchemaStoreForRootInterface.containsKey(serviceName)) {
782 schemaNode =
783 getYangSchemaNodeUsingGeneratedRootNodeInterfaceFileName(
784 serviceName);
785 } else if (yangSchemaStoreForRootOpParam.containsKey(serviceName)) {
786 schemaNode = getYangSchemaNodeUsingGeneratedRootNodeOpPramFileName(
787 serviceName);
788 }
789
790 if (schemaNode != null) {
791 String name = getEventClassName(schemaNode);
792
793 YsrAppContext appContext =
794 yangRootSchemaStoreForNotification.get(name);
795 if (appContext != null && !appContext.isNotificationRegistered()) {
796 appContext.setNotificationRegistered(true);
797 return true;
798 }
799 }
800 return false;
801 }
802
803 /**
804 * Returns schema node's generated interface class name.
805 *
806 * @param schemaNode schema node
807 * @return schema node's generated interface class name
808 */
809 private String getInterfaceClassName(YangSchemaNode schemaNode) {
810 return schemaNode.getJavaPackage() + PERIOD +
811 getCapitalCase(schemaNode.getJavaClassNameOrBuiltInType());
812 }
813
814 /**
815 * Returns schema node's generated op param class name.
816 *
817 * @param schemaNode schema node
818 * @return schema node's generated op param class name
819 */
820 private String getOpParamClassName(YangSchemaNode schemaNode) {
821 return getInterfaceClassName(schemaNode) + OP_PARAM;
822 }
823
824 /**
825 * Returns schema node's generated op param class name.
826 *
827 * @param schemaNode schema node
828 * @return schema node's generated op param class name
829 */
830 private String getDefaultClassName(YangSchemaNode schemaNode) {
831 return schemaNode.getJavaPackage() + PERIOD + getCapitalCase(DEFAULT) +
832 getCapitalCase(schemaNode.getJavaClassNameOrBuiltInType());
833 }
834
835 /**
836 * Returns schema node's generated event class name.
837 *
838 * @param schemaNode schema node
839 * @return schema node's generated event class name
840 */
841 private String getEventClassName(YangSchemaNode schemaNode) {
842 return getInterfaceClassName(schemaNode).toLowerCase() + PERIOD +
843 getCapitalCase(schemaNode.getJavaClassNameOrBuiltInType()) +
844 EVENT_STRING;
845 }
846
847 /**
848 * Returns schema node's generated service class name.
849 *
850 * @param schemaNode schema node
851 * @return schema node's generated service class name
852 */
853 private String getServiceName(YangSchemaNode schemaNode) {
854 return getInterfaceClassName(schemaNode) + SERVICE;
855 }
856
857 /**
858 * Returns YSR application context for schema map.
859 *
860 * @return YSR application context for schema map
861 */
862 YsrAppContext ysrContextForSchemaStore() {
863 return ysrContextForSchemaStore;
864 }
865
866 /**
867 * Sets YSR application context for schema map.
868 *
869 * @param context YSR application context for
870 * schema map
871 */
872 void ysrContextForSchemaStore(YsrAppContext context) {
873 ysrContextForSchemaStore = context;
874 }
875
876 /**
877 * Returns YSR app context for application store.
878 *
879 * @return YSR app context for application store
880 */
881 YsrAppContext ysrContextForAppStore() {
882 return ysrContextForAppStore;
883 }
884
885 /**
886 * Retrieves schema node from the store and deletes jar file path.
887 *
888 * @param appName application name
889 * @param store YSR stores
890 * @param appObject applications object
891 * @return schema node from the store
892 */
893 private YangSchemaNode retrieveNodeForUnregister(
894 String appName,
895 ConcurrentMap<String, YsrAppContext> store, Object appObject) {
896
897 YsrAppContext curContext = store.get(appName);
898 boolean isValidObject;
899 if (curContext != null) {
900 isValidObject = verifyAppObject(appObject, curContext.appObject());
901 if (isValidObject) {
902 YangSchemaNode curNode = curContext.curNode();
903 //Delete all the generated ysr information in application's
904 // package.
905 removeYsrGeneratedTemporaryResources(curContext.jarPath(),
906 appName);
907 return curNode;
908 }
909 }
910 return null;
911 }
912
913 /**
914 * Verifies the application object which needs to be unregistered.
915 *
916 * @param appObject current received application object
917 * @param context stored application object
918 * @return true if objects are equal
919 */
920 private boolean verifyAppObject(Object appObject, Object context) {
921 if (appObject != null && context != null) {
922 return appObject.equals(context);
923 }
924 return appObject == null && context == null;
925 }
926
927 /**
928 * Removes YSR generated temporary resources.
929 *
930 * @param rscPath resource path
931 * @param appName application name
932 */
933 private void removeYsrGeneratedTemporaryResources(String rscPath,
934 String appName) {
935 if (rscPath != null) {
936 File jarPath = new File(rscPath);
937 if (jarPath.exists()) {
938 try {
939 deleteDirectory(jarPath);
940 } catch (IOException e) {
941 log.error("failed to delete ysr resources for {} : {}",
942 appName, e.getLocalizedMessage());
943 }
944 }
945 }
946 }
947
948 /**
949 * Removes from YANG schema store.
950 *
951 * @param curNode schema node
952 */
953 private void removeFromYangSchemaStore(YangSchemaNode curNode) {
954 removeSchemaNode(curNode);
955 }
956
957 /**
958 * Removes from YANG schema notification store.
959 *
960 * @param curNode schema node
961 */
962 private void removeFromYangNotificationStore(YangSchemaNode curNode) {
963 yangRootSchemaStoreForNotification
964 .remove(getEventClassName(curNode));
965 }
966
967 /**
968 * Removes from app store.
969 *
970 * @param appName application name
971 */
972 private void removeFromAppSchemaStore(String appName) {
973 appObjectStore.remove(appName);
974 }
975
976 /**
977 * Removes from interface store.
978 *
979 * @param appName application name
980 */
981 private void removeFromYangSchemaNodeForRootInterface(String appName) {
982 yangSchemaStoreForRootInterface.remove(appName);
983 }
984
985 /**
986 * Removes from op param store.
987 *
988 * @param appName application name
989 */
990 private void removeFromYangSchemaNodeForRootOpParam(String appName) {
991 yangSchemaStoreForRootOpParam.remove(appName + OP_PARAM);
992 }
993
994 /**
995 * Removes YANG file information from file store.
996 *
997 * @param schemaNode schema node
998 */
999 private void removeYangFileInfoFromStore(YangSchemaNode schemaNode) {
1000 yangFileStore.remove(getModuleIdentifier(schemaNode));
1001 }
1002
1003 /**
1004 * Verifies if class with given name exists.
1005 *
1006 * @param appName application name
1007 * @return true if class exists
1008 */
1009 boolean verifyClassExistence(String appName) {
1010 try {
1011 classLoader.loadClass(appName);
1012 return true;
1013 } catch (ClassNotFoundException e) {
1014 return false;
1015 }
1016 }
1017
1018 /**
1019 * Process notification registration for manager class object.
1020 *
1021 * @param yangService yang service
1022 * @param yangManager yang manager
1023 * @param ynhService notification extended service
1024 */
1025 private void processNotificationRegistration(
1026 Class<?> yangService, Object yangManager,
1027 YangNotificationExtendedService ynhService) {
1028
1029 if (yangManager != null && yangManager instanceof ListenerService) {
1030 if (verifyNotificationObject(yangService)) {
1031 ynhService.registerAsListener(
1032 (ListenerService) yangManager);
1033 }
1034 }
1035 }
1036
1037 /**
1038 * Clears database for YSR.
1039 */
1040 public void flushYsrData() {
1041 appObjectStore.clear();
1042 yangSchemaStore.clear();
1043 yangRootSchemaStoreForNotification.clear();
1044 yangSchemaStoreForRootOpParam.clear();
1045 yangSchemaStoreForRootInterface.clear();
1046 registerClassStore.clear();
1047 yangFileStore.clear();
1048 }
1049
1050 /**
1051 * Sets class loader of registered class.
1052 *
1053 * @param classLoader class loader of registered class
1054 */
1055 void setClassLoader(ClassLoader classLoader) {
1056 this.classLoader = classLoader;
1057 }
1058
1059 /**
1060 * Process module library for a registered service.
1061 *
1062 * @param node YANG schema nodes
1063 */
1064 private void processModuleLibrary(YangNode node) {
1065 YangModuleInformation moduleInformation =
1066 new DefaultYangModuleInformation(getModuleIdentifier(node),
1067 node.getNameSpace());
1068 addSubModuleIdentifier(node, (
1069 DefaultYangModuleInformation) moduleInformation);
1070 //TODO: add feature list to module information.
1071 ((DefaultYangModuleLibrary) library)
1072 .addModuleInformation(moduleInformation);
1073 }
1074
1075 /**
1076 * Adds sub module identifier.
1077 *
1078 * @param node schema node
1079 * @param information module information
1080 */
1081 private void addSubModuleIdentifier(
1082 YangSchemaNode node, DefaultYangModuleInformation information) {
1083 List<YangInclude> includeList = new ArrayList<>();
1084 if (node instanceof YangModule) {
1085 includeList = ((YangModule) node).getIncludeList();
1086 } else if (node instanceof YangSubModule) {
1087 includeList = ((YangSubModule) node).getIncludeList();
1088 }
1089 for (YangInclude include : includeList) {
1090 information.addSubModuleIdentifiers(getModuleIdentifier(
1091 include.getIncludedNode()));
1092 }
1093 }
1094
1095 /**
1096 * Returns module identifier for schema node.
1097 *
1098 * @param schemaNode schema node
1099 * @return module identifier for schema node
1100 */
1101 private YangModuleIdentifier getModuleIdentifier(
1102 YangSchemaNode schemaNode) {
1103 return new DefaultYangModuleIdentifier(
1104 schemaNode.getName(), getDateInStringFormat(schemaNode));
1105 }
1106
1107 /**
1108 * Returns module library.
1109 *
1110 * @return module library
1111 */
1112 public YangModuleLibrary getLibrary() {
1113 return library;
1114 }
1115
1116}