org.j2free.servlet.EntityAdminServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.j2free.servlet.EntityAdminServlet.java

Source

/*
 * EntityAdminServlet.java
 *
 * Created on April 3, 2008, 1:07 AM
 *
 * Copyright (c) 2008 Foo Brew, Inc.
 *
 * 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.j2free.servlet;

import java.io.*;

import java.lang.reflect.Constructor;

import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import org.j2free.annotations.ServletConfig;
import org.j2free.admin.Marshaller;
import org.j2free.admin.MarshallingException;
import org.j2free.admin.ReflectionMarshaller;
import org.j2free.jpa.Controller;
import org.j2free.util.CharArrayWrapper;
import org.j2free.util.ServletUtils;

/**
 *
 * @author Ryan Wilson
 * @version
 */
@ServletConfig
public class EntityAdminServlet extends HttpServlet {
    private Log log = LogFactory.getLog(EntityAdminServlet.class);

    private TreeMap<String, Class> entityLookup;

    private static class Dispatch {
        private static final String ADMIN_JSP = "/WEB-INF/j2free/jsp/Admin.jsp";

        private static final String ENTITY_LIST = "/WEB-INF/j2free/jsp/EntityList.jsp";
        private static final String ENTITY_SELECTOR = "/WEB-INF/j2free/jsp/EntityBrowser.jsp";
        private static final String ENTITY_EDIT = "/WEB-INF/j2free/jsp/EntityEdit.jsp";
        private static final String ENTITY_INSPECT = "/WEB-INF/j2free/jsp/EntityInspect.jsp";
        private static final String ENTITY_CREATE = "/WEB-INF/j2free/jsp/EntityCreate.jsp";
    }

    /**
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String url = request.getRequestURL().toString();

        if (entityLookup == null) {
            entityLookup = new TreeMap<String, Class>();
            snoopEntities();
        }

        request.setAttribute("availableEntities", entityLookup.values());
        /*
                if (action.equalsIgnoreCase("create")) {
        action = ACTION_CREATE;
             
        try {
            Class klass = Class.forName(path[2]);
            Marshaller marshaller = Marshaller.getForClass(klass);
            request.setAttribute("fields",marshaller.marshallOut(null,true));
        } catch (Exception e) {
            // Handle error
        }
             
                } else if (action.equalsIgnoreCase("delete")) {
        action = ACTION_DELETE;
             
        try {
            Class klass = Class.forName(path[2]);
            data = pb.findPrimaryKey(klass,Integer.parseInt(path[3]));
        } catch (Exception e) {
            // Handle error
        }
             
                } else if (action.equalsIgnoreCase("edit")) {
        action = ACTION_EDIT;
             
        try {
            Class klass = Class.forName(path[2]);
            data = pb.findPrimaryKey(klass,Integer.parseInt(path[3]));
             
            log.debug(data);
             
            Marshaller marshaller = Marshaller.getForClass(klass);
            request.setAttribute("fields",marshaller.marshallOut(data,true));
            request.setAttribute("object",data);
             
        } catch (Exception e) {
            // Handle error
        }
             
                } else { }
         */

