com.servoy.j2db.server.headlessclient.SolutionLoader.java Source code

Java tutorial

Introduction

Here is the source code for com.servoy.j2db.server.headlessclient.SolutionLoader.java

Source

/*
 This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
    
 This program is free software; you can redistribute it and/or modify it under
 the terms of the GNU Affero General Public License as published by the Free
 Software Foundation; either version 3 of the License, or (at your option) any
 later version.
    
 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
    
 You should have received a copy of the GNU Affero General Public License along
 with this program; if not, see http://www.gnu.org/licenses or write to the Free
 Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
 */
package com.servoy.j2db.server.headlessclient;

import java.rmi.RemoteException;
import java.util.Iterator;

import javax.servlet.http.HttpSession;

import org.apache.wicket.AbortException;
import org.apache.wicket.Page;
import org.apache.wicket.PageParameters;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.RestartResponseAtInterceptPageException;
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.Session;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.protocol.http.WebRequest;
import org.apache.wicket.protocol.http.WebResponse;
import org.apache.wicket.protocol.http.servlet.AbortWithWebErrorCodeException;
import org.apache.wicket.request.target.basic.RedirectRequestTarget;
import org.apache.wicket.request.target.coding.HybridUrlCodingStrategy;

import com.servoy.j2db.FormManager;
import com.servoy.j2db.IMainContainer;
import com.servoy.j2db.IWebClientApplication;
import com.servoy.j2db.Messages;
import com.servoy.j2db.persistence.Form;
import com.servoy.j2db.persistence.IRepository;
import com.servoy.j2db.persistence.Solution;
import com.servoy.j2db.persistence.SolutionMetaData;
import com.servoy.j2db.scripting.StartupArguments;
import com.servoy.j2db.server.headlessclient.MainPage.ShowUrlInfo;
import com.servoy.j2db.server.shared.ApplicationServerRegistry;
import com.servoy.j2db.util.Debug;
import com.servoy.j2db.util.Settings;
import com.servoy.j2db.util.Utils;

public class SolutionLoader extends WebPage {
    private static final long serialVersionUID = 1L;

