001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: DatabaseTextStore.java 3634 2007-01-08 21:42:24Z gbevin $
007: */
008: package com.uwyn.rife.cmf.dam.contentstores;
009:
010: import com.uwyn.rife.cmf.Content;
011: import com.uwyn.rife.cmf.ContentInfo;
012: import com.uwyn.rife.cmf.MimeType;
013: import com.uwyn.rife.cmf.dam.ContentDataUser;
014: import com.uwyn.rife.cmf.dam.contentstores.exceptions.StoreContentDataErrorException;
015: import com.uwyn.rife.cmf.dam.contentstores.exceptions.UseContentDataErrorException;
016: import com.uwyn.rife.cmf.dam.exceptions.ContentManagerException;
017: import com.uwyn.rife.cmf.format.Formatter;
018: import com.uwyn.rife.cmf.format.exceptions.FormatException;
019: import com.uwyn.rife.cmf.transform.ContentTransformer;
020: import com.uwyn.rife.database.Datasource;
021: import com.uwyn.rife.database.DbPreparedStatement;
022: import com.uwyn.rife.database.DbPreparedStatementHandler;
023: import com.uwyn.rife.database.exceptions.DatabaseException;
024: import com.uwyn.rife.database.queries.Insert;
025: import com.uwyn.rife.database.queries.Select;
026: import com.uwyn.rife.engine.ElementSupport;
027: import com.uwyn.rife.tools.Convert;
028: import com.uwyn.rife.tools.ExceptionUtils;
029: import com.uwyn.rife.tools.InnerClassException;
030: import com.uwyn.rife.tools.StringUtils;
031: import java.io.IOException;
032: import java.io.OutputStream;
033: import java.io.Reader;
034: import java.io.StringReader;
035: import java.io.UnsupportedEncodingException;
036: import java.sql.ResultSet;
037: import java.sql.SQLException;
038: import java.sql.Types;
039: import java.util.Map;
040: import java.util.logging.Logger;
041:
042: public abstract class DatabaseTextStore extends DatabaseContentStore {
043: public DatabaseTextStore(Datasource datasource) {
044: super (datasource);
045:
046: addMimeType(MimeType.APPLICATION_XHTML);
047: addMimeType(MimeType.TEXT_PLAIN);
048: addMimeType(MimeType.TEXT_XML);
049: }
050:
051: public String getContentType(ContentInfo contentInfo) {
052: MimeType mimeType = MimeType.getMimeType(contentInfo
053: .getMimeType());
054: if (!getSupportedMimeTypes().contains(mimeType)) {
055: return null;
056: }
057:
058: String content_type = mimeType.toString();
059:
060: Map<String, String> attributes = contentInfo.getAttributes();
061: if (attributes != null) {
062: if (attributes.containsKey("content-type")) {
063: content_type = attributes.get("content-type");
064: }
065: }
066:
067: return content_type + "; charset=UTF-8";
068: }
069:
070: public Formatter getFormatter(MimeType mimeType, boolean fragment) {
071: if (!getSupportedMimeTypes().contains(mimeType)) {
072: return null;
073: }
074: return mimeType.getFormatter();
075: }
076:
077: protected boolean _storeContentData(Insert storeContent,
078: final int id, Content content,
079: ContentTransformer transformer)
080: throws ContentManagerException {
081: if (id < 0)
082: throw new IllegalArgumentException("id must be positive");
083: if (content != null && content.getData() != null
084: && !(content.getData() instanceof String))
085: throw new IllegalArgumentException(
086: "the content data must be of type String");
087:
088: assert storeContent != null;
089:
090: final String typed_data;
091:
092: if (null == content || null == content.getData()) {
093: typed_data = null;
094: } else {
095: Formatter formatter = null;
096: if (!Convert.toBoolean(content.getAttribute("unformatted"),
097: false)) {
098: formatter = getFormatter(content.getMimeType(), content
099: .isFragment());
100: }
101:
102: if (formatter != null) {
103: try {
104: typed_data = (String) formatter.format(content,
105: transformer);
106: } catch (FormatException e) {
107: throw new StoreContentDataErrorException(id, e);
108: }
109: } else {
110: typed_data = (String) content.getData();
111: }
112: }
113:
114: return storeContent(storeContent, id, typed_data);
115: }
116:
117: protected boolean storeContent(Insert storeContent, final int id,
118: final String data) throws ContentManagerException {
119: try {
120: int result = executeUpdate(storeContent,
121: new DbPreparedStatementHandler() {
122: public void setParameters(
123: DbPreparedStatement statement) {
124: statement.setInt("contentId", id);
125: if (null == data) {
126: statement
127: .setNull("content", Types.CLOB)
128: .setInt(
129: getContentSizeColumnName(),
130: 0);
131: } else {
132: byte[] bytes = null;
133: try {
134: bytes = data.getBytes("UTF-8");
135: } catch (UnsupportedEncodingException e) {
136: // this is impossible, UTF-8 is always supported
137: Logger
138: .getLogger(
139: "com.uwyn.rife.cmf")
140: .severe(
141: ExceptionUtils
142: .getExceptionStackTrace(e));
143: }
144:
145: statement.setInt(
146: getContentSizeColumnName(),
147: bytes.length)
148: .setCharacterStream("content",
149: new StringReader(data),
150: data.length());
151: }
152: }
153: });
154:
155: return result > 0;
156: } catch (DatabaseException e) {
157: throw new StoreContentDataErrorException(id, e);
158: }
159: }
160:
161: protected <ResultType> ResultType _useContentData(
162: Select retrieveContent, final int id, ContentDataUser user)
163: throws ContentManagerException {
164: if (id < 0)
165: throw new IllegalArgumentException("id must be positive");
166: if (null == user)
167: throw new IllegalArgumentException("user can't be null");
168:
169: assert retrieveContent != null;
170:
171: try {
172: return (ResultType) user
173: .useContentData(executeGetFirstString(
174: retrieveContent,
175: new DbPreparedStatementHandler() {
176: public void setParameters(
177: DbPreparedStatement statement) {
178: statement.setInt("contentId", id);
179: }
180: }));
181: } catch (DatabaseException e) {
182: throw new UseContentDataErrorException(id, e);
183: }
184: }
185:
186: public String getContentForHtml(int id, final ContentInfo info,
187: ElementSupport element, String serveContentExitName)
188: throws ContentManagerException {
189: return useContentData(id, new ContentDataUser() {
190: public String useContentData(Object contentData)
191: throws InnerClassException {
192: if (null == contentData) {
193: return "";
194: }
195:
196: if (MimeType.APPLICATION_XHTML.equals(info
197: .getMimeType())) {
198: return contentData.toString();
199: } else if (MimeType.TEXT_PLAIN.equals(info
200: .getMimeType())) {
201: return StringUtils.encodeHtml(contentData
202: .toString());
203: }
204:
205: return "";
206: }
207: });
208: }
209:
210: protected void outputContentColumn(ResultSet resultSet,
211: OutputStream os) throws SQLException {
212: Reader text_reader = resultSet.getCharacterStream("content");
213: char[] buffer = new char[512];
214: int size = 0;
215: try {
216: while ((size = text_reader.read(buffer)) != -1) {
217: String string_buffer = new String(buffer, 0, size);
218: os.write(string_buffer.getBytes("UTF-8"));
219: }
220:
221: os.flush();
222: } catch (IOException e) {
223: // don't do anything, the client has probably disconnected
224: }
225: }
226: }
|