        request.getRequestDispatcher(Dispatch.ADMIN_JSP).forward(request, response);
    }

    /**
     *
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        Controller controller = Controller.get(); // Get the controller associated with the current thread;

        String uri = request.getRequestURI();
        uri = uri.replaceFirst(".*?/(list|find|inspect|create|save|update|delete)", "$1"); // chop off the part before what we care about
        String path[] = uri.split("/");

        log.debug(uri);
        log.debug("path.length = " + path.length);

        if (path.length < 1) {
            log.debug("too little path info " + uri);
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            return;
        }

        RequestDispatcher rd = null;

        if (path[0].equals("list")) {
            log.debug("in list");
            if (path.length < 2) {
                log.debug("too few parts for list");
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                return;
            }
            try {
                Class klass = entityLookup.get(path[1]);

                if (klass == null) {
                    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                    response.getWriter().println("Could not find class for entity type: " + path[1]);
                    return;
                }

                Marshaller marshaller = ReflectionMarshaller.getForClass(klass);

                int start = ServletUtils.getIntParameter(request, "start", 0);
                int limit = ServletUtils.getIntParameter(request, "limit", 100);

                List entities;
                if (path.length == 3) {
                    String[] stringIds = path[2].split(",");
                    Object[] ignoredIds = new Object[stringIds.length];

                    Class idType = marshaller.getIdType();

                    // NOTE: this will only work with integer entityIds
                    if (idType == Integer.class) {
                        for (int i = 0; i < stringIds.length; i++)
                            ignoredIds[i] = Integer.parseInt(stringIds[i]);
                    } else if (idType == String.class) {
                        for (int i = 0; i < stringIds.length; i++)
                            ignoredIds[i] = stringIds[i];
                    } else if (idType == Long.class) {
                        for (int i = 0; i < stringIds.length; i++)
                            ignoredIds[i] = Long.parseLong(stringIds[i]);
                    }

                    entities = controller.listByCriterions(klass, start, limit, Order.asc(marshaller.getIdName()),
                            Restrictions.not(Restrictions.in(marshaller.getIdName(), ignoredIds)));
                } else
                    entities = controller.listByCriterions(klass, start, limit, Order.asc(marshaller.getIdName()));

                TreeMap<String, Object> entityMap = new TreeMap<String, Object>();
                for (Object obj : entities) {
                    entityMap.put(marshaller.extractId(obj).toString(), obj);
                }

                request.setAttribute("start", start);
                request.setAttribute("limit", limit);

                request.setAttribute("total", controller.count(klass));

                request.setAttribute("simpleName", klass.getSimpleName());
                request.setAttribute("package", klass.getPackage().getName() + ".");
                request.setAttribute("entities", entityMap);

                if (ServletUtils.getBooleanParameter(request, "selector", false))
                    rd = request.getRequestDispatcher(Dispatch.ENTITY_SELECTOR);
                else
                    rd = request.getRequestDispatcher(Dispatch.ENTITY_LIST);

            } catch (Exception e) {
                log.error("Error listing entities", e);
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                return;
            }
        } else if (path[0].equals("find") || path[0].equals("inspect")) {
            log.debug("in find");
            if (path.length < 3) {
                log.debug("too few parts for find");
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                return;
            }
            try {
                Class klass = entityLookup.get(path[1]);

                if (klass == null) {
                    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                    response.getWriter().println("Could not find class for entity type: " + path[1]);
                    return;
                }

                Marshaller marshaller = ReflectionMarshaller.getForClass(klass);

                Object entity = controller.findPrimaryKey(klass, marshaller.asIdType(path[2]));
                request.setAttribute("entity", entity);
                request.setAttribute("entityId", marshaller.extractId(entity));
                request.setAttribute("fields", marshaller.marshallOut(entity, true));

                if (path[0].equals("find"))
                    rd = request.getRequestDispatcher(Dispatch.ENTITY_EDIT);
                else
                    rd = request.getRequestDispatcher(Dispatch.ENTITY_INSPECT);

            } catch (Exception e) {
                log.error("error finding entity", e);
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                return;
            }
        } else if (path[0].equals("create")) {
            log.debug("in create");
            if (path.length < 2) {
                log.debug("too few parts for create");
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                return;
            }
            try {
                Class klass = entityLookup.get(path[1]);

                if (klass == null) {
                    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                    response.getWriter().println("Could not find class for entity type: " + path[1]);
                    return;
                }

                Marshaller marshaller = ReflectionMarshaller.getForClass(klass);

                Constructor zeroArgsConst = klass.getConstructor();
                if (!zeroArgsConst.isAccessible())
                    zeroArgsConst.setAccessible(true);

                Object entity = zeroArgsConst.newInstance();
                request.setAttribute("simpleName", klass.getSimpleName());
                request.setAttribute("package", klass.getPackage().getName() + ".");
                request.setAttribute("fields", marshaller.marshallOut(entity, true));

                rd = request.getRequestDispatcher(Dispatch.ENTITY_CREATE);

            } catch (Exception e) {
                log.error("error creating entity", e);
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                return;
            }
        } else if (path[0].equals("save")) {
            log.debug("in save");

            if (path.length < 2) {
                log.debug("too few parts for save");
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                return;
            }

            Marshaller marshaller = null;

            try {
                Class klass = entityLookup.get(path[1]);

                if (klass == null) {
                    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                    response.getWriter().println("Could not find class for entity type: " + path[1]);
                    return;
                }

                marshaller = ReflectionMarshaller.getForClass(klass);

                Object entity = klass.newInstance();

                entity = marshaller.marshallIn(entity, request.getParameterMap(), controller);

                controller.persist(entity, true);

                if (controller.hasErrors()) {
                    response.getWriter().println(controller.getErrorsAsString("<br />", true));
                    return;
                } else {
                    response.setStatus(HttpServletResponse.SC_CREATED);

                    // need this to display dates in the DB stored format
                    entity = controller.findPrimaryKey(klass, marshaller.extractId(entity));

                    request.setAttribute("entity", entity);
                    request.setAttribute("entityId", marshaller.extractId(entity));
                    request.setAttribute("fields", marshaller.marshallOut(entity, true));

                    rd = request.getRequestDispatcher(Dispatch.ENTITY_EDIT);
                }

            } catch (MarshallingException e) {
                log.error("error saving entity", e);
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                response.getWriter().println(e.getMessage());
                return;
            } catch (Exception e) {
                log.error("error saving entity", e);
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                return;
            }

        } else if (path[0].equals("update")) {
            log.debug("in update");

            if (path.length < 3) {
                log.debug("too few parts for update");
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                return;
            }

            try {
                Class klass = entityLookup.get(path[1]);

                if (klass == null) {
                    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                    response.getWriter().println("Could not find class for entity type: " + path[1]);
                    return;
                }

                Marshaller marshaller = ReflectionMarshaller.getForClass(klass);

                Object entity = controller.findPrimaryKey(klass, marshaller.asIdType(path[2]));

                entity = marshaller.marshallIn(entity, request.getParameterMap(), controller);

                controller.merge(entity);

                if (controller.hasErrors()) {
                    response.getWriter().println(controller.getErrorsAsString("<br />", true));
                    return;
                } else {
                    response.setStatus(HttpServletResponse.SC_CREATED);

                    // need this to display dates in the DB stored format
                    entity = controller.findPrimaryKey(klass, marshaller.extractId(entity));

                    request.setAttribute("entity", entity);
                    request.setAttribute("entityId", marshaller.extractId(entity));
                    request.setAttribute("fields", marshaller.marshallOut(entity, true));

                    rd = request.getRequestDispatcher(Dispatch.ENTITY_EDIT);
                }

            } catch (MarshallingException e) {
                log.error("error saving entity", e);
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                response.getWriter().println(e.getMessage());
                return;
            } catch (Exception e) {
                log.error("error updating entity", e);
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                return;
            }

        } else if (path[0].equals("delete")) {

            log.debug("in delete");

            if (path.length < 3) {
                log.debug("too few parts for delete");
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                return;
            }

            try {
                Class klass = entityLookup.get(path[1]);

                if (klass == null) {
                    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                    response.getWriter().println("Could not find class for entity type: " + path[1]);
                    return;
                }

                Marshaller marshaller = ReflectionMarshaller.getForClass(klass);

                Object entity = controller.findPrimaryKey(klass, marshaller.asIdType(path[2]));

                controller.remove(entity);
                entity = null;
                controller.flush();

                if (controller.hasErrors()) {
                    response.getWriter().println(controller.getErrorsAsString("<br />", true));
                    return;
                } else {
                    response.setStatus(HttpServletResponse.SC_CREATED);
                    return;
                }

            } catch (Exception e) {
                log.error("error updating entity", e);
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
                return;
            }

        } else {
            log.debug("Don't know what to do!");
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            return;
        }

        CharArrayWrapper responseWrapper = new CharArrayWrapper((HttpServletResponse) response);
        rd.forward(request, responseWrapper);

        String responseString = responseWrapper.toString().replaceAll("\n", " ").replaceAll("\\s{2,}", " ")
                .replaceAll("> ", ">").replaceAll(" <", "<").replaceAll(" />", "/>");
        response.setContentLength(responseString.length());
        response.setContentType("text/javascript");

        PrintWriter out = response.getWriter();
        out.write(responseString);
        out.flush();
        out.close();
    }

    private void snoopEntities() {
        /* This would look up all loaded classes, then filter down to whatever
         * you want.  It's not the best way for this process, but still pretty
         * fucking cool.
        try {
        ClassLoader cl = EntityAdminServlet.class.getClassLoader();
        Class clClass  = cl.getClass();
        while (clClass != java.lang.ClassLoader.class) {
            clClass = clClass.getSuperclass();
        }
        Field clClassesField = clClass.getDeclaredField("classes");
        clClassesField.setAccessible(true);
        Vector classes = (Vector)clClassesField.get(cl);
             
        Class klass;
        for (Iterator itr = classes.iterator(); itr.hasNext();) {
            klass = (Class)itr.next();
            if (klass.isAnnotationPresent(Entity.class))
                availableEntities.add(klass);
        }
             
        } catch (Exception e) {
        log.error(e);
        }
         */

        Map metadata = Controller.get().getSession().getSessionFactory().getAllClassMetadata();

        for (Iterator itr = metadata.entrySet().iterator(); itr.hasNext();) {
            try {
                Map.Entry ent = (Map.Entry) itr.next();
                Class clazz = Class.forName((String) ent.getKey());
                entityLookup.put(clazz.getSimpleName(), clazz);
            } catch (Exception e) {
                log.warn("Could not load " + itr.next());
            }
        }
    }
}