    public SolutionLoader(PageParameters pp) {
        SolutionMetaData theReq = null;

        try {
            if (ApplicationServerRegistry.get().getDataServer().isInGlobalMaintenanceMode()
                    || ApplicationServerRegistry.get().getDataServer().isInServerMaintenanceMode()) {
                // do this before redirect & register client - where it is usually detected, because when clustered
                // this should result in a valid switch to another server in the cluster by the load balancer; if we wait until
                // after redirect, a page expired will happen on the other server

                //         throw new AbortWithHttpStatusException(HttpServletResponse.SC_SERVICE_UNAVAILABLE, false); this works, but doesn't show maintenance error page for non-clustered case

                Session.get().invalidate();
                RequestCycle.get().setRedirect(false);
                throw new RestartResponseException(new ServoyServerInMaintenanceMode());
            }
        } catch (RemoteException e) {
            // will not happen
            throw new RuntimeException(e);
        }

        FeedbackPanel feedback = new FeedbackPanel("feedback");
        add(feedback);

        StartupArguments argumentsScope = new StartupArguments(pp);

        String solutionName = argumentsScope.getSolutionName();
        String method = argumentsScope.getMethodName();
        String firstArgument = argumentsScope.getFirstArgument();

        try {
            IRepository repository = ApplicationServerRegistry.get().getLocalRepository();
            SolutionMetaData smd = (SolutionMetaData) repository.getRootObjectMetaData(solutionName,
                    IRepository.SOLUTIONS);
            if (smd == null || smd.getSolutionType() == SolutionMetaData.SOLUTION
                    || smd.getSolutionType() == SolutionMetaData.WEB_CLIENT_ONLY
                    || ((smd.getSolutionType() == SolutionMetaData.MOBILE
                            || smd.getSolutionType() == SolutionMetaData.MODULE)
                            && ApplicationServerRegistry.get().isDeveloperStartup())) {
                theReq = smd;
            } else {
                Debug.log("Not loading solution " + smd.getName() + ", it is not configured for webclient usage");
                theReq = null;
            }

            if (theReq != null) {
                Solution sol = (Solution) repository.getActiveRootObject(solutionName, IRepository.SOLUTIONS);
                if (sol.getLoginSolutionName() == null && sol.getLoginFormID() <= 0 && theReq.getMustAuthenticate()
                        && !((WebClientSession) getSession()).isSignedIn()) {
                    String authType = pp.getString("sv_auth_type"); //$NON-NLS-1$
                    boolean authorized = false;
                    if ((authType != null && authType.equals("basic")) || //$NON-NLS-1$
                            (authType == null && Utils.getAsBoolean(Settings.getInstance()
                                    .getProperty("servoy.webclient.basic.authentication", "false")))) //$NON-NLS-1$ //$NON-NLS-2$
                    {
                        String authorizationHeader = ((WebRequest) RequestCycle.get().getRequest())
                                .getHttpServletRequest().getHeader("Authorization"); //$NON-NLS-1$
                        if (authorizationHeader != null) {
                            String authorization = authorizationHeader.substring(6);
                            // TODO: which encoding to use? see http://tools.ietf.org/id/draft-reschke-basicauth-enc-05.xml
                            authorization = new String(Utils.decodeBASE64(authorization));
                            int index = authorization.indexOf(':');
                            if (index > 0) {
                                String username = authorization.substring(0, index);
                                String password = authorization.substring(index + 1);
                                authorized = ((WebClientSession) getSession()).authenticate(username, password);
                            }
                        }
                        if (!authorized) {
                            ((WebResponse) RequestCycle.get().getResponse()).getHttpServletResponse()
                                    .setHeader("WWW-Authenticate", "Basic realm=\"webclient\""); //$NON-NLS-1$ //$NON-NLS-2$
                            throw new AbortWithWebErrorCodeException(401);
                        }
                    }

                    if (!authorized) {
                        //signin first
                        throw new RestartResponseAtInterceptPageException(SignIn.class);
                    }
                }
                WebClientSession session;
                HttpSession httpSession;
                synchronized (sol) {
                    // create the http session
                    httpSession = ((WebRequest) RequestCycle.get().getRequest()).getHttpServletRequest()
                            .getSession();
                    Session.unset();
                    session = (WebClientSession) getSession();
                    session.bind();
                    session.getClientInfo();
                }
                synchronized (httpSession) {
                    IWebClientApplication sc = session.getWebClient();
                    if (sc != null && sc.getSolution() != null
                            && sc.getFlattenedSolution().getMainSolutionMetaData().getName().equals(solutionName)) {
                        // make sure it is registered as a start of a request.
                        session.getWebClient().onBeginRequest(session);
                        FormManager formManager = ((FormManager) sc.getFormManager());
                        String currentPageMapName = getPageMap().getName();
                        if (currentPageMapName != null && !Utils
                                .equalObjects(sc.getMainPage().getPageMap().getName(), currentPageMapName)) {
                            IMainContainer newContainer = formManager.getOrCreateMainContainer(currentPageMapName);
                            formManager.setCurrentContainer(newContainer, currentPageMapName);
                        }
                        // remove the method/argument from the page parameters, they shouldn't be used to generate a redirect url.
                        pp.remove("method"); //$NON-NLS-1$
                        pp.remove("m"); //$NON-NLS-1$
                        pp.remove("argument"); //$NON-NLS-1$
                        pp.remove("a"); //$NON-NLS-1$

                        // also remove client method arguments to avoid stackoverflow for deeplinked authenticate solutions (js_login called inside deeplinked method)
                        sc.handleArguments(null);
                        if (method != null) {
                            try {
                                sc.getScriptEngine().getScopesScope().executeGlobalFunction(null, method,
                                        (firstArgument == null ? null
                                                : new Object[] { firstArgument, argumentsScope.toJSMap() }),
                                        false, false);
                            } catch (Exception e1) {
                                sc.reportError(
                                        Messages.getString("servoy.formManager.error.ExecutingOpenSolutionMethod", //$NON-NLS-1$
                                                new Object[] { method }),
                                        e1);
                            }
                        }
                        if (formManager.getCurrentContainer().getController() == null) {
                            Iterator<Form> e = sc.getFlattenedSolution().getForms(true);
                            // add all forms first, they may be referred to in the login form
                            Form first = sc.getFlattenedSolution().getForm(sc.getSolution().getFirstFormID());
                            boolean formCanBeInstantiated = sc.getFlattenedSolution().formCanBeInstantiated(first);
                            while (!formCanBeInstantiated && e.hasNext()) {
                                Form form = e.next();
                                formCanBeInstantiated = sc.getFlattenedSolution().formCanBeInstantiated(form);
                                if (formCanBeInstantiated)
                                    first = form;
                            }
                            if (first != null) {
                                formManager.showFormInCurrentContainer(first.getName());
                            }
                        }

                    } else {
                        sc = session.startSessionClient(theReq, method, argumentsScope);
                    }
                    if (sc.isValid()) {
                        Page page = sc.getMainPage();
                        // do get it from the real wicket session so that a lock is set on this page. (or waited for the lock)
                        Page p = session.getPage(page.getPageMapName(), page.getId(),
                                page.getCurrentVersionNumber());
                        if (p instanceof MainPage) {
                            page = p;
                            ShowUrlInfo urlScript = ((MainPage) p).getShowUrlInfo();
                            if (urlScript != null && "_self".equals(urlScript.getTarget())) {
                                // a redirect was found to it self, just redirect directly to that one.
                                // clear the current main pages show url script first.
                                ((MainPage) p).getShowUrlScript();
                                RequestCycle.get().setRequestTarget(new RedirectRequestTarget(urlScript.getUrl()));
                                return;
                            }
                        }

                        HybridUrlCodingStrategy.setInitialPageParameters(page, pp);
                        setResponsePage(page);
                        setRedirect(true);
                        //setRedirect(Utils.getAsBoolean(sc.getSettings().getProperty("servoy.webclient.nice.urls", "false")));
                    }
                }
            }
        } catch (RestartResponseAtInterceptPageException restart) {
            setRedirect(false);
            throw restart;
        } catch (AbortException abort) {
            setRedirect(true);
            throw abort;
        } catch (Exception e) {
            Debug.error(e);
            error(e.toString());
        }
    }
}