| // Copyright 2011 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package com.google.enterprise.adaptor.examples; |
| |
| import com.google.enterprise.adaptor.AbstractAdaptor; |
| import com.google.enterprise.adaptor.AdaptorContext; |
| import com.google.enterprise.adaptor.DocId; |
| import com.google.enterprise.adaptor.DocIdPusher; |
| import com.google.enterprise.adaptor.Request; |
| import com.google.enterprise.adaptor.Response; |
| |
| import java.io.*; |
| import java.nio.charset.Charset; |
| import java.sql.*; |
| import java.util.*; |
| import java.util.logging.*; |
| |
| /** |
| * Demonstrates what code is necessary for putting DB |
| * content onto a GSA. |
| */ |
| public class DbAdaptorTemplate extends AbstractAdaptor { |
| private static final Logger log |
| = Logger.getLogger(DbAdaptorTemplate.class.getName()); |
| private Charset encoding = Charset.forName("UTF-8"); |
| |
| @Override |
| public void init(AdaptorContext context) throws Exception { |
| Class.forName("org.gjt.mm.mysql.Driver"); |
| log.info("loaded driver"); |
| } |
| |
| private static Connection makeNewConnection() throws SQLException { |
| // TODO(pjo): DB connection pooling. |
| String url = "jdbc:mysql://127.0.0.1/adaptor1"; |
| log.fine("about to connect"); |
| Connection conn = DriverManager.getConnection(url, "root", "test"); |
| log.fine("connected"); |
| return conn; |
| } |
| |
| private static ResultSet getFromDb(Connection conn, String query) |
| throws SQLException { |
| Statement st = conn.createStatement(); |
| log.fine("about to query: " + query); |
| ResultSet rs = st.executeQuery(query); |
| log.fine("queried"); |
| return rs; |
| } |
| |
| /** Get all doc ids from database. */ |
| @Override |
| public void getDocIds(DocIdPusher pusher) throws IOException, |
| InterruptedException { |
| ArrayList<DocId> primaryKeys = new ArrayList<DocId>(); |
| Connection conn = null; |
| try { |
| conn = makeNewConnection(); |
| ResultSet rs = getFromDb(conn, "select id from backlog"); |
| while (rs.next()) { |
| DocId id = new DocId("" + rs.getInt("id")); |
| primaryKeys.add(id); |
| } |
| } catch (SQLException problem) { |
| log.log(Level.SEVERE, "failed getting ids", problem); |
| throw new IOException(problem); |
| } finally { |
| tryClosingConnection(conn); |
| } |
| if (log.isLoggable(Level.FINEST)) { |
| log.finest("primary keys: " + primaryKeys); |
| } |
| pusher.pushDocIds(primaryKeys); |
| } |
| |
| /** Gives the bytes of a document referenced with id. */ |
| @Override |
| public void getDocContent(Request req, Response resp) throws IOException { |
| DocId id = req.getDocId(); |
| Connection conn = null; |
| try { |
| conn = makeNewConnection(); |
| String query = "select * from backlog where id = " + id.getUniqueId(); |
| ResultSet rs = getFromDb(conn, query); |
| |
| // First handle cases with no data to return. |
| boolean hasResult = rs.next(); |
| if (!hasResult) { |
| resp.respondNotFound(); |
| return; |
| } |
| ResultSetMetaData rsMetaData = rs.getMetaData(); |
| int numberOfColumns = rsMetaData.getColumnCount(); |
| if (0 == numberOfColumns) { |
| log.warning("no columns in results"); |
| // TODO(pjo): Cause some sort of error code. |
| resp.getOutputStream().write( |
| "no columns in database result".getBytes(encoding)); |
| return; |
| } |
| |
| // If we have data then create lines of resulting document. |
| StringBuilder line1 = new StringBuilder(); |
| StringBuilder line2 = new StringBuilder(); |
| StringBuilder line3 = new StringBuilder(); |
| for (int i = 1; i < (numberOfColumns + 1); i++) { |
| String tableName = rsMetaData.getTableName(i); |
| String columnName = rsMetaData.getColumnName(i); |
| Object value = rs.getObject(i); |
| line1.append(","); |
| line1.append(makeIntoCsvField(tableName)); |
| line2.append(","); |
| line2.append(makeIntoCsvField(columnName)); |
| line3.append(","); |
| line3.append(makeIntoCsvField("" + value)); |
| } |
| String document = line1.substring(1) + "\n" |
| + line2.substring(1) + "\n" + line3.substring(1) + "\n"; |
| resp.getOutputStream().write(document.getBytes(encoding)); |
| } catch (SQLException problem) { |
| log.log(Level.SEVERE, "failed getting content", problem); |
| throw new IOException("retrieval error", problem); |
| } finally { |
| tryClosingConnection(conn); |
| } |
| } |
| |
| /** Call default main for adaptors. */ |
| public static void main(String[] args) { |
| AbstractAdaptor.main(new DbAdaptorTemplate(), args); |
| } |
| |
| private static void tryClosingConnection(Connection conn) { |
| if (null != conn) { |
| try { |
| conn.close(); |
| } catch (SQLException e) { |
| log.log(Level.WARNING, "close failed", e); |
| } |
| } |
| } |
| |
| private static String makeIntoCsvField(String s) { |
| /* |
| * Fields that contain a special character (comma, newline, |
| * or double quote), must be enclosed in double quotes. |
| * <...> If a field's value contains a double quote character |
| * it is escaped by placing another double quote character next to it. |
| */ |
| String doubleQuote = "\""; |
| boolean containsSpecialChar = s.contains(",") |
| || s.contains("\n") || s.contains(doubleQuote); |
| if (containsSpecialChar) { |
| s = s.replace(doubleQuote, doubleQuote + doubleQuote); |
| s = doubleQuote + s + doubleQuote; |
| } |
| return s; |
| } |
| } |