OnlineGlomImages: Detect the mime-type (content type).
[online-glom:gwt-glom.git] / src / main / java / org / glom / web / server / OnlineGlomImages.java
1 /*
2  * Copyright (C) 2012 Openismus GmbH
3  *
4  * This file is part of GWT-Glom.
5  *
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.
10  *
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
14  * for more details.
15  *
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/>.
18  */
19
20 package org.glom.web.server;
21
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;
33
34 import javax.servlet.ServletException;
35 import javax.servlet.http.HttpServlet;
36 import javax.servlet.http.HttpServletRequest;
37 import javax.servlet.http.HttpServletResponse;
38
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.LayoutItemField;
44
45 import com.google.gwt.http.client.Response;
46
47 /**
48  * @author Murray Cumming <murrayc@murrayc.com>
49  * 
50  */
51 public class OnlineGlomImages extends HttpServlet {
52
53         private static final long serialVersionUID = -3550760617357422853L;
54         
55         ConfiguredDocumentSet configuredDocumentSet = new ConfiguredDocumentSet();
56         
57         public OnlineGlomImages() {
58                 try {
59                         configuredDocumentSet.readConfiguration();
60                 } catch (ServletException e) {
61                         // TODO Auto-generated catch block
62                         e.printStackTrace();
63                 }
64         }
65         
66         private void doError(HttpServletResponse resp, int errorCode, final String errorMessage) throws IOException {
67                 Log.error(errorMessage);
68                 resp.sendError(errorCode, errorMessage);
69         }
70         
71         private void doError(HttpServletResponse resp, int errorCode, final String errorMessage, final String documentID) throws IOException {
72                 Log.error(documentID, errorMessage);
73                 resp.sendError(errorCode, errorMessage);
74         }
75
76         @Override
77         public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
78
79                 //These match the history token keys in DetailsPlace:
80                 final String attrDocumentID = StringUtils.defaultString(req.getParameter("document"));
81                 final String attrTableName = StringUtils.defaultString(req.getParameter("table"));
82                 final String attrPrimaryKeyValue = StringUtils.defaultString(req.getParameter("value"));
83                 final String attrFieldName = StringUtils.defaultString(req.getParameter("field"));
84                 
85                 if(StringUtils.isEmpty(attrDocumentID)) {
86                         doError(resp, Response.SC_NOT_FOUND, "No document ID was specified.");
87                         return;
88                 }
89                 
90                 if(StringUtils.isEmpty(attrTableName)) {
91                         doError(resp, Response.SC_NOT_FOUND, "No table name was specified.", attrDocumentID);
92                         return;
93                 }
94                 
95                 if(StringUtils.isEmpty(attrPrimaryKeyValue)) {
96                         doError(resp, Response.SC_NOT_FOUND, "No primary key value was specified.", attrDocumentID);
97                         return;
98                 }
99                 
100                 if(StringUtils.isEmpty(attrFieldName)) {
101                         doError(resp, Response.SC_NOT_FOUND, "No field name was specified.", attrDocumentID);
102                         return;
103                 }
104                 
105                 final ConfiguredDocument configuredDocument = configuredDocumentSet.getDocument(attrDocumentID);
106                 if(configuredDocument == null) {
107                         doError(resp, Response.SC_NOT_FOUND, "The specified document was not found.", attrDocumentID);
108                         return;
109                 }
110                 
111                 if(!configuredDocument.isAuthenticated()) {
112                         doError(resp, Response.SC_NOT_FOUND, "No access to the document.", attrDocumentID);
113                         return;
114                 }
115
116                 final Document document = configuredDocument.getDocument();
117                 if(document == null) {
118                         doError(resp, Response.SC_NOT_FOUND, "The specified document details were not found.", attrDocumentID);
119                         return;
120                 }
121                 
122                 final Field field = document.getField(attrTableName, attrFieldName);
123                 if(field == null) {
124                         doError(resp, Response.SC_NOT_FOUND, "The specified field was not found: field=" + attrFieldName, attrDocumentID);
125                         return;
126                 }
127                 
128                 final Field fieldPrimaryKey = document.getTablePrimaryKeyField(attrTableName);
129                 
130                 TypedDataItem primaryKeyValue = new TypedDataItem();
131                 primaryKeyValue.setNumber(Double.parseDouble(attrPrimaryKeyValue));
132                 
133                 final LayoutItemField layoutItemField = new LayoutItemField();
134                 layoutItemField.setFullFieldDetails(field);
135                 final List<LayoutItemField> fieldsToGet = new ArrayList<LayoutItemField>();
136                 fieldsToGet.add(layoutItemField);
137                 final String query = SqlUtils.buildSqlSelectWithKey(attrTableName, fieldsToGet, fieldPrimaryKey, primaryKeyValue);
138                 
139                 Connection connection = null;
140                 try {
141                         connection = configuredDocument.getCpds().getConnection();
142                 } catch (final SQLException e) {
143                         //e.printStackTrace();
144
145                         doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "SQL exception: " + e.getMessage(), attrDocumentID);
146                         return;
147                 }
148                 
149                 Statement st = null;
150                 try {
151                         st = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
152                 } catch (SQLException e) {
153                         doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "SQL exception: " + e.getMessage(), attrDocumentID);
154                         return;
155                 }
156                 
157                 if(st == null) {
158                         doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "The SQL statement is null.", attrDocumentID);
159                         return;
160                 }
161
162                 ResultSet rs = null;
163                 try {
164                         rs = st.executeQuery(query);
165                 } catch (SQLException e) {
166                         doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "SQL exception: " + e.getMessage(), attrDocumentID);
167                         return;
168                 }
169
170                 if(rs == null) {
171                         doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "The SQL result set is null.", attrDocumentID);
172                         return;
173                 }
174                 
175                 byte[] bytes = null;
176                 try {
177                         rs.next();
178                         bytes = rs.getBytes(1); //This is 1-indexed, not 0-indexed.
179                 } catch (SQLException e) {
180                         doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "SQL exception: " + e.getMessage(), attrDocumentID);
181                         return;
182                 }
183
184                 if(bytes == null) {
185                         doError(resp, Response.SC_INTERNAL_SERVER_ERROR, "The database contained null.", attrDocumentID);
186                         return;
187                 }
188                 
189                 final InputStream is = new ByteArrayInputStream(bytes);
190                 final String contentType = URLConnection.guessContentTypeFromStream(is);        
191                 resp.setContentType(contentType);
192
193                 // Set content size:
194                 resp.setContentLength((int) bytes.length);
195
196                 // Open the output stream:
197                 final OutputStream out = resp.getOutputStream();
198
199                 // Copy the contents to the output stream
200                 out.write(bytes);
201                 out.close();
202         }
203 }