/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 ro.nextreports.server.web.dashboard.chart; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.UUID; import org.apache.wicket.IResourceListener; import org.apache.wicket.markup.head.IHeaderResponse; import org.apache.wicket.markup.head.JavaScriptHeaderItem; import org.apache.wicket.markup.html.panel.GenericPanel; import org.apache.wicket.model.IModel; import org.apache.wicket.request.IRequestHandler; import org.apache.wicket.request.handler.resource.ResourceRequestHandler; import org.apache.wicket.request.resource.ByteArrayResource; import org.apache.wicket.request.resource.IResource; import org.apache.wicket.request.resource.PackageResourceReference; import org.apache.wicket.spring.injection.annot.SpringBean; import ro.nextreports.server.service.StorageService; import ro.nextreports.server.web.core.UrlUtil; /** * http://cwiki.apache.org/WICKET/open-flash-chart-and-wicket.html */ public class OpenFlashChart extends GenericPanel<String> implements IResourceListener { private static final long serialVersionUID = 1L; // private ByteArrayResource jsonResource; // private String jsonUrl; private String width; private String height; private SWFObject swf; private boolean detachedPage; @SpringBean private StorageService storageService; public OpenFlashChart(String id, String width, String height, IModel<String> jsonModel) { super(id, jsonModel); this.width = width; this.height = height; // if I call this metod in onResourceRequested() I will obtain a small time for rendering // because json string will be created only on flash request // createJsonResource(); } @Override public void renderHead(IHeaderResponse response) { super.renderHead(response); response.render(JavaScriptHeaderItem.forReference(new PackageResourceReference(OpenFlashChart.class, "saveChartImage.js"))); } @Override public void onResourceRequested() { //System.out.println("OpenFlashChart.onResourceRequested()"); //System.out.println("requestUrl = " + RequestCycle.get().getRequest().getUrl()); //System.out.println("... " + this); IResource jsonResource = createJsonResource(); // IResource.Attributes attrs = new IResource.Attributes(RequestCycle.get().getRequest(), RequestCycle.get().getResponse(), null); // jsonResource.respond(attrs); IRequestHandler requestHandler = new ResourceRequestHandler(jsonResource, null); requestHandler.respond(getRequestCycle()); } @Override public boolean isVisible() { return getModelObject() != null; } @Override protected boolean getStatelessHint() { return false; } @Override protected void onInitialize() { //System.out.println("OpenFlashChart.onInitialize()"); super.onInitialize(); String swfURL = toAbsolutePath(urlFor(new PackageResourceReference(OpenFlashChart.class, "open-flash-chart.swf"), null).toString()); // see http://ofc2dz.com/OFC2/downloads/ofc2Downloads.html // http://ofc2dz.com/OFC2/examples/MiscellaneousPatches.html (Passing the Char Parameter "ID" when saving images (23-Feb-2009)) // for embedded charts in html pages we also put some randomness at the end (if we have charts from different dashboards id is chart1 for all) swfURL = swfURL.concat("?id=").concat(getMarkupId()).concat("&nocache=").concat(UUID.randomUUID().toString());; //System.out.println("swfURL = " + swfURL); swf = new SWFObject(swfURL, width, height, "9.0.0"); add(swf); } @Override protected void onBeforeRender() { //System.out.println("OpenFlashChart.onBeforeRender()"); //createJsonResource(); String jsonUrl = getUrlForJson(); //System.out.println("jsonUrl = " + jsonUrl); swf.addParameter("data-file", jsonUrl); swf.addParameter("wmode", "transparent"); super.onBeforeRender(); } private IResource createJsonResource() { //System.out.println("OpenFlashChart.createJsonResource()"); String jsonData = getJsonData(); //System.out.println("jsonData = " + jsonData); IResource jsonResource = null; try { jsonResource = new ByteArrayResource("text/plain", jsonData.getBytes("UTF-8")) { private static final long serialVersionUID = 1L; // These headers are needed for IE // // Pragma & Cache-Control are needed for https (otherwise a #2032 Error will be thrown) // see http://dwairi.wordpress.com/2009/01/15/open-flash-chart-ie-and-ssl/ // // Use no-store for Cache-Control & Expires to force IE to not cache flash (otherwise refresh actions & // drill-down are not working) // see http://www.cfcoffee.co.uk/index.cfm/2010/1/24/IE-and-XML-issue-over-SSL // @Override protected void setResponseHeaders(ResourceResponse data, Attributes attributes) { // TODO wicket 1.5 //data.getHeaders().addHeader("Pragma", "public"); //data.getHeaders().addHeader("Cache-Control", "no-store, must-revalidate"); //data.getHeaders().addHeader("Expires", "-1"); data.disableCaching(); super.setResponseHeaders(data, attributes); } }; } catch (UnsupportedEncodingException e) { e.printStackTrace(); throw new RuntimeException("OpenFlashChart.createJsonResource : " + e.getMessage()); } return jsonResource; } private String getUrlForJson() { // CharSequence dataPath = RequestCycle.get().urlFor(OpenFlashChart.this, IResourceListener.INTERFACE); // CharSequence dataPath = RequestCycle.get().urlFor(new ComponentRenderingRequestHandler(this)); // System.out.println(jsonResource); // CharSequence dataPath = urlFor(new ResourceRequestHandler(jsonResource, null)); /* ResourceReference resourceReference = new ResourceReference("jsonData-" + getMarkupId()) { private static final long serialVersionUID = 1L; @Override public IResource getResource() { return jsonResource; } }; // register resource reference if (resourceReference.canBeRegistered()) { getApplication().getResourceReferenceRegistry().registerResourceReference(resourceReference); } // CharSequence dataPath = urlFor(new ResourceReferenceRequestHandler(resourceReference)); */ CharSequence dataPath = urlFor(IResourceListener.INTERFACE, null); try { dataPath = URLEncoder.encode(dataPath.toString(), "UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException("Error encoding dataPath for Chart Json data file.", e); } return toAbsolutePath(dataPath.toString()); } private String getJsonData() { return getModelObject(); } private String toAbsolutePath(String path) { // server behind Apache, firewall etc StringBuffer base = UrlUtil.getAppBaseUrl(storageService); // @todo there is a problem with a detached chart seen in a WidgetZoomPage.class // this method is called for swf object and for json data // in case of detached chart, json data url does not contain "wicket/" // path contains "wicket/" for swf object url // path contains "widgetList" in dashboards // path contains "tabs-panel" when we run chart // path contains "widget%3F" if we have iframe code in an external html //if (!path.contains("widgetList") && !path.contains("wicket/") && !path.contains("tabs-panel") && !path.contains("widget%3F")) { if (detachedPage) { base.append("wicket/"); } String url = base.append(path).toString(); return url; } public void setDetachedPage(boolean detachedPage) { this.detachedPage = detachedPage; } }