2 * Copyright (C) 2012 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;
22 import java.io.ByteArrayInputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.OutputStream;
26 import java.net.URLConnection;
27 import java.sql.Connection;
28 import java.sql.ResultSet;
29 import java.sql.SQLException;
30 import java.sql.Statement;
31 import java.util.ArrayList;
32 import java.util.List;
34 import javax.servlet.ServletException;
35 import javax.servlet.http.HttpServlet;
36 import javax.servlet.http.HttpServletRequest;
37 import javax.servlet.http.HttpServletResponse;
39 import org.apache.commons.lang3.StringUtils;
40 import org.glom.web.server.libglom.Document;
41 import org.glom.web.shared.TypedDataItem;
42 import org.glom.web.shared.libglom.Field;
43 import org.glom.web.shared.libglom.layout.LayoutItem;
44 import org.glom.web.shared.libglom.layout.LayoutItemField;
45 import org.glom.web.shared.libglom.layout.LayoutItemImage;
47 import com.google.gwt.http.client.Response;
50 * @author Murray Cumming <murrayc@murrayc.com>
53 public class OnlineGlomImages extends HttpServlet {
55 private static final long serialVersionUID = -3550760617357422853L;
57 ConfiguredDocumentSet configuredDocumentSet = new ConfiguredDocumentSet();
59 public OnlineGlomImages() {
61 configuredDocumentSet.readConfiguration();
62 } catch (ServletException e) {
63 Log.error("Configuration error", e);
67 private void doError(HttpServletResponse resp, int errorCode, final String errorMessage) throws IOException {
68 Log.error(errorMessage);
69 resp.sendError(errorCode, errorMessage);
72 private void doError(HttpServletResponse resp, int errorCode, final String errorMessage, final String documentID) throws IOException {
73 Log.error(documentID, errorMessage);
74 resp.sendError(errorCode, errorMessage);
78 public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
80 //These match the history token keys in DetailsPlace:
81 final String attrDocumentID = StringUtils.defaultString(req.getParameter("document"));
82 final String attrTableName = StringUtils.defaultString(req.getParameter("table"));
83 final String attrPrimaryKeyValue = StringUtils.defaultString(req.getParameter("value"));
84 final String attrFieldName = StringUtils.defaultString(req.getParameter("field"));
86 //To request a static LayoutItemImage from the document
87 //instead of from the database:
88 final String attrLayoutName = StringUtils.defaultString(req.getParameter("layout"));
89 final String attrLayoutPath = StringUtils.defaultString(req.getParameter("layoutpath"));
91 if(StringUtils.isEmpty(attrDocumentID)) {
92 doError(resp, Response.SC_NOT_FOUND, "No document ID was specified.");
96 if(StringUtils.isEmpty(attrTableName)) {
97 doError(resp, Response.SC_NOT_FOUND, "No table name was specified.", attrDocumentID);
101 //TODO: Is it from the database or is it a static LayouteItemText from the document.
103 final boolean fromDb = !StringUtils.isEmpty(attrPrimaryKeyValue);
104 final boolean fromLayout = !StringUtils.isEmpty(attrLayoutName);
106 if(!fromDb && !fromLayout) {
107 doError(resp, Response.SC_NOT_FOUND, "No primary key value or layout name was specified.", attrDocumentID);
111 if(fromDb && StringUtils.isEmpty(attrFieldName)) {
112 doError(resp, Response.SC_NOT_FOUND, "No field name was specified.", attrDocumentID);
116 final ConfiguredDocument configuredDocument = configuredDocumentSet.getDocument(attrDocumentID);
117 if(configuredDocument == null) {
118 doError(resp, Response.SC_NOT_FOUND, "The specified document was not found.", attrDocumentID);
122 if(!configuredDocument.isAuthenticated()) {
123 doError(resp, Response.SC_NOT_FOUND, "No access to the document.", attrDocumentID);
127 final Document document = configuredDocument.getDocument();
128 if(document == null) {
129 doError(resp, Response.SC_NOT_FOUND, "The specified document details were not found.", attrDocumentID);
135 bytes = getImageFromDatabase(resp, attrDocumentID, attrTableName, attrPrimaryKeyValue, attrFieldName,
136 configuredDocument, document);
138 bytes = getImageFromDocument(resp, attrDocumentID, attrTableName, attrLayoutName, attrLayoutPath,
139 configuredDocument, document);
143 doError(resp, Response.SC_NOT_FOUND, "The image bytes could not be found. Please see the earlier error.", attrDocumentID);
147 final InputStream is = new ByteArrayInputStream(bytes);
148 final String contentType = URLConnection.guessContentTypeFromStream(is);
149 resp.setContentType(contentType);
152 resp.setContentLength((int) bytes.length);
154 // Open the output stream:
155 final OutputStream out = resp.getOutputStream();
157 // Copy the contents to the output stream
162 /** Get the image from a specific <data_layout_text> node of a specific layout for a specific table in the document,
163 * with no access to the database data.
166 * @param attrDocumentID
167 * @param attrTableName
168 * @param attrLayoutName
169 * @param attrLayoutPath
170 * @param configuredDocument
173 * @throws IOException
175 private byte[] getImageFromDocument(HttpServletResponse resp, final String attrDocumentID, final String attrTableName,
176 final String attrLayoutName, final String attrLayoutPath, final ConfiguredDocument configuredDocument, final Document document) throws IOException {
177 final LayoutItem item = document.getLayoutItemByPath(attrTableName, attrLayoutName, attrLayoutPath);
180 doError(resp, Response.SC_NOT_FOUND, "The item specifed by the layout path could not be found, attrLayoutPath=" + attrLayoutPath, attrDocumentID);
184 if(!(item instanceof LayoutItemImage)) {
185 doError(resp, Response.SC_NOT_FOUND, "The item specifed by the layout path is not an image. It has class: " + item.getClass().getName() + " and item name=" + item.getName() + ", attrLayoutPath=" + attrLayoutPath, attrDocumentID);
189 final LayoutItemImage image = (LayoutItemImage)item;
190 return image.getImage().getImageData();
193 /** Get the image from a specific field of a specific record in a specific table in the database.
196 * @param attrDocumentID
197 * @param attrTableName
198 * @param attrPrimaryKeyValue
199 * @param attrFieldName
200 * @param configuredDocument
203 * @throws IOException
205 private byte[] getImageFromDatabase(HttpServletResponse resp, final String attrDocumentID,
206 final String attrTableName, final String attrPrimaryKeyValue, final String attrFieldName,
207 final ConfiguredDocument configuredDocument, final Document document) throws IOException {
208 final Field field = document.getField(attrTableName, attrFieldName);
210 doError(resp, Response.SC_NOT_FOUND, "The specified field was not found: field=" + attrFieldName, attrDocumentID);
214 final Field fieldPrimaryKey = document.getTablePrimaryKeyField(attrTableName);
216 TypedDataItem primaryKeyValue = new TypedDataItem();
217 primaryKeyValue.setNumber(Double.parseDouble(attrPrimaryKeyValue));
219 final LayoutItemField layoutItemField = new LayoutItemField();
220 layoutItemField.setFullFieldDetails(field);
221 final List<LayoutItemField> fieldsToGet = new ArrayList<LayoutItemField>();
222 fieldsToGet.add(layoutItemField);
223 final String query = SqlUtils.buildSqlSelectWithKey(attrTableName, fieldsToGet, fieldPrimaryKey, primaryKeyValue);
225 Connection connection = null;
227 connection = configuredDocument.getCpds().getConnection();
228 } catch (final SQLException e) {
229 //e.printStackTrace();
231 doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "SQL exception: " + e.getMessage(), attrDocumentID);
237 st = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
238 } catch (SQLException e) {
239 doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "SQL exception: " + e.getMessage(), attrDocumentID);
244 doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "The SQL statement is null.", attrDocumentID);
250 rs = st.executeQuery(query);
251 } catch (SQLException e) {
252 doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "SQL exception: " + e.getMessage(), attrDocumentID);
257 doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "The SQL result set is null.", attrDocumentID);
264 bytes = rs.getBytes(1); //This is 1-indexed, not 0-indexed.
265 } catch (SQLException e) {
266 doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "SQL exception: " + e.getMessage(), attrDocumentID);
271 doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "The database contained null.", attrDocumentID);