2 * Copyright (C) 2010, 2011 Openismus GmbH
4 * This file is part of GWT-Glom.
6 * GWT-Glom is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
11 * GWT-Glom is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with GWT-Glom. If not, see <http://www.gnu.org/licenses/>.
20 package org.glom.web.server;
23 import java.io.FilenameFilter;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.sql.SQLException;
27 import java.util.ArrayList;
28 import java.util.Hashtable;
29 import java.util.Properties;
31 import org.glom.libglom.BakeryDocument.LoadFailureCodes;
32 import org.glom.libglom.Document;
33 import org.glom.libglom.Glom;
34 import org.glom.web.client.OnlineGlomService;
35 import org.glom.web.shared.DetailsLayoutAndData;
36 import org.glom.web.shared.Documents;
37 import org.glom.web.shared.GlomDocument;
38 import org.glom.web.shared.GlomField;
39 import org.glom.web.shared.layout.LayoutGroup;
41 import com.google.gwt.user.server.rpc.RemoteServiceServlet;
42 import com.mchange.v2.c3p0.DataSources;
45 * The servlet class for setting up the server side of Online Glom. The public methods in this class are the methods
46 * that can be called by the client side code.
48 * @author Ben Konrath <ben@bagu.org>
50 @SuppressWarnings("serial")
51 public class OnlineGlomServiceImpl extends RemoteServiceServlet implements OnlineGlomService {
53 // convenience class to for dealing with the Online Glom configuration file
54 private class OnlineGlomProperties extends Properties {
55 public String getKey(String value) {
56 for (String key : stringPropertyNames()) {
57 if (getProperty(key).trim().equals(value))
64 private final Hashtable<String, ConfiguredDocument> documentMapping = new Hashtable<String, ConfiguredDocument>();
67 * This is called when the servlet is started or restarted.
69 public OnlineGlomServiceImpl() throws Exception {
71 // Find the configuration file. See this thread for background info:
72 // http://stackoverflow.com/questions/2161054/where-to-place-properties-files-in-a-jsp-servlet-web-application
73 OnlineGlomProperties config = new OnlineGlomProperties();
74 InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("onlineglom.properties");
76 Log.fatal("onlineglom.properties not found.");
77 throw new IOException();
81 // check if we can read the configured glom file directory
82 String documentDirName = config.getProperty("glom.document.directory");
83 File documentDir = new File(documentDirName);
84 if (!documentDir.isDirectory()) {
85 Log.fatal(documentDirName + " is not a directory.");
86 throw new IOException();
88 if (!documentDir.canRead()) {
89 Log.fatal("Can't read the files in : " + documentDirName);
90 throw new IOException();
93 // get and check the glom files in the specified directory
94 final String glomFileExtension = ".glom";
95 File[] glomFiles = documentDir.listFiles(new FilenameFilter() {
97 public boolean accept(File dir, String name) {
98 return name.endsWith(glomFileExtension);
102 for (File glomFile : glomFiles) {
103 Document document = new Document();
104 document.set_file_uri("file://" + glomFile.getAbsolutePath());
106 boolean retval = document.load(error);
107 if (retval == false) {
109 if (LoadFailureCodes.LOAD_FAILURE_CODE_NOT_FOUND == LoadFailureCodes.swigToEnum(error)) {
110 message = "Could not find file: " + glomFile.getAbsolutePath();
112 message = "An unknown error occurred when trying to load file: " + glomFile.getAbsolutePath();
115 // continue with for loop because there may be other documents in the directory
119 ConfiguredDocument configuredDocument = new ConfiguredDocument(document);
120 // check if a username and password have been set and work for the current document
121 String filename = glomFile.getName();
122 String key = config.getKey(filename);
124 String[] keyArray = key.split("\\.");
125 if (keyArray.length == 3 && "filename".equals(keyArray[2])) {
126 // username/password could be set, let's check to see if it works
127 String usernameKey = key.replaceAll(keyArray[2], "username");
128 String passwordKey = key.replaceAll(keyArray[2], "password");
129 configuredDocument.setUsernameAndPassword(config.getProperty(usernameKey),
130 config.getProperty(passwordKey));
134 // check the if the global username and password have been set and work with this document
135 if (!configuredDocument.isAuthenticated()) {
136 configuredDocument.setUsernameAndPassword(config.getProperty("glom.document.username"),
137 config.getProperty("glom.document.password"));
140 // The key for the hash table is the file name without the .glom extension and with spaces ( ) replaced with
141 // pluses (+). The space/plus replacement makes the key more friendly for URLs.
142 String documentID = filename.substring(0, glomFile.getName().length() - glomFileExtension.length())
144 configuredDocument.setDocumentID(documentID);
145 documentMapping.put(documentID, configuredDocument);
151 * This is called when the servlet is stopped or restarted.
153 * @see javax.servlet.GenericServlet#destroy()
156 public void destroy() {
157 Glom.libglom_deinit();
159 for (String documenTitle : documentMapping.keySet()) {
160 ConfiguredDocument configuredDoc = documentMapping.get(documenTitle);
162 DataSources.destroy(configuredDoc.getCpds());
163 } catch (SQLException e) {
164 Log.error(documenTitle, "Error cleaning up the ComboPooledDataSource.", e);
173 * @see org.glom.web.client.OnlineGlomService#getGlomDocument(java.lang.String)
176 public GlomDocument getGlomDocument(String documentID) {
178 ConfiguredDocument configuredDoc = documentMapping.get(documentID);
180 // FIXME check for authentication
182 return configuredDoc.getGlomDocument();
189 * @see org.glom.web.client.OnlineGlomService#getListViewLayout(java.lang.String, java.lang.String)
192 public LayoutGroup getListViewLayout(String documentID, String tableName) {
193 ConfiguredDocument configuredDoc = documentMapping.get(documentID);
195 // FIXME check for authentication
197 return configuredDoc.getListViewLayoutGroup(tableName);
203 * @see org.glom.web.client.OnlineGlomService#getListViewData(java.lang.String, java.lang.String, int, int)
206 public ArrayList<GlomField[]> getListViewData(String documentID, String tableName, int start, int length) {
207 ConfiguredDocument configuredDoc = documentMapping.get(documentID);
208 if (!configuredDoc.isAuthenticated()) {
209 return new ArrayList<GlomField[]>();
211 return configuredDoc.getListViewData(tableName, start, length, false, 0, false);
217 * @see org.glom.web.client.OnlineGlomService#getSortedListViewData(java.lang.String, java.lang.String, int, int,
221 public ArrayList<GlomField[]> getSortedListViewData(String documentID, String tableName, int start, int length,
222 int sortColumnIndex, boolean isAscending) {
223 ConfiguredDocument configuredDoc = documentMapping.get(documentID);
224 if (!configuredDoc.isAuthenticated()) {
225 return new ArrayList<GlomField[]>();
227 return configuredDoc.getListViewData(tableName, start, length, true, sortColumnIndex, isAscending);
233 * @see org.glom.web.client.OnlineGlomService#getDocuments()
236 public Documents getDocuments() {
237 Documents documents = new Documents();
238 for (String documentID : documentMapping.keySet()) {
239 ConfiguredDocument configuredDoc = documentMapping.get(documentID);
240 documents.addDocument(documentID, configuredDoc.getDocument().get_database_title());
248 * @see org.glom.web.client.OnlineGlomService#isAuthenticated(java.lang.String)
250 public boolean isAuthenticated(String documentID) {
251 return documentMapping.get(documentID).isAuthenticated();
257 * @see org.glom.web.client.OnlineGlomService#checkAuthentication(java.lang.String, java.lang.String,
261 public boolean checkAuthentication(String documentID, String username, String password) {
262 ConfiguredDocument configuredDoc = documentMapping.get(documentID);
264 return configuredDoc.setUsernameAndPassword(username, password);
265 } catch (SQLException e) {
266 Log.error(documentID, "Unknown SQL Error checking the database authentication.", e);
274 * @see org.glom.web.client.OnlineGlomService#getDetailsData(java.lang.String, java.lang.String, java.lang.String)
277 public GlomField[] getDetailsData(String documentID, String tableName, String primaryKeyValue) {
278 ConfiguredDocument configuredDoc = documentMapping.get(documentID);
280 // FIXME check for authentication
282 return configuredDoc.getDetailsData(tableName, primaryKeyValue);
288 * @see org.glom.web.client.OnlineGlomService#getDetailsLayoutAndData(java.lang.String, java.lang.String,
292 public DetailsLayoutAndData getDetailsLayoutAndData(String documentID, String tableName, String primaryKeyValue) {
293 ConfiguredDocument configuredDoc = documentMapping.get(documentID);
294 DetailsLayoutAndData initalDetailsView = new DetailsLayoutAndData();
296 // FIXME check for authentication
298 initalDetailsView.setLayout(configuredDoc.getDetailsLayoutGroup(tableName));
299 initalDetailsView.setData(configuredDoc.getDetailsData(tableName, primaryKeyValue));
301 return initalDetailsView;
307 * @see org.glom.web.client.OnlineGlomService#getRelatedListData(java.lang.String, java.lang.String, int, int)
310 public ArrayList<GlomField[]> getRelatedListData(String documentID, String tableName, String relationshipName,
311 String foreignKeyValue, int start, int length) {
312 ConfiguredDocument configuredDoc = documentMapping.get(documentID);
314 // FIXME check for authentication
316 return configuredDoc.getRelatedListData(tableName, relationshipName, foreignKeyValue, start, length, false, 0,
323 * @see org.glom.web.client.OnlineGlomService#getSortedRelatedListData(java.lang.String, java.lang.String, int, int,
327 public ArrayList<GlomField[]> getSortedRelatedListData(String documentID, String tableName,
328 String relationshipName, String foreignKeyValue, int start, int length, int sortColumnIndex, boolean ascending) {
329 ConfiguredDocument configuredDoc = documentMapping.get(documentID);
331 // FIXME check for authentication
333 return configuredDoc.getRelatedListData(tableName, relationshipName, foreignKeyValue, start, length, true,
334 sortColumnIndex, ascending);
337 public int getRelatedListRowCount(String documentID, String tableName, String relationshipName,
338 String foreignKeyValue) {
339 ConfiguredDocument configuredDoc = documentMapping.get(documentID);
341 // FIXME check for authentication
343 return configuredDoc.getRelatedListRowCount(tableName, relationshipName, foreignKeyValue);