org.jboss.dashboard.workspace.GraphicElementManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.dashboard.workspace.GraphicElementManagerImpl.java

Source

/**
 * Copyright (C) 2012 Red Hat, Inc. and/or its affiliates.
 *
 * 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.
 */
package org.jboss.dashboard.workspace;

import org.jboss.dashboard.Application;
import org.jboss.dashboard.annotation.Priority;
import org.jboss.dashboard.annotation.Startable;
import org.jboss.dashboard.database.hibernate.HibernateTxFragment;
import org.jboss.dashboard.ui.NavigationManager;
import org.jboss.dashboard.ui.controller.RequestContext;
import org.jboss.dashboard.ui.resources.GraphicElement;
import org.hibernate.FlushMode;
import org.hibernate.Session;

import javax.inject.Inject;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public abstract class GraphicElementManagerImpl implements GraphicElementManager, Startable {
    private static transient org.slf4j.Logger log = org.slf4j.LoggerFactory
            .getLogger(GraphicElementManagerImpl.class.getName());

    protected Class classToHandle;
    protected String classToHandleName;
    protected String descriptorFileName;
    protected Properties defaultElementProperties;

    protected String baseDir;
    protected String elementsDir;
    protected List elements;
    protected List baseElements;

    @Inject
    private ResourceMappings mappings;

    public Priority getPriority() {
        return Priority.HIGH;
    }

    public void start() throws Exception {
        log.info("Starting " + getClass().getName());
        if (GraphicElement.class.isAssignableFrom(classToHandle)) {

            classToHandleName = classToHandle.getName();
            if (classToHandleName.indexOf('.') != -1) {
                classToHandleName = classToHandleName.substring(classToHandleName.lastIndexOf('.') + 1);
            }

            Field f = classToHandle.getDeclaredField("DESCRIPTOR_FILENAME");
            descriptorFileName = (String) f.get(null);
            f = classToHandle.getDeclaredField("DEFAULT_PROPERTIES");
            defaultElementProperties = (Properties) f.get(null);
        } else {
            throw new IllegalArgumentException(classToHandle + " is not subclass of " + GraphicElement.class);
        }

        elementsDir = mappings.getProperty(classToHandleName.toLowerCase());
        if (elementsDir == null) {
            throw new Exception("Property " + classToHandleName.toLowerCase() + " not found. Cannot load "
                    + classToHandleName.toLowerCase() + "s.");
        }

        loadDbElements();
        deployBaseElements();
        if (elements != null) {
            new HibernateTxFragment() {
                protected void txFragment(Session session) throws Exception {
                    for (Iterator iterator = elements.iterator(); iterator.hasNext();) {
                        GraphicElement graphicElement = (GraphicElement) iterator.next();
                        graphicElement.checkDeployment();
                        session.update(graphicElement);
                    }
                }
            }.execute();
        }
    }

    /**
     * Take all elements in DB, and load them
     */
    protected void loadDbElements() throws Exception {
        elements = new Vector();

        HibernateTxFragment txFragment = new HibernateTxFragment() {
            protected void txFragment(Session session) throws Exception {
                FlushMode oldFlushMode = session.getFlushMode();
                session.setFlushMode(FlushMode.NEVER);
                List dbItems = session.createQuery("from " + classToHandle.getName() + " as element").list();
                for (int i = 0; i < dbItems.size(); i++) {
                    GraphicElement element = (GraphicElement) dbItems.get(i);
                    //element.deploy();
                    log.debug("Loaded db item " + element.getId());
                    elements.add(element);
                }
                session.setFlushMode(oldFlushMode);
            }
        };

        txFragment.execute();
        Collections.sort(elements);
    }

    /**
     * Reads zipped elements in a directory and deploys them all.
     */
    protected void deployBaseElements() throws Exception {
        log.debug("Deploying elements in directory " + Application.lookup().getBaseAppDirectory() + File.separator
                + baseDir + ". Expecting type = " + classToHandleName);
        File dir = new File(Application.lookup().getBaseAppDirectory() + File.separator + baseDir);
        baseElements = new ArrayList();
        if (dir.exists()) {
            File[] elementZips = dir.listFiles(new FilenameFilter() {
                public boolean accept(File dir, String name) {
                    return (name.endsWith(".zip"));
                }
            });
            for (int i = 0; elementZips != null && i < elementZips.length; i++) {
                final File elementZip = elementZips[i];
                final String elementName = elementZip.getName().substring(0, elementZip.getName().length() - 4);
                baseElements.add(elementName);
                HibernateTxFragment fragment = new HibernateTxFragment(true) {
                    public void txFragment(Session session) throws Exception {
                        deployZippedElement(elementZip, elementName);//Global for all workspaces.
                    }
                };
                fragment.execute();
            }
        }
    }

    /**
     * Deploys an element (zip file). Deployment consists in creating or updating it in database
     */
    protected void deployZippedElement(File zipFile, String elementId) throws Exception {
        log.debug("Deploying " + classToHandleName + " " + zipFile);
        final GraphicElement existingElement = getElement(elementId, null, null, null);
        log.debug("Existing element with id " + elementId + " = " + existingElement);
        if (existingElement != null) {
            log.debug("Updating file " + zipFile + ". (Already deployed in db)");
            existingElement.setZipFile(zipFile);
            existingElement.setLastModified(new Date());
        } else {
            log.info("Deploying to database " + classToHandleName + " " + zipFile);
            Constructor c = classToHandle.getConstructor(new Class[] { String.class, File.class });
            final GraphicElement element = (GraphicElement) c.newInstance(new Object[] { elementId, zipFile });

            HibernateTxFragment txFragment = new HibernateTxFragment() {
                protected void txFragment(Session session) throws Exception {
                    element.setLastModified(new Date());
                    session.save(element);
                }
            };

            txFragment.execute();
            elements.add(element);
            Collections.sort(elements);
        }
    }

    /**
     * Returns all elements installed in the system
     */
    public GraphicElement[] getElements() {
        //Collections.sort(elements);
        GraphicElement[] elementsArray = (GraphicElement[]) elements.toArray(new GraphicElement[elements.size()]);
        //Arrays.sort(elementsArray);
        return elementsArray;
    }

    /**
     * Return all elements belonging to given workspace
     *
     * @param workspaceId Set to null to indicate elements that apply to all workspaces.
     */
    public GraphicElement[] getElements(String workspaceId) {
        List l = new ArrayList();
        GraphicElement[] sortedElements = getElements();
        for (int i = 0; i < sortedElements.length; i++) {
            GraphicElement element = (GraphicElement) sortedElements[i];
            if (hasSameValue(element.getWorkspaceId(), workspaceId))
                l.add(element);
        }
        log.debug("Elements with workspace=" + workspaceId + ": " + l.size());
        return (GraphicElement[]) l.toArray(new GraphicElement[l.size()]);
    }

    /**
     * Return all elements belonging to given workspace and section
     *
     * @param workspaceId  Set to null to indicate elements that apply to all workspaces.
     * @param sectionId Set to null to indicate elements that apply to all sections.
     */
    public GraphicElement[] getElements(String workspaceId, Long sectionId) {
        List l = new ArrayList();
        GraphicElement[] sortedElements = getElements(workspaceId);
        for (int i = 0; i < sortedElements.length; i++) {
            GraphicElement element = (GraphicElement) sortedElements[i];
            if (hasSameValue(element.getSectionId(), sectionId))
                l.add(element);
        }
        log.debug("Elements with workspace=" + workspaceId + ", section=" + sectionId + ": " + l.size());
        return (GraphicElement[]) l.toArray(new GraphicElement[l.size()]);
    }

    /**
     * Return all elements belonging to given workspace and section
     *
     * @param workspaceId  Set to null to indicate elements that apply to all workspaces.
     * @param sectionId Set to null to indicate elements that apply to all sections.
     * @param panelId Set to null to indicate elements that apply to all panel instances.
     */
    public GraphicElement[] getElements(String workspaceId, Long sectionId, Long panelId) {
        List l = new ArrayList();
        GraphicElement[] sortedElements = getElements(workspaceId, sectionId);
        for (int i = 0; i < sortedElements.length; i++) {
            GraphicElement element = (GraphicElement) sortedElements[i];
            if (hasSameValue(element.getPanelId(), panelId))
                l.add(element);
        }
        log.debug("Elements with workspace=" + workspaceId + ", section=" + sectionId + ", panel=" + panelId + ": "
                + l.size());
        return (GraphicElement[]) l.toArray(new GraphicElement[l.size()]);
    }

    /**
     * Get the elements visible for a given context. These are the base elements plus the workspace, section and panel
     * elements. But hierarchy applies: Panel elements may hide section ones, workspace ones and global ones.
     * Assume current workspace, section and panel.
     */
    public GraphicElement[] getAvailableElements() {
        Workspace workspace = NavigationManager.lookup().getCurrentWorkspace();
        Section section = NavigationManager.lookup().getCurrentSection();
        Panel panel = RequestContext.lookup().getActivePanel();
        Long idPanel = null;
        if (panel != null && section != null) {
            idPanel = panel.getPanelId();
            if (getElementScopeDescriptor().isAllowedInstance()) {
                idPanel = panel.getInstanceId();
            }
        }
        return getAvailableElements(workspace == null ? null : workspace.getId(),
                section == null ? null : section.getId(), panel == null ? null : idPanel);
    }

    /**
     * Get the elements visible for a given context. These are the base elements plus the workspace, section and panel
     * elements. But hierarchy applies: Panel elements may hide section ones, workspace ones and global ones.
     */
    public GraphicElement[] getAvailableElements(String workspaceId, Long sectionId, Long panelId) {
        log.debug(
                "Getting available elements in context (" + workspaceId + ", " + sectionId + ", " + panelId + ")");
        List elementsToReturn = new ArrayList();
        Set elementIds = new HashSet();
        GraphicElement[] panelElements = getElements(workspaceId, sectionId, panelId);
        for (int i = 0; i < panelElements.length; i++) {
            GraphicElement element = panelElements[i];
            elementsToReturn.add(element);
            elementIds.add(element.getId());
        }
        GraphicElement[] sectionElements = getElements(workspaceId, sectionId, null);
        for (int i = 0; i < sectionElements.length; i++) {
            GraphicElement element = sectionElements[i];
            if (elementIds.contains(element.getId()))
                continue;
            elementsToReturn.add(element);
            elementIds.add(element.getId());
        }
        GraphicElement[] instanceElements = getElements(workspaceId, null, panelId);
        for (int i = 0; i < instanceElements.length; i++) {
            GraphicElement element = instanceElements[i];
            if (elementIds.contains(element.getId()))
                continue;
            elementsToReturn.add(element);
            elementIds.add(element.getId());
        }
        GraphicElement[] workspaceElements = getElements(workspaceId, null, null);
        for (int i = 0; i < workspaceElements.length; i++) {
            GraphicElement element = workspaceElements[i];
            if (elementIds.contains(element.getId()))
                continue;
            elementsToReturn.add(element);
            elementIds.add(element.getId());
        }
        GraphicElement[] globalElements = getElements(null);
        for (int i = 0; i < globalElements.length; i++) {
            GraphicElement element = globalElements[i];
            if (elementIds.contains(element.getId()))
                continue;
            elementsToReturn.add(element);
            elementIds.add(element.getId());
        }

        GraphicElement[] elementsArray = (GraphicElement[]) elementsToReturn.toArray(new GraphicElement[] {});
        Arrays.sort(elementsArray);
        if (log.isDebugEnabled()) {
            ArrayList l = new ArrayList();
            for (int i = 0; i < elementsArray.length; i++) {
                GraphicElement element = elementsArray[i];
                l.add(element.getDbid());
            }
            log.debug("Got available elements in context (" + workspaceId + ", " + sectionId + ", " + panelId
                    + "): " + l);
        }
        return elementsArray;
    }

    /**
     * Get the elements manageable for a given context. These are the base elements plus the workspace, section and panel
     * elements. Assume current workspace, section and panel.
     */
    public GraphicElement[] getManageableElements() {
        Workspace workspace = NavigationManager.lookup().getCurrentWorkspace();
        Section section = NavigationManager.lookup().getCurrentSection();
        Panel panel = RequestContext.lookup().getActivePanel();
        return getManageableElements(workspace == null ? null : workspace.getId(),
                section == null ? null : section.getId(), panel == null ? null : panel.getPanelId());
    }

    /**
     * Get the elements visible for a given context.
     * These are the base elements plus the workspace, section and panel elements.
     */
    public GraphicElement[] getManageableElements(String workspaceId, Long sectionId, Long panelId) {
        List elementsToReturn = new ArrayList();

        if (workspaceId == null && sectionId == null & panelId == null) {
            elementsToReturn.addAll(Arrays.asList(getElements()));//All elements in system
        } else if (workspaceId != null && sectionId == null & panelId == null) {
            GraphicElement[] workspaceGlobalElements = getElements(workspaceId, null, null);
            Set usedIds = new HashSet();
            //Workspace global elements
            for (int i = 0; i < workspaceGlobalElements.length; i++) {
                GraphicElement element = workspaceGlobalElements[i];
                usedIds.add(element.getId());
                elementsToReturn.add(element);
            }
            //Global elements with different id
            GraphicElement[] globalElements = getElements(null);
            for (int i = 0; i < globalElements.length; i++) {
                GraphicElement element = globalElements[i];
                if (usedIds.contains(element.getId()))
                    continue;
                elementsToReturn.add(element);
            }
            //Workspace non-global elements
            GraphicElement[] workspaceElements = getElements(workspaceId);
            for (int i = 0; i < workspaceElements.length; i++) {
                GraphicElement element = workspaceElements[i];
                if (element.getSectionId() == null && element.getPanelId() == null)
                    continue;
                usedIds.add(element.getId());
                elementsToReturn.add(element);
            }
        } else if (workspaceId != null && sectionId != null & panelId == null) {
            //All elements defined for this section, plus workspace base elements, plus base elements with different id.
            Set usedIds = new HashSet();
            GraphicElement[] sectionElements = getElements(workspaceId, sectionId);
            for (int i = 0; i < sectionElements.length; i++) {
                GraphicElement element = sectionElements[i];
                usedIds.add(element.getId());
                elementsToReturn.add(element);
            }
            GraphicElement[] workspaceElements = getElements(workspaceId, null, null);
            for (int i = 0; i < workspaceElements.length; i++) {
                GraphicElement element = workspaceElements[i];
                if (usedIds.contains(element.getId()))
                    continue;
                usedIds.add(element.getId());
                elementsToReturn.add(element);
            }
            GraphicElement[] globalElements = getElements(null);
            for (int i = 0; i < globalElements.length; i++) {
                GraphicElement element = globalElements[i];
                if (usedIds.contains(element.getId()))
                    continue;
                usedIds.add(element.getId());
                elementsToReturn.add(element);
            }
        } else if (workspaceId != null && sectionId != null & panelId != null) {
            //All elements defined for this panel, plus workspace base elements, plus base elements with different id.
            Set usedIds = new HashSet();

            GraphicElement[] panelElements = getElements(workspaceId, sectionId, panelId);
            for (int i = 0; i < panelElements.length; i++) {
                GraphicElement element = panelElements[i];
                usedIds.add(element.getId());
                elementsToReturn.add(element);
            }
            GraphicElement[] sectionElements = getElements(workspaceId, sectionId, null);
            for (int i = 0; i < sectionElements.length; i++) {
                GraphicElement element = sectionElements[i];
                if (usedIds.contains(element.getId()))
                    continue;
                usedIds.add(element.getId());
                elementsToReturn.add(element);
            }
            GraphicElement[] instanceElements = getElements(workspaceId, null, panelId);
            for (int i = 0; i < instanceElements.length; i++) {
                GraphicElement element = instanceElements[i];
                if (usedIds.contains(element.getId()))
                    continue;
                usedIds.add(element.getId());
                elementsToReturn.add(element);
            }
            GraphicElement[] workspaceElements = getElements(workspaceId, null, null);
            for (int i = 0; i < workspaceElements.length; i++) {
                GraphicElement element = workspaceElements[i];
                if (usedIds.contains(element.getId()))
                    continue;
                usedIds.add(element.getId());
                elementsToReturn.add(element);
            }
            GraphicElement[] globalElements = getElements(null);
            for (int i = 0; i < globalElements.length; i++) {
                GraphicElement element = globalElements[i];
                if (usedIds.contains(element.getId()))
                    continue;
                usedIds.add(element.getId());
                elementsToReturn.add(element);
            }
        }

        GraphicElement[] elementsArray = (GraphicElement[]) elementsToReturn.toArray(new GraphicElement[] {});
        Arrays.sort(elementsArray);
        return elementsArray;
    }

    /**
     * Get an element visible for a given context. These are the base elements plus the workspace, section and panel
     * elements. But hierarchy applies: Panel elements may hide section ones, workspace ones and global ones.
     * Assume current workspace, section and panel.
     */
    public GraphicElement getAvailableElement(String id) {
        GraphicElement[] elements = getAvailableElements();
        for (int i = 0; i < elements.length; i++) {
            GraphicElement element = elements[i];
            if (element.getId().equals(id))
                return element;
        }
        return null;
    }

    /**
     * Get an element by dbid.
     */
    public GraphicElement getElementByDbid(String dbid) {
        for (int i = 0; i < elements.size(); i++) {
            GraphicElement element = (GraphicElement) elements.get(i);
            if (element.getDbid().toString().equals(dbid))
                return element;
        }
        return null;
    }

    /**
     * Returns an element by its id and context.
     */
    public GraphicElement getElement(String id, String workspaceId, Long sectionId, Long panelId) {
        GraphicElement[] contextElements = getElements(workspaceId, sectionId, panelId);
        for (int i = 0; i < contextElements.length; i++) {
            GraphicElement element = contextElements[i];
            if (element.getId().equals(id))
                return element;
        }
        return null;
    }

    /**
     * Returns the default element, that is, the one whose id is 'default' and workspace is null.
     */
    public GraphicElement getDefaultElement() {
        return getElement(getDefaultResourceId(), null, null, null);
    }

    protected String getDefaultResourceId() {
        return "Default_" + classToHandleName;
    }

    /**
     * Determines if given element is a base element. These elements are special,
     * as they hold a main copy on HD, and are copied to DB on startup. That's why they can't be edited
     * in admin pages, because the HD copy is intended not to be modified in any way.
     */
    public boolean isBaseElement(GraphicElement element) {
        if (!classToHandle.isAssignableFrom(element.getClass()))
            throw new IllegalArgumentException(
                    "Class not compatible with " + classToHandle + ": " + element.getClass());
        return element.getWorkspaceId() == null && element.getSectionId() == null && element.getPanelId() == null
                && baseElements != null && baseElements.contains(element.getId());
    }

    /**
     * @return the base directory for elements, once deployed, starting in /www/htdocs/.
     */
    public String getElementsDir() {
        return elementsDir;
    }

    /**
     * Create or update existing element
     */
    public void createOrUpdate(GraphicElement element) throws Exception {
        if (!classToHandle.isAssignableFrom(element.getClass()))
            throw new IllegalArgumentException(
                    "Class not compatible with " + classToHandle + ": " + element.getClass());

        final GraphicElement elementToUse;
        GraphicElement existingElement = getElement(element.getId(), element.getWorkspaceId(),
                element.getSectionId(), element.getPanelId());
        if (existingElement != null) {
            elementToUse = existingElement;
            if (isBaseElement(existingElement)) {
                log.error("Cannot replace data for a base element.");
                return;
            }
            elementToUse.setZipFile(element.getZipFile());
        } else {
            elementToUse = element;
            elements.add(element);
        }

        new HibernateTxFragment() {
            protected void txFragment(Session session) throws Exception {
                elementToUse.setLastModified(new Date());
                session.saveOrUpdate(elementToUse);
            }
        }.execute();
        Collections.sort(elements);
    }

    /**
     * Delete existing element
     */
    public void delete(final GraphicElement element) {
        if (!classToHandle.isAssignableFrom(element.getClass()))
            throw new IllegalArgumentException(
                    "Class not compatible with " + classToHandle + ": " + element.getClass());
        log.debug("Deleting element with dbid = " + element.getDbid());
        elements.remove(element);
        Collections.sort(elements);
        element.clearDeploymentFiles();

        try {
            new HibernateTxFragment() {
                protected void txFragment(Session session) throws Exception {
                    session.delete(element);
                }
            }.execute();
        } catch (Exception e) {
            log.error("Error deleting element.", e);
        }
    }

    private boolean hasSameValue(Object o1, Object o2) {
        if (o1 == null && o2 == null)
            return true;
        else if (o1 == null)
            return false;
        else if (o2 == null)
            return false;
        else
            return o1.equals(o2);
    }

    public synchronized void addFileToResource(final String name, final File file, final GraphicElement element,
            final String descriptorFileName) throws Exception {
        byte[] zipFile = element.getZipFile();
        byte[] buffer = new byte[65536];

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ZipOutputStream zos = new ZipOutputStream(bos);

        ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipFile));
        ZipEntry entry = null;
        while ((entry = zis.getNextEntry()) != null) {
            String entryName = entry.getName();
            if (entryName.equals(descriptorFileName)) {
                Properties props = new Properties();
                props.load(zis);
                props.setProperty("resource." + name, name);
                zos.putNextEntry(new ZipEntry(entryName));
                props.store(zos, "");
                zos.closeEntry();
            } else if (entryName.equals(name)) {
                throw new Exception("Duplicated entry name: " + name);
            } else {
                zos.putNextEntry(new ZipEntry(entryName));
                int len = 0;
                while ((len = zis.read(buffer)) != -1) {
                    zos.write(buffer, 0, len);
                }
                zos.closeEntry();
            }
        }

        InputStream in = new BufferedInputStream(new FileInputStream(file));
        zos.putNextEntry(new ZipEntry(name));
        int len = 0;
        while ((len = in.read(buffer)) != -1) {
            zos.write(buffer, 0, len);
        }
        zos.closeEntry();
        zos.close();
        element.setZipFile(bos.toByteArray());
        createOrUpdate(element);
    }
}