|
@@ -18,9 +18,31 @@
|
|
|
|
|
|
package org.apache.ambari.server.view;
|
|
|
|
|
|
-import com.google.inject.AbstractModule;
|
|
|
-import com.google.inject.Guice;
|
|
|
-import com.google.inject.Injector;
|
|
|
+import java.beans.IntrospectionException;
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileInputStream;
|
|
|
+import java.io.FileNotFoundException;
|
|
|
+import java.io.FileOutputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.net.MalformedURLException;
|
|
|
+import java.net.URL;
|
|
|
+import java.net.URLClassLoader;
|
|
|
+import java.util.Collection;
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.Enumeration;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.HashSet;
|
|
|
+import java.util.LinkedList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Set;
|
|
|
+import java.util.jar.JarEntry;
|
|
|
+import java.util.jar.JarFile;
|
|
|
+
|
|
|
+import javax.xml.bind.JAXBContext;
|
|
|
+import javax.xml.bind.JAXBException;
|
|
|
+import javax.xml.bind.Unmarshaller;
|
|
|
|
|
|
import org.apache.ambari.server.api.resources.ResourceInstanceFactoryImpl;
|
|
|
import org.apache.ambari.server.api.resources.SubResourceDefinition;
|
|
@@ -31,6 +53,8 @@ import org.apache.ambari.server.configuration.Configuration;
|
|
|
import org.apache.ambari.server.controller.spi.Resource;
|
|
|
import org.apache.ambari.server.orm.dao.MemberDAO;
|
|
|
import org.apache.ambari.server.orm.dao.PrivilegeDAO;
|
|
|
+import org.apache.ambari.server.orm.dao.ResourceDAO;
|
|
|
+import org.apache.ambari.server.orm.dao.ResourceTypeDAO;
|
|
|
import org.apache.ambari.server.orm.dao.UserDAO;
|
|
|
import org.apache.ambari.server.orm.dao.ViewDAO;
|
|
|
import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
|
|
@@ -72,30 +96,9 @@ import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.security.core.GrantedAuthority;
|
|
|
|
|
|
-import javax.xml.bind.JAXBContext;
|
|
|
-import javax.xml.bind.JAXBException;
|
|
|
-import javax.xml.bind.Unmarshaller;
|
|
|
-
|
|
|
-import java.beans.IntrospectionException;
|
|
|
-import java.io.File;
|
|
|
-import java.io.FileNotFoundException;
|
|
|
-import java.io.FileOutputStream;
|
|
|
-import java.io.IOException;
|
|
|
-import java.io.InputStream;
|
|
|
-import java.net.MalformedURLException;
|
|
|
-import java.net.URL;
|
|
|
-import java.net.URLClassLoader;
|
|
|
-import java.util.Collection;
|
|
|
-import java.util.Collections;
|
|
|
-import java.util.Enumeration;
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.HashSet;
|
|
|
-import java.util.LinkedList;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
-import java.util.Set;
|
|
|
-import java.util.jar.JarEntry;
|
|
|
-import java.util.jar.JarFile;
|
|
|
+import com.google.inject.AbstractModule;
|
|
|
+import com.google.inject.Guice;
|
|
|
+import com.google.inject.Injector;
|
|
|
|
|
|
/**
|
|
|
* Registry for view and view instance definitions.
|
|
@@ -178,6 +181,15 @@ public class ViewRegistry {
|
|
|
*/
|
|
|
private static SecurityHelper securityHelper;
|
|
|
|
|
|
+ /**
|
|
|
+ * Resource data access object.
|
|
|
+ */
|
|
|
+ private static ResourceDAO resourceDAO;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Resource type data access object.
|
|
|
+ */
|
|
|
+ private static ResourceTypeDAO resourceTypeDAO;
|
|
|
|
|
|
// ----- Constructors ------------------------------------------------------
|
|
|
|
|
@@ -388,13 +400,17 @@ public class ViewRegistry {
|
|
|
// extract the archive and get the class loader
|
|
|
ClassLoader cl = extractViewArchive(archiveFile, helper.getFile(archivePath));
|
|
|
|
|
|
+ viewConfig = helper.getViewConfigFromExtractedArchive(archivePath);
|
|
|
+
|
|
|
ViewEntity viewDefinition = createViewDefinition(viewConfig, configuration, cl, archivePath);
|
|
|
|
|
|
Set<ViewInstanceEntity> instanceDefinitions = new HashSet<ViewInstanceEntity>();
|
|
|
|
|
|
for (InstanceConfig instanceConfig : viewConfig.getInstances()) {
|
|
|
try {
|
|
|
- instanceDefinitions.add(createViewInstanceDefinition(viewConfig, viewDefinition, instanceConfig));
|
|
|
+ ViewInstanceEntity instanceEntity = createViewInstanceDefinition(viewConfig, viewDefinition, instanceConfig);
|
|
|
+ instanceEntity.setXmlDriven(true);
|
|
|
+ instanceDefinitions.add(instanceEntity);
|
|
|
} catch (Exception e) {
|
|
|
LOG.error("Caught exception adding view instance for view " +
|
|
|
viewDefinition.getViewName(), e);
|
|
@@ -451,9 +467,11 @@ public class ViewRegistry {
|
|
|
}
|
|
|
instanceEntity.validate(viewEntity);
|
|
|
|
|
|
+ ResourceTypeEntity resourceTypeEntity = resourceTypeDAO.findByName(ViewEntity.getViewName(viewName, version));
|
|
|
// create an admin resource to represent this view instance
|
|
|
ResourceEntity resourceEntity = new ResourceEntity();
|
|
|
- resourceEntity.setResourceType(viewEntity.getResourceType());
|
|
|
+ resourceEntity.setResourceType(resourceTypeEntity);
|
|
|
+ resourceDAO.create(resourceEntity);
|
|
|
|
|
|
instanceEntity.setResource(resourceEntity);
|
|
|
|
|
@@ -467,6 +485,7 @@ public class ViewRegistry {
|
|
|
throw new IllegalStateException(message);
|
|
|
}
|
|
|
instanceEntity.setViewInstanceId(persistedInstance.getViewInstanceId());
|
|
|
+ instanceEntity.setResource(persistedInstance.getResource());
|
|
|
|
|
|
try {
|
|
|
// bind the view instance to a view
|
|
@@ -507,6 +526,9 @@ public class ViewRegistry {
|
|
|
ViewInstanceEntity entity = getInstanceDefinition(viewName, version, instanceName);
|
|
|
|
|
|
if (entity != null) {
|
|
|
+ if (entity.isXmlDriven()) {
|
|
|
+ throw new IllegalStateException("View instances defined via xml can't be updated through api requests");
|
|
|
+ }
|
|
|
if (LOG.isDebugEnabled()) {
|
|
|
LOG.debug("Updating view instance " + viewName + "/" +
|
|
|
version + "/" + instanceName);
|
|
@@ -542,8 +564,9 @@ public class ViewRegistry {
|
|
|
* Uninstall a view instance for the view with the given view name.
|
|
|
*
|
|
|
* @param instanceEntity the view instance entity
|
|
|
+ * @throws IllegalStateException if the given instance is not in a valid state
|
|
|
*/
|
|
|
- public void uninstallViewInstance(ViewInstanceEntity instanceEntity) {
|
|
|
+ public void uninstallViewInstance(ViewInstanceEntity instanceEntity) throws IllegalStateException {
|
|
|
ViewEntity viewEntity = getDefinition(instanceEntity.getViewName());
|
|
|
|
|
|
if (viewEntity != null) {
|
|
@@ -552,7 +575,9 @@ public class ViewRegistry {
|
|
|
String version = viewEntity.getVersion();
|
|
|
|
|
|
if (getInstanceDefinition(viewName, version, instanceName) != null) {
|
|
|
-
|
|
|
+ if (instanceEntity.isXmlDriven()) {
|
|
|
+ throw new IllegalStateException("View instances defined via xml can't be deleted through api requests");
|
|
|
+ }
|
|
|
if (LOG.isDebugEnabled()) {
|
|
|
LOG.debug("Deleting view instance " + viewName + "/" +
|
|
|
version + "/" +instanceName);
|
|
@@ -882,10 +907,6 @@ public class ViewRegistry {
|
|
|
|
|
|
setPersistenceEntities(viewInstanceDefinition);
|
|
|
|
|
|
- ResourceEntity resourceEntity = new ResourceEntity();
|
|
|
- resourceEntity.setResourceType(viewDefinition.getResourceType());
|
|
|
- viewInstanceDefinition.setResource(resourceEntity);
|
|
|
-
|
|
|
viewDefinition.addInstanceDefinition(viewInstanceDefinition);
|
|
|
}
|
|
|
|
|
@@ -983,13 +1004,28 @@ public class ViewRegistry {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // sync the given view with the db
|
|
|
+ /**
|
|
|
+ * Sync given view with data in DB. Ensures that view data in DB is updated,
|
|
|
+ * all instances changes from xml config are reflected to DB
|
|
|
+ *
|
|
|
+ * @param view view config from xml
|
|
|
+ * @param instanceDefinitions view instances from xml
|
|
|
+ * @throws Exception
|
|
|
+ */
|
|
|
private void syncView(ViewEntity view,
|
|
|
Set<ViewInstanceEntity> instanceDefinitions)
|
|
|
throws Exception {
|
|
|
-
|
|
|
String viewName = view.getName();
|
|
|
|
|
|
+ // get or create an admin resource type to represent this view
|
|
|
+ ResourceTypeEntity resourceTypeEntity = resourceTypeDAO.findByName(viewName);
|
|
|
+ if (resourceTypeEntity == null) {
|
|
|
+ resourceTypeEntity = new ResourceTypeEntity();
|
|
|
+ resourceTypeEntity.setName(view.getName());
|
|
|
+ resourceTypeDAO.create(resourceTypeEntity);
|
|
|
+ }
|
|
|
+ view.setResourceType(resourceTypeEntity);
|
|
|
+
|
|
|
ViewEntity persistedView = viewDAO.findByName(viewName);
|
|
|
|
|
|
// if the view is not yet persisted ...
|
|
@@ -997,13 +1033,31 @@ public class ViewRegistry {
|
|
|
if (LOG.isDebugEnabled()) {
|
|
|
LOG.debug("Creating View " + viewName + ".");
|
|
|
}
|
|
|
+
|
|
|
+ for( ViewInstanceEntity instance : view.getInstances()) {
|
|
|
+
|
|
|
+ // create an admin resource to represent this view instance
|
|
|
+ ResourceEntity resourceEntity = new ResourceEntity();
|
|
|
+ resourceEntity.setResourceType(resourceTypeEntity);
|
|
|
+ resourceDAO.create(resourceEntity);
|
|
|
+
|
|
|
+ instance.setResource(resourceEntity);
|
|
|
+ }
|
|
|
// ... merge it
|
|
|
- persistedView = viewDAO.merge(view);
|
|
|
+ viewDAO.merge(view);
|
|
|
+
|
|
|
+ persistedView = viewDAO.findByName(viewName);
|
|
|
+ if (persistedView == null) {
|
|
|
+ String message = "View " + viewName + " can not be found.";
|
|
|
+
|
|
|
+ LOG.error(message);
|
|
|
+ throw new IllegalStateException(message);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- Map<String, ViewInstanceEntity> instanceEntityMap = new HashMap<String, ViewInstanceEntity>();
|
|
|
+ Map<String, ViewInstanceEntity> xmlInstanceEntityMap = new HashMap<String, ViewInstanceEntity>();
|
|
|
for( ViewInstanceEntity instance : view.getInstances()) {
|
|
|
- instanceEntityMap.put(instance.getName(), instance);
|
|
|
+ xmlInstanceEntityMap.put(instance.getName(), instance);
|
|
|
}
|
|
|
|
|
|
view.setResourceType(persistedView.getResourceType());
|
|
@@ -1016,7 +1070,12 @@ public class ViewRegistry {
|
|
|
ViewInstanceEntity instance =
|
|
|
view.getInstanceDefinition(instanceName);
|
|
|
|
|
|
- instanceEntityMap.remove(instanceName);
|
|
|
+ if (persistedInstance.isXmlDriven() && !xmlInstanceEntityMap.containsKey(instanceName)) {
|
|
|
+ instanceDAO.remove(persistedInstance);
|
|
|
+ xmlInstanceEntityMap.remove(instanceName);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ xmlInstanceEntityMap.remove(instanceName);
|
|
|
|
|
|
// if the persisted instance is not in the registry ...
|
|
|
if (instance == null) {
|
|
@@ -1027,23 +1086,39 @@ public class ViewRegistry {
|
|
|
}
|
|
|
instance.setViewInstanceId(persistedInstance.getViewInstanceId());
|
|
|
|
|
|
- // apply the persisted overrides to the in-memory instance
|
|
|
- instance.setLabel(persistedInstance.getLabel());
|
|
|
- instance.setDescription(persistedInstance.getDescription());
|
|
|
- instance.setVisible(persistedInstance.isVisible());
|
|
|
- instance.setData(persistedInstance.getData());
|
|
|
- instance.setProperties(persistedInstance.getProperties());
|
|
|
- instance.setEntities(persistedInstance.getEntities());
|
|
|
+ if (instance.isXmlDriven()) {
|
|
|
+ // override db data with data from {@InstanceConfig}
|
|
|
+ persistedInstance.setLabel(instance.getLabel());
|
|
|
+ persistedInstance.setDescription(instance.getDescription());
|
|
|
+ persistedInstance.setVisible(instance.isVisible());
|
|
|
+ persistedInstance.setIcon(instance.getIcon());
|
|
|
+ persistedInstance.setIcon64(instance.getIcon64());
|
|
|
+ persistedInstance.setProperties(instance.getProperties());
|
|
|
+
|
|
|
+ instanceDAO.merge(persistedInstance);
|
|
|
+ } else {
|
|
|
+ // apply the persisted overrides to the in-memory instance
|
|
|
+ view.removeInstanceDefinition(instanceName);
|
|
|
+ view.addInstanceDefinition(persistedInstance);
|
|
|
+ }
|
|
|
|
|
|
instance.setResource(persistedInstance.getResource());
|
|
|
}
|
|
|
|
|
|
- // these instances appear in the archive but have been deleted
|
|
|
- // from the db... remove them from the registry
|
|
|
- for (ViewInstanceEntity instance : instanceEntityMap.values()) {
|
|
|
- view.removeInstanceDefinition(instance.getName());
|
|
|
- instanceDefinitions.remove(instance);
|
|
|
+ // these instances appear in the archive but not present in the db... add
|
|
|
+ // them to db and registry
|
|
|
+ for (ViewInstanceEntity instance : xmlInstanceEntityMap.values()) {
|
|
|
+ // create an admin resource to represent this view instance
|
|
|
+ ResourceEntity resourceEntity = new ResourceEntity();
|
|
|
+ resourceEntity.setResourceType(resourceTypeEntity);
|
|
|
+ resourceDAO.create(resourceEntity);
|
|
|
+ instance.setResource(resourceEntity);
|
|
|
+
|
|
|
+ instanceDAO.merge(instance);
|
|
|
+ bindViewInstance(view, instance);
|
|
|
+ instanceDefinitions.add(instance);
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
|
|
|
// ensure that the extracted view archive directory exists
|
|
@@ -1196,13 +1271,16 @@ public class ViewRegistry {
|
|
|
*/
|
|
|
public static void init(ViewDAO viewDAO, ViewInstanceDAO instanceDAO,
|
|
|
UserDAO userDAO, MemberDAO memberDAO, PrivilegeDAO privilegeDAO,
|
|
|
- SecurityHelper securityHelper) {
|
|
|
+ SecurityHelper securityHelper, ResourceDAO resourceDAO,
|
|
|
+ ResourceTypeDAO resourceTypeDAO) {
|
|
|
setViewDAO(viewDAO);
|
|
|
setInstanceDAO(instanceDAO);
|
|
|
setUserDAO(userDAO);
|
|
|
setMemberDAO(memberDAO);
|
|
|
setPrivilegeDAO(privilegeDAO);
|
|
|
setSecurityHelper(securityHelper);
|
|
|
+ setResourceDAO(resourceDAO);
|
|
|
+ setResourceTypeDAO(resourceTypeDAO);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1259,6 +1337,24 @@ public class ViewRegistry {
|
|
|
ViewRegistry.securityHelper = securityHelper;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Set the resource DAO.
|
|
|
+ *
|
|
|
+ * @param resourceDAO the resource DAO
|
|
|
+ */
|
|
|
+ protected static void setResourceDAO(ResourceDAO resourceDAO) {
|
|
|
+ ViewRegistry.resourceDAO = resourceDAO;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Set the resource type DAO.
|
|
|
+ *
|
|
|
+ * @param resourceTypeDAO the resource type DAO.
|
|
|
+ */
|
|
|
+ protected static void setResourceTypeDAO(ResourceTypeDAO resourceTypeDAO) {
|
|
|
+ ViewRegistry.resourceTypeDAO = resourceTypeDAO;
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
// ----- inner class : ViewRegistryHelper ----------------------------------
|
|
|
|
|
@@ -1285,6 +1381,26 @@ public class ViewRegistry {
|
|
|
return (ViewConfig) jaxbUnmarshaller.unmarshal(configStream);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Get the view configuration from the extracted archive file.
|
|
|
+ *
|
|
|
+ * @param archivePath path to extracted archive
|
|
|
+ *
|
|
|
+ * @return the associated view configuration
|
|
|
+ *
|
|
|
+ * @throws JAXBException if xml is malformed
|
|
|
+ * @throws FileNotFoundException if xml was not found
|
|
|
+ */
|
|
|
+ public ViewConfig getViewConfigFromExtractedArchive(String archivePath)
|
|
|
+ throws JAXBException, FileNotFoundException {
|
|
|
+
|
|
|
+ InputStream configStream = new FileInputStream(new File(archivePath + File.separator + VIEW_XML));
|
|
|
+ JAXBContext jaxbContext = JAXBContext.newInstance(ViewConfig.class);
|
|
|
+ Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
|
|
|
+
|
|
|
+ return (ViewConfig) jaxbUnmarshaller.unmarshal(configStream);
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Get a new file instance for the given path.
|
|
|
*
|