/*
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.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Locale;
import javax.servlet.ServletContext;
import org.apache.wicket.Session;
import org.apache.wicket.util.resource.AbstractStringResourceStream;
import org.apache.wicket.util.resource.IResourceStream;
import org.apache.wicket.util.resource.UrlResourceStream;
import org.apache.wicket.util.resource.locator.IResourceStreamLocator;
import org.apache.wicket.util.resource.locator.ResourceStreamLocator;
import org.apache.wicket.util.time.Time;
import com.servoy.j2db.FlattenedSolution;
import com.servoy.j2db.FormController;
import com.servoy.j2db.IForm;
import com.servoy.j2db.IServiceProvider;
import com.servoy.j2db.persistence.Form;
import com.servoy.j2db.persistence.IRepository;
import com.servoy.j2db.persistence.RootObjectMetaData;
import com.servoy.j2db.persistence.Solution;
import com.servoy.j2db.server.headlessclient.dataui.TemplateGenerator;
import com.servoy.j2db.server.shared.ApplicationServerRegistry;
import com.servoy.j2db.server.shared.IApplicationServerSingleton;
import com.servoy.j2db.util.Debug;
import com.servoy.j2db.util.Pair;
/**
* Serves the static resources and templates
*
* @author jcompagner
*/
public final class ServoyResourceStreamLocator implements IResourceStreamLocator
{
public static final String[] editablePages = { "SelectSolution", "MainPage", "SignIn", "ServoyExpiredPage", "ServoyServerToBusyPage", "UnsupportedBrowserPage" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
private final IResourceStreamLocator classLoaderResourceStreamLocator = new ResourceStreamLocator();
private final IResourceStreamLocator templateResourceStreamLocator = new ResourceStreamLocator()
{
@Override
public IResourceStream locate(Class< ? > clazz, String pathname)
{
if (clazz == ServoyPageExpiredPage.class || clazz == ServoyErrorPage.class)
{
try
{
URL url = context.getResource("/servoy-webclient/templates/default/" + pathname); //$NON-NLS-1$
if (url != null)
{
return new NullUrlResourceStream(url)
{
private static final long serialVersionUID = 1L;
@Override
public Time lastModifiedTime()
{
return Time.now();
}
};
}
}
catch (MalformedURLException ex)
{
Debug.trace("Load failed for " + pathname + " (ignored, getting default)"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
else if (pathname.startsWith("com/servoy/j2db/server/headlessclient/WebForm_")) //$NON-NLS-1$
{
int index = pathname.indexOf("form::"); //$NON-NLS-1$
if (index != -1)
{
int index2 = pathname.indexOf("::form", index + 6); //$NON-NLS-1$
try
{
String solutionAndForm = pathname.substring(index + 6, index2);
solutionAndForm = solutionAndForm.replace(':', '/');
String templateDir = pathname.substring(index2 + 7);
int index3 = templateDir.indexOf("$");//this is a bit strange, but the most easy way //$NON-NLS-1$
if (index3 != -1) templateDir = templateDir.substring(0, index3);
final String fullpath = "/servoy-webclient/templates/" + templateDir + "/" + solutionAndForm + ".html"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
URL url = context.getResource(fullpath);
if (url != null)
{
return new NullUrlResourceStream(url);
}
String[] names = solutionAndForm.split("/"); //$NON-NLS-1$
if (names != null && names.length == 2)
{
try
{
IApplicationServerSingleton as = ApplicationServerRegistry.get();
RootObjectMetaData sd = as.getLocalRepository().getRootObjectMetaData(names[0], IRepository.SOLUTIONS);
if (sd != null)
{
Solution sol = (Solution)as.getLocalRepository().getActiveRootObject(sd.getRootObjectId());
IServiceProvider sp = null;
Form form = null;
if (Session.exists())
{
sp = ((WebClientSession)Session.get()).getWebClient();
if (sp != null)
{
IForm fc = ((WebClient)sp).getFormManager().getForm(names[1]);
if (fc instanceof FormController)
{
FlattenedSolution clientSolution = sp.getFlattenedSolution();
form = clientSolution.getForm(((FormController)fc).getForm().getName());
}
}
}
if (form == null)
{
form = sol.getForm(names[1]);
}
if (form != null)
{
Pair<String, String> pair = TemplateGenerator.getFormHTMLAndCSS(sol, form, sp, names[1]);
String html = pair.getLeft();
return new TemplateResourceStream(html, sd.getRootObjectId(), fullpath);
}
else
{
Debug.error("No form found for " + names[1] + " of solution " + names[0]); //$NON-NLS-1$ //$NON-NLS-2$
}
}
else
{
Debug.error("No solution found for " + names[0]); //$NON-NLS-1$
}
}
catch (Exception ex)
{
Debug.error("No solution and form found from " + solutionAndForm, ex); //$NON-NLS-1$
}
}
else
{
Debug.error("No solution and form found from " + solutionAndForm); //$NON-NLS-1$
}
}
catch (MalformedURLException ex)
{
Debug.error(ex);
}
}
}
else if (testIfEditablePage(pathname))
{
String name = pathname.substring("com/servoy/j2db/server/headlessclient/".length()); //$NON-NLS-1$
try
{
URL url = context.getResource("/servoy-webclient/templates/default/" + name); //$NON-NLS-1$
if (url != null)
{
return new NullUrlResourceStream(url);
}
}
catch (MalformedURLException ex)
{
Debug.trace("Load failed for " + name + " (ignored, getting default)"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
return null;
}
};
private final ServletContext context;
private boolean testIfEditablePage(String pathname)
{
for (String element : editablePages)
{
if (pathname.startsWith("com/servoy/j2db/server/headlessclient/" + element)) //$NON-NLS-1$
{
return true;
}
}
return false;
}
/**
* Constructor
*
* @param finder The finder to search
*/
public ServoyResourceStreamLocator(WebClientsApplication application)
{
super();
this.context = application.getWicketFilter().getFilterConfig().getServletContext();
}
/**
* @see wicket.util.resource.locator.IResourceStreamLocator#locate(java.lang.Class, java.lang.String, java.lang.String, java.util.Locale, java.lang.String)
*/
public IResourceStream locate(Class< ? > clazz, String path, String style, Locale locale, String extension)
{
IResourceStream stream = templateResourceStreamLocator.locate(clazz, path, style, locale, extension);
if (stream == null)
{
return classLoaderResourceStreamLocator.locate(clazz, path, style, locale, extension);
}
return stream;
}
/**
* @see wicket.util.resource.locator.IResourceStreamLocator#locate(java.lang.Class, java.lang.String)
*/
public IResourceStream locate(Class< ? > clazz, String path)
{
IResourceStream stream = templateResourceStreamLocator.locate(clazz, path);
if (stream == null)
{
return classLoaderResourceStreamLocator.locate(clazz, path);
}
return stream;
}
private class TemplateResourceStream extends AbstractStringResourceStream
{
private static final long serialVersionUID = 1L;
private final String html;
private final int sol_id;
private final String fullpath;
TemplateResourceStream(String html, int sol_id, String fullpath)
{
this.html = html;
this.sol_id = sol_id;
this.fullpath = fullpath;
setCharset(Charset.forName("UTF8")); //$NON-NLS-1$
}
/**
* @see wicket.util.resource.AbstractStringResourceStream#getString()
*/
@Override
protected String getString()
{
return html;
}
/**
* @see wicket.util.resource.AbstractStringResourceStream#lastModifiedTime()
*/
@Override
public Time lastModifiedTime()
{
try
{
URL url = context.getResource(fullpath);
if (url != null)
{
return Time.valueOf(url.openConnection().getLastModified());
}
}
catch (Exception ex)
{
}
try
{
Solution sol = (Solution)ApplicationServerRegistry.get().getLocalRepository().getActiveRootObject(sol_id);
if (sol != null)
{
return Time.valueOf(sol.getLastModifiedTime());
}
}
catch (Exception ex)
{
Debug.error(ex);
}
return Time.now();
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
try
{
Solution sol = (Solution)ApplicationServerRegistry.get().getLocalRepository().getActiveRootObject(sol_id);
if (sol != null)
{
return "Markup[solution:" + sol.getName() + ", fullpath:" + fullpath + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
catch (Exception ex)
{
Debug.error(ex);
}
return "Markup[solution:<unknown>, fullpath:" + fullpath + "]"; //$NON-NLS-1$ //$NON-NLS-2$
}
}
private static class NullUrlResourceStream extends UrlResourceStream
{
private static final long serialVersionUID = 1L;
/**
* @param url
*/
public NullUrlResourceStream(URL url)
{
super(url);
}
/**
* @see wicket.util.resource.UrlResourceStream#lastModifiedTime()
*/
@Override
public Time lastModifiedTime()
{
Time time = super.lastModifiedTime();
if (time != null && time.getMilliseconds() != 0) return time;
return Time.now();
}
}
}