1 /*
2  * Copyright (C) 2007 - 2011 Vivien Malerba <malerba@gnome-db.org>
3  * Copyright (C) 2008 Murray Cumming <murrayc@murrayc.com>
4  * Copyright (C) 2010 David King <davidk@openismus.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA  02110-1301, USA.
20  */
21 
22 #include <glib/gi18n-lib.h>
23 #include <glib/gstdio.h>
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <engine/gda-report-engine.h>
28 #include <gda-report-document.h>
29 #include <gda-report-document-private.h>
30 #include "gda-report-docbook-document.h"
31 #include <libgda/binreloc/gda-binreloc.h>
32 
33 struct _GdaReportDocbookDocumentPrivate {
34 	gchar *html_stylesheet;
35 	gchar *fo_stylesheet;
36 	gchar *java_home;
37 	gchar *fop_path;
38 };
39 
40 /* properties */
41 enum
42 {
43         PROP_0,
44 	PROP_HTML_STYLESHEET,
45 
46 	PROP_FO_STYLESHEET,
47 	PROP_JAVA_HOME,
48 	PROP_FOP_PATH
49 };
50 
51 static void gda_report_docbook_document_class_init (GdaReportDocbookDocumentClass *klass);
52 static void gda_report_docbook_document_init       (GdaReportDocbookDocument *doc, GdaReportDocbookDocumentClass *klass);
53 static void gda_report_docbook_document_dispose   (GObject *object);
54 static void gda_report_docbook_document_set_property (GObject *object,
55 						      guint param_id,
56 						      const GValue *value,
57 						      GParamSpec *pspec);
58 static void gda_report_docbook_document_get_property (GObject *object,
59 						      guint param_id,
60 						      GValue *value,
61 						      GParamSpec *pspec);
62 
63 static gboolean gda_report_docbook_document_run_as_html (GdaReportDocument *doc, const gchar *filename, GError **error);
64 static gboolean gda_report_docbook_document_run_as_pdf (GdaReportDocument *doc, const gchar *filename, GError **error);
65 
66 static GObjectClass *parent_class = NULL;
67 
68 /*
69  * GdaReportDocbookDocument class implementation
70  */
71 static void
gda_report_docbook_document_class_init(GdaReportDocbookDocumentClass * klass)72 gda_report_docbook_document_class_init (GdaReportDocbookDocumentClass *klass)
73 {
74 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
75 	GdaReportDocumentClass *doc_class = GDA_REPORT_DOCUMENT_CLASS (klass);
76 
77 	parent_class = g_type_class_peek_parent (klass);
78 
79 	/* report methods */
80 	object_class->dispose = gda_report_docbook_document_dispose;
81 
82 	/* Properties */
83         object_class->set_property = gda_report_docbook_document_set_property;
84         object_class->get_property = gda_report_docbook_document_get_property;
85 
86 	g_object_class_install_property (object_class, PROP_HTML_STYLESHEET,
87                                          g_param_spec_string ("html-stylesheet", NULL, NULL, NULL,
88 							      G_PARAM_WRITABLE | G_PARAM_READABLE));
89 	g_object_class_install_property (object_class, PROP_FO_STYLESHEET,
90                                          g_param_spec_string ("fo-stylesheet", NULL, NULL, NULL,
91 							      G_PARAM_WRITABLE | G_PARAM_READABLE));
92 	g_object_class_install_property (object_class, PROP_JAVA_HOME,
93                                          g_param_spec_string ("java-home", NULL, NULL, NULL,
94 							      G_PARAM_WRITABLE | G_PARAM_READABLE));
95 	g_object_class_install_property (object_class, PROP_FOP_PATH,
96                                          g_param_spec_string ("fop-path", NULL, NULL, NULL,
97 							      G_PARAM_WRITABLE | G_PARAM_READABLE));
98 
99 	/* virtual methods */
100 	doc_class->run_as_html = gda_report_docbook_document_run_as_html;
101 	doc_class->run_as_pdf = gda_report_docbook_document_run_as_pdf;
102 }
103 
104 static void
gda_report_docbook_document_init(GdaReportDocbookDocument * doc,G_GNUC_UNUSED GdaReportDocbookDocumentClass * klass)105 gda_report_docbook_document_init (GdaReportDocbookDocument *doc,
106 				  G_GNUC_UNUSED GdaReportDocbookDocumentClass *klass)
107 {
108 	doc->priv = g_new0 (GdaReportDocbookDocumentPrivate, 1);
109 }
110 
111 static void
gda_report_docbook_document_dispose(GObject * object)112 gda_report_docbook_document_dispose (GObject *object)
113 {
114 	GdaReportDocbookDocument *doc = (GdaReportDocbookDocument *) object;
115 
116 	g_return_if_fail (GDA_IS_REPORT_DOCBOOK_DOCUMENT (doc));
117 
118 	/* free memory */
119 	if (doc->priv) {
120 		g_free (doc->priv->html_stylesheet);
121 		g_free (doc->priv->fo_stylesheet);
122 		g_free (doc->priv->java_home);
123 		g_free (doc->priv->fop_path);
124 
125 		g_free (doc->priv);
126 		doc->priv = NULL;
127 	}
128 
129 	/* chain to parent class */
130 	parent_class->dispose (object);
131 }
132 
133 GType
gda_report_docbook_document_get_type(void)134 gda_report_docbook_document_get_type (void)
135 {
136 	static GType type = 0;
137 
138 	if (G_UNLIKELY (type == 0)) {
139 		static GMutex registering;
140 		static GTypeInfo info = {
141 			sizeof (GdaReportDocbookDocumentClass),
142 			(GBaseInitFunc) NULL,
143 			(GBaseFinalizeFunc) NULL,
144 			(GClassInitFunc) gda_report_docbook_document_class_init,
145 			NULL, NULL,
146 			sizeof (GdaReportDocbookDocument),
147 			0,
148 			(GInstanceInitFunc) gda_report_docbook_document_init,
149 			0
150 		};
151 
152 		g_mutex_lock (&registering);
153 		if (type == 0)
154 			type = g_type_register_static (GDA_TYPE_REPORT_DOCUMENT, "GdaReportDocbookDocument", &info, 0);
155 		g_mutex_unlock (&registering);
156 	}
157 
158 	return type;
159 }
160 
161 static void
gda_report_docbook_document_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)162 gda_report_docbook_document_set_property (GObject *object,
163 				guint param_id,
164 				const GValue *value,
165 				GParamSpec *pspec)
166 {
167         GdaReportDocbookDocument *doc;
168 
169         doc = GDA_REPORT_DOCBOOK_DOCUMENT (object);
170         if (doc->priv) {
171                 switch (param_id) {
172 		case PROP_HTML_STYLESHEET:
173 			if (doc->priv->html_stylesheet) {
174 				g_free (doc->priv->html_stylesheet);
175 				doc->priv->html_stylesheet = NULL;
176 			}
177 			if (g_value_get_string (value))
178 				doc->priv->html_stylesheet = g_strdup (g_value_get_string (value));
179 			break;
180 		case PROP_FO_STYLESHEET:
181 			if (doc->priv->fo_stylesheet) {
182 				g_free (doc->priv->fo_stylesheet);
183 				doc->priv->fo_stylesheet = NULL;
184 			}
185 			if (g_value_get_string (value))
186 				doc->priv->fo_stylesheet = g_strdup (g_value_get_string (value));
187 			break;
188 		case PROP_JAVA_HOME:
189 			if (doc->priv->java_home) {
190 				g_free (doc->priv->java_home);
191 				doc->priv->java_home = NULL;
192 			}
193 			if (g_value_get_string (value))
194 				doc->priv->java_home = g_strdup (g_value_get_string (value));
195 			break;
196 		case PROP_FOP_PATH:
197 			if (doc->priv->fop_path) {
198 				g_free (doc->priv->fop_path);
199 				doc->priv->fop_path = NULL;
200 			}
201 			if (g_value_get_string (value))
202 				doc->priv->fop_path = g_strdup (g_value_get_string (value));
203 			break;
204 		default:
205 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
206 			break;
207                 }
208         }
209 }
210 
211 static void
gda_report_docbook_document_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)212 gda_report_docbook_document_get_property (GObject *object,
213 				guint param_id,
214 				GValue *value,
215 				GParamSpec *pspec)
216 {
217         GdaReportDocbookDocument *doc;
218 
219         doc = GDA_REPORT_DOCBOOK_DOCUMENT (object);
220         if (doc->priv) {
221 		switch (param_id) {
222 		case PROP_HTML_STYLESHEET:
223 			g_value_set_string (value, doc->priv->html_stylesheet);
224 			break;
225 		case PROP_FO_STYLESHEET:
226 			g_value_set_string (value, doc->priv->fo_stylesheet);
227 			break;
228 		case PROP_JAVA_HOME:
229 			g_value_set_string (value, doc->priv->java_home);
230 			break;
231 		case PROP_FOP_PATH:
232 			g_value_set_string (value, doc->priv->fop_path);
233 			break;
234 		default:
235 			G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
236 			break;
237 		}
238         }
239 }
240 
241 /**
242  * gda_report_docbook_document_new
243  * @engine: a #GdaReportEngine, or %NULL
244  *
245  * Creates a new #GdaReportDocbookDocument using @engine if specified
246  *
247  * Returns: a new #GdaReportDocbookDocument object
248  */
249 GdaReportDocument *
gda_report_docbook_document_new(GdaReportEngine * engine)250 gda_report_docbook_document_new (GdaReportEngine *engine)
251 {
252 	if (engine)
253 		return (GdaReportDocument *) g_object_new (GDA_TYPE_REPORT_DOCBOOK_DOCUMENT, "engine", engine, NULL);
254 	else
255 		return (GdaReportDocument *) g_object_new (GDA_TYPE_REPORT_DOCBOOK_DOCUMENT, NULL);
256 }
257 
258 
259 /* virtual methods */
260 static gboolean
gda_report_docbook_document_run_as_html(GdaReportDocument * doc,const gchar * filename,GError ** error)261 gda_report_docbook_document_run_as_html (GdaReportDocument *doc, const gchar *filename, GError **error)
262 {
263 	static GMutex init_mutex;
264 	static gchar *xsltproc = NULL;
265 	GdaReportDocbookDocument *fdoc;
266 	gchar **argv;
267 	gboolean retval;
268 
269 	g_return_val_if_fail (GDA_IS_REPORT_DOCBOOK_DOCUMENT (doc), FALSE);
270 	g_return_val_if_fail (filename && *filename, FALSE);
271 	fdoc = GDA_REPORT_DOCBOOK_DOCUMENT (doc);
272 	g_return_val_if_fail (fdoc->priv, FALSE);
273 
274 	g_mutex_lock (&init_mutex);
275 	if (!xsltproc) {
276 		xsltproc = g_find_program_in_path ("xsltproc");
277 		if (!xsltproc) {
278 			xsltproc = gda_gbr_get_file_path (GDA_BIN_DIR, "xsltproc", NULL);
279 			if (!g_file_test (xsltproc, G_FILE_TEST_IS_EXECUTABLE)) {
280 				g_free (xsltproc);
281 				xsltproc = NULL;
282 			}
283 		}
284 		if (!xsltproc) {
285 			g_set_error (error, 0, 0,
286 				     _("Could not find the '%s' program"), "xsltproc");
287 			g_mutex_unlock (&init_mutex);
288 			return FALSE;
289 		}
290 	}
291 
292 	if (!fdoc->priv->html_stylesheet) {
293 		 fdoc->priv->html_stylesheet = gda_gbr_get_file_path (GDA_DATA_DIR, "xml", "docbook",
294 								    "stylesheet", "html", "docbook.xsl", NULL);
295 		if (!g_file_test (fdoc->priv->html_stylesheet, G_FILE_TEST_EXISTS)) {
296 			g_free (fdoc->priv->html_stylesheet);
297 			fdoc->priv->html_stylesheet = NULL;
298 		}
299 		if (!fdoc->priv->html_stylesheet) {
300 			g_set_error (error, 0, 0, "%s",
301 				     _("Could not find the DocBook XSL stylesheet for HTML"));
302 			g_mutex_unlock (&init_mutex);
303 			return FALSE;
304 		}
305 	}
306 	g_mutex_unlock (&init_mutex);
307 
308 	argv = g_new (gchar *, 9);
309 	argv[0] = g_strdup (xsltproc);
310 	argv[1] = g_strdup ("--output");
311 	argv[2] = g_strdup (filename);
312 	argv[3] = g_strdup ("--stringparam");
313 	argv[4] = g_strdup ("use.extensions");
314 	argv[5] = g_strdup ("0");
315 	argv[6] = g_strdup (fdoc->priv->html_stylesheet);
316 	argv[7] = NULL;
317 	argv[8] = NULL;
318 
319 	retval = _gda_report_document_run_converter_argv (doc, NULL, argv, 7,
320 							 "xsltproc", error);
321 	g_strfreev (argv);
322 	return retval;
323 }
324 
325 static gboolean
gda_report_docbook_document_run_as_pdf(GdaReportDocument * doc,const gchar * filename,GError ** error)326 gda_report_docbook_document_run_as_pdf (GdaReportDocument *doc, const gchar *filename, GError **error)
327 {
328 	GdaReportDocbookDocument *fdoc;
329 	gchar **argv;
330 	gboolean retval;
331 
332 	g_return_val_if_fail (GDA_IS_REPORT_DOCBOOK_DOCUMENT (doc), FALSE);
333 	g_return_val_if_fail (filename && *filename, FALSE);
334 	fdoc = GDA_REPORT_DOCBOOK_DOCUMENT (doc);
335 	g_return_val_if_fail (fdoc->priv, FALSE);
336 
337 	if (!fdoc->priv->fop_path) {
338 		fdoc->priv->fop_path = g_find_program_in_path ("fop");
339 		if (!fdoc->priv->fop_path) {
340 			fdoc->priv->fop_path = gda_gbr_get_file_path (GDA_BIN_DIR, "fop", NULL);
341 			if (!g_file_test (fdoc->priv->fop_path, G_FILE_TEST_IS_EXECUTABLE)) {
342 				g_free (fdoc->priv->fop_path);
343 				fdoc->priv->fop_path = NULL;
344 			}
345 		}
346 		if (!fdoc->priv->fop_path && fdoc->priv->java_home) {
347 			fdoc->priv->fop_path = g_build_filename (fdoc->priv->java_home, "fop", NULL);
348 			if (!g_file_test (fdoc->priv->fop_path, G_FILE_TEST_IS_EXECUTABLE)) {
349 				g_free (fdoc->priv->fop_path);
350 				fdoc->priv->fop_path = NULL;
351 			}
352 		}
353 		if (!fdoc->priv->fop_path) {
354 			g_set_error (error, 0, 0,
355 				     _("Could not find the '%s' program"), "fop");
356 			return FALSE;
357 		}
358 	}
359 
360 	if (!fdoc->priv->fo_stylesheet) {
361 		 fdoc->priv->fo_stylesheet = gda_gbr_get_file_path (GDA_DATA_DIR, "xml", "docbook",
362 								    "stylesheet", "fo", "docbook.xsl", NULL);
363 		if (!g_file_test (fdoc->priv->fo_stylesheet, G_FILE_TEST_EXISTS)) {
364 			g_free (fdoc->priv->fo_stylesheet);
365 			fdoc->priv->fo_stylesheet = NULL;
366 		}
367 		if (!fdoc->priv->fo_stylesheet) {
368 			g_set_error (error, 0, 0, "%s",
369 				     _("Could not find the DocBook XSL stylesheet for Formatting Objects"));
370 			return FALSE;
371 		}
372 	}
373 
374 	argv = g_new (gchar *, 8);
375 	argv[0] = g_strdup (fdoc->priv->fop_path);
376 	argv[1] = g_strdup ("-xml");
377 	argv[2] = NULL;
378 	argv[3] = g_strdup ("-xsl");
379 	argv[4] = g_strdup (fdoc->priv->fo_stylesheet);
380 	argv[5] = g_strdup ("-pdf");
381 	argv[6] = g_strdup (filename);
382 	argv[7] = NULL;
383 
384 	gint i;
385 	for (i= 0; i< 7; i++)
386 		g_print ("==%d %s\n", i, argv[i]);
387 
388 	retval = _gda_report_document_run_converter_argv (doc, NULL, argv, 2,
389 							 "fop", error);
390 	g_strfreev (argv);
391 	return retval;
392 }
393