| /** |
| * Copyright (c) 2011, 2014 - Lunifera GmbH (Gross Enzersdorf) |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Florian Pirchner - Initial implementation |
| */ |
| package org.eclipse.osbp.vaaclipse.addons.app.resources; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.net.URL; |
| import java.util.Map; |
| |
| import javax.servlet.ServletException; |
| import javax.servlet.http.HttpServlet; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.eclipse.osbp.vaaclipse.api.ResourceInfoProvider; |
| import org.eclipse.osbp.vaaclipse.publicapi.theme.Theme; |
| import org.eclipse.osbp.vaaclipse.publicapi.theme.ThemeContribution; |
| import org.eclipse.osbp.vaaclipse.publicapi.theme.ThemeEngine; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.service.component.annotations.Activate; |
| import org.osgi.service.component.annotations.Component; |
| import org.osgi.service.component.annotations.Deactivate; |
| import org.osgi.service.component.annotations.Reference; |
| import org.osgi.service.component.annotations.ReferenceCardinality; |
| import org.osgi.service.http.HttpService; |
| |
| /** |
| * This class runs as an OSGi component and serves the themes and widgetsets |
| * directly from the core Vaadin bundle. |
| * <p/> |
| * |
| * To add your own theme or widget set create a fragment which contains your |
| * theme/widgetset files and export those as packages. The |
| * <code>Fragment-Host</code> should be set to the Vaadin core bundle. The |
| * fragment containing your theme/widgetset resources will be added to the core |
| * Vaadin bundle dynamically. |
| * <p/> |
| * |
| * Of course static resources should really be deployed separately to a web |
| * server that proxies servlet requests on to the container. |
| * |
| * @author brindy |
| */ |
| @SuppressWarnings("serial") |
| @Component(immediate = true, enabled = true, property = { "http.alias=/VAADIN" }) |
| public class StaticResources extends HttpServlet { |
| |
| /** The http service. */ |
| private HttpService httpService; |
| |
| /** The resource info provider. */ |
| private ResourceInfoProvider resourceInfoProvider; |
| |
| /** The theme engine. */ |
| private ThemeEngine themeEngine; |
| |
| /** The alias. */ |
| private String alias; |
| |
| /** |
| * Instantiates a new static resources. |
| */ |
| public StaticResources() { |
| |
| } |
| |
| /** |
| * Bind. |
| * |
| * @param httpService |
| * the http service |
| */ |
| @Reference(name = "bindHttpService", service = HttpService.class, target = "(org.eclipse.osbp.ecview.jetty.serviceType=application)", cardinality = ReferenceCardinality.MANDATORY) |
| public void bind(HttpService httpService) { |
| this.httpService = httpService; |
| } |
| |
| /** |
| * Unbind. |
| * |
| * @param httpService |
| * the http service |
| */ |
| public void unbind(HttpService httpService) { |
| this.httpService = null; |
| } |
| |
| /** |
| * Bind resource info provider. |
| * |
| * @param provider |
| * the provider |
| */ |
| @Reference(name = "bindResourceInfoProvider", service = ResourceInfoProvider.class, cardinality = ReferenceCardinality.MANDATORY) |
| public void bindResourceInfoProvider(ResourceInfoProvider provider) { |
| this.resourceInfoProvider = provider; |
| } |
| |
| /** |
| * Unbind resource info provider. |
| * |
| * @param provider |
| * the provider |
| */ |
| public void unbindResourceInfoProvider(ResourceInfoProvider provider) { |
| this.resourceInfoProvider = null; |
| } |
| |
| /** |
| * Bind theme engine. |
| * |
| * @param themeEngine |
| * the theme engine |
| */ |
| @Reference(name = "bindThemeEngine", service = ThemeEngine.class, cardinality = ReferenceCardinality.MANDATORY) |
| public void bindThemeEngine(ThemeEngine themeEngine) { |
| this.themeEngine = themeEngine; |
| } |
| |
| /** |
| * Unbind theme engine. |
| * |
| * @param themeEngine |
| * the theme engine |
| */ |
| public void unbindThemeEngine(ThemeEngine themeEngine) { |
| this.themeEngine = null; |
| } |
| |
| /** |
| * Start. |
| * |
| * @param ctx |
| * the ctx |
| * @param properties |
| * the properties |
| * @throws Exception |
| * the exception |
| */ |
| @Activate |
| public void start(BundleContext ctx, Map<String, String> properties) |
| throws Exception { |
| alias = properties.get("http.alias"); |
| httpService.registerServlet(alias, this, null, null); |
| } |
| |
| /** |
| * Stop. |
| */ |
| @Deactivate |
| public void stop() { |
| httpService.unregister(alias); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest |
| * , javax.servlet.http.HttpServletResponse) |
| */ |
| @Override |
| protected void doGet(HttpServletRequest req, HttpServletResponse resp) |
| throws ServletException, IOException { |
| |
| if (this.resourceInfoProvider == null) |
| resp.sendError(HttpServletResponse.SC_CONFLICT); |
| |
| String path = req.getPathInfo(); |
| |
| if (path.endsWith("css")) { |
| resp.setContentType("text/css"); |
| } |
| |
| String resourcePath = alias + path; |
| |
| String themeId = null; |
| if (path.startsWith("/themes")) { |
| themeId = path.split("/")[2]; |
| } |
| if (themeId == null || themeId.isEmpty()) { |
| themeId = resourceInfoProvider.getCssTheme(); |
| } |
| InputStream in = getInputStream(resourcePath, |
| themeEngine.getTheme(themeId), |
| resourceInfoProvider.getApplicationtWidgetset(), |
| resourceInfoProvider.getApplicationtWidgetsetName(), |
| resourceInfoProvider.getApplicationHeaderIcon()); |
| |
| if (in == null) { |
| resp.sendError(HttpServletResponse.SC_NOT_FOUND); |
| return; |
| } |
| |
| try { |
| OutputStream out = resp.getOutputStream(); |
| |
| byte[] buffer = new byte[1024]; |
| int read = 0; |
| |
| try { |
| while (-1 != (read = in.read(buffer))) { |
| out.write(buffer, 0, read); |
| } |
| } finally { |
| out.close(); |
| } |
| } catch (Exception e) { |
| e.printStackTrace(); |
| resp.sendError(HttpServletResponse.SC_NOT_FOUND); |
| } finally { |
| in.close(); |
| } |
| } |
| |
| /** |
| * Gets the input stream. |
| * |
| * @param url |
| * the url |
| * @param theme |
| * the theme |
| * @param e4WidgetsetUri |
| * the e4 widgetset uri |
| * @param e4WidgetsetName |
| * the e4 widgetset name |
| * @param headerIconUri |
| * the header icon uri |
| * @return the input stream |
| */ |
| public InputStream getInputStream(String url, Theme theme, |
| String e4WidgetsetUri, String e4WidgetsetName, String headerIconUri) { |
| String path = null; |
| |
| StringBuffer urlString = new StringBuffer(url); |
| urlString.trimToSize(); |
| if (urlString.length() == 0) |
| throw new IllegalArgumentException(); |
| if (urlString.charAt(0) != '/') |
| throw new IllegalArgumentException(); |
| String processedUrl = urlString.substring(1); |
| String[] segments = processedUrl.split("/"); |
| |
| if (segments.length < 2) |
| throw new IllegalArgumentException(); |
| |
| if (!"VAADIN".equals(segments[0])) |
| throw new IllegalArgumentException(); |
| |
| if (segments[1].equals("widgetsets")) { |
| // return |
| // "platform:/plugin/org.eclipse.osbp.vaaclipse.resources" + |
| // url; |
| String widgetSetName = segments[2]; |
| if (e4WidgetsetName.equals(widgetSetName)) { |
| String restPath = buildSegments(segments, 3); |
| path = e4WidgetsetUri + "/" + restPath; |
| } else { |
| path = "platform:/plugin/com.vaadin.client-compiled" + url; |
| } |
| } else if (segments[1].equals("themes")) { |
| String themeName = segments[2]; |
| |
| if (theme.getWebId().equals(themeName)) { |
| if ("styles.css".equals(segments[3])) { |
| return theme.getCssAsStream(); |
| } else if ("original_styles.css".equals(segments[3])) { |
| path = theme.getCssUri(); |
| } else { |
| if ("plugin".equals(segments[3])) // this is absolute |
| // bundle path |
| { |
| String bundleName = segments[4]; |
| path = "platform:/plugin/" + bundleName + "/" |
| + buildSegments(segments, 5); |
| } else {// this is relative theme path |
| if (url.endsWith("css")) { |
| String cssFileName = url.substring(url |
| .lastIndexOf('/') + 1); |
| cssFileName = cssFileName.substring(0, |
| cssFileName.lastIndexOf('.')); |
| ThemeContribution themeContribution = themeEngine |
| .getThemeContributionByWebId(cssFileName); |
| if (themeContribution != null) |
| path = themeContribution.getCssUri(); |
| else { |
| for (String cssUri : theme.getAllCssURIs()) { |
| String relPath = buildSegments( |
| segments, 3); |
| String cssPath = cssUri.substring(0, |
| cssUri.lastIndexOf('/')) |
| + "/" |
| + relPath; |
| try { |
| URL cssUrl = new URL(cssPath); |
| return cssUrl.openStream(); |
| } catch (Exception e) { |
| } |
| } |
| } |
| } else { |
| String relPath = buildSegments(segments, 3); |
| return theme.getThemeResourceAsStream(relPath); |
| } |
| } |
| } |
| } else // any theme |
| { |
| if ("styles.css".equals(segments[3])) { |
| Theme inheritedTheme = themeEngine.getTheme(themeName); |
| path = inheritedTheme.getCssUri(); |
| } else { |
| path = "platform:/plugin/com.vaadin.themes" + url; |
| } |
| } |
| } else if ("vaadinBootstrap.js".equals(segments[1])) { |
| path = "platform:/plugin/com.vaadin.server" + url; |
| } else if ("vaadinPush.debug.js".equals(segments[1])) { |
| path = "platform:/plugin/com.vaadin.push" + url; |
| } else if ("vaadinPush.js".equals(segments[1])) { |
| path = "platform:/plugin/com.vaadin.push" + url; |
| } else { |
| return null; |
| } |
| |
| try { |
| URL u = new URL(path); |
| return u.openStream(); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| return null; |
| } |
| } |
| |
| /** |
| * Builds the segments. |
| * |
| * @param segments |
| * the segments |
| * @param start |
| * the start |
| * @return the string |
| */ |
| private static String buildSegments(String[] segments, int start) { |
| StringBuffer b = new StringBuffer(); |
| for (int i = start; i < segments.length; i++) { |
| b.append(segments[i]); |
| b.append('/'); |
| } |
| if (b.length() > 0) |
| return b.substring(0, b.length() - 1); |
| else |
| return ""; |
| } |
| } |