/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.resource.adapter.google.gdata; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.teiid.logging.LogManager; import org.teiid.resource.adapter.google.auth.AuthHeaderFactory; import org.teiid.translator.google.api.SpreadsheetOperationException; import org.teiid.translator.google.api.UpdateSet; import org.teiid.translator.google.api.result.UpdateResult; import com.google.gdata.client.spreadsheet.FeedURLFactory; import com.google.gdata.client.spreadsheet.SpreadsheetQuery; import com.google.gdata.client.spreadsheet.SpreadsheetService; import com.google.gdata.data.BaseFeed; import com.google.gdata.data.IEntry; import com.google.gdata.data.spreadsheet.ListEntry; import com.google.gdata.data.spreadsheet.ListFeed; import com.google.gdata.data.spreadsheet.SpreadsheetEntry; import com.google.gdata.data.spreadsheet.SpreadsheetFeed; import com.google.gdata.util.ServiceException; /** * Spreadsheet browser implemented by gdata-java-client: http://code.google.com/p/gdata-java-client/ * * This browser authenticates using Client Login. * * @author fnguyen * */ public class GDataClientLoginAPI { private static final int RETRY_DELAY = 3000; private SpreadsheetService service; private FeedURLFactory factory; private AuthHeaderFactory headerFactory = null; public void setHeaderFactory(AuthHeaderFactory headerFactory) { this.headerFactory = headerFactory; service.setHeader("Authorization" , headerFactory.getAuthHeader()); //$NON-NLS-1$ } public GDataClientLoginAPI() { service = new SpreadsheetService("GdataSpreadsheetBrowser"); //$NON-NLS-1$ this.factory = FeedURLFactory.getDefault(); } public SpreadsheetEntry getSpreadsheetEntry(String sheetName, boolean key) { if (key) { try { return getSpreadsheetEntry(new URL(factory.getSpreadsheetsFeedUrl(), "full/"+sheetName), SpreadsheetEntry.class); } catch (MalformedURLException e) { throw new SpreadsheetOperationException(e); } } SpreadsheetQuery squery = new SpreadsheetQuery(factory.getSpreadsheetsFeedUrl()); squery.setTitleExact(true); squery.setTitleQuery(sheetName); SpreadsheetFeed feed = (SpreadsheetFeed) getSpreadsheetFeedQuery(squery, SpreadsheetFeed.class); List<SpreadsheetEntry> entry = feed.getEntries(); if (entry.size() == 0) throw new SpreadsheetOperationException("Couldn't find spreadsheet:" + sheetName); if (entry.size() > 1) { throw new SpreadsheetOperationException("Multiple worksheets with the given title:" + sheetName + ". Consider using a sheet key instead."); } return entry.get(0); } private BaseFeed<?, ?> getSpreadsheetFeedQuery(SpreadsheetQuery squery, Class<? extends BaseFeed<?, ?>> feedClass) { try { return service.getFeed(squery, feedClass); } catch (Exception ex) { try { Thread.sleep(RETRY_DELAY); } catch (InterruptedException e) { } // Try to relogin reauthenticate(); try { return service.getFeed(squery, SpreadsheetFeed.class); } catch (Exception ex2) { throw new SpreadsheetOperationException("Error getting spreadsheet feed. Possibly bad authentication or connection problems. " + ex2); } } } private <E extends IEntry> E getSpreadsheetEntry(URL entryUrl, Class<E> entryClass) { try { return service.getEntry(entryUrl, entryClass); } catch (Exception ex) { try { Thread.sleep(RETRY_DELAY); } catch (InterruptedException e) { } // Try to relogin reauthenticate(); try { return service.getEntry(entryUrl, entryClass); } catch (Exception ex2) { throw new SpreadsheetOperationException("Error getting spreadsheet feed. Possibly bad authentication or connection problems. " + ex2); } } } private void reauthenticate() { headerFactory.login(); service.setHeader("Authorization", headerFactory.getAuthHeader()); //$NON-NLS-1$ } /** * Updates spreadsheet using the listfeed. * * @param spreadsheetKey key that identifies spreadsheet * @param worksheetID id that identifies worksheet * @param criteria update criteria * @param updateSet fields that should be updated * @return number of updated rows */ public UpdateResult listFeedUpdate(String spreadsheetKey, String worksheetID, String criteria, List<UpdateSet> updateSet) { SpreadsheetQuery query = null; try { query = new SpreadsheetQuery(factory.getListFeedUrl(spreadsheetKey, worksheetID, "private", "full")); //$NON-NLS-1$ //$NON-NLS-2$ if (criteria != null) { query.setStringCustomParameter("sq", criteria); //$NON-NLS-1$ } } catch (MalformedURLException e) { throw new SpreadsheetOperationException("Error getting spreadsheet URL: " + e); } ListFeed listfeed = (ListFeed) getSpreadsheetFeedQuery(query, ListFeed.class); int counter=0; for (ListEntry row : listfeed.getEntries()) { for (UpdateSet set : updateSet) { row.getCustomElements().setValueLocal(set.getColumnID(), set.getValue()); } try { row.update(); } catch (IOException e) { LogManager.logWarning(this.getClass().getName(), e,"Error occured when updating spreadsheet row"); continue; } catch (ServiceException e2) { LogManager.logWarning(this.getClass().getName(), e2,"Error occured when updating spreadsheet row"); continue; } counter++; } return new UpdateResult(listfeed.getEntries().size(), counter); } /** * Deletes spreadsheet rows using the listfeed. * * @param spreadsheetKey key that identifies spreadsheet * @param worksheetID id that identifies worksheet * @param criteria delete criteria * @return number of deleted rows */ public UpdateResult listFeedDelete(String spreadsheetKey, String worksheetID, String criteria) { SpreadsheetQuery query = null; try { query = new SpreadsheetQuery(factory.getListFeedUrl(spreadsheetKey, worksheetID, "private", "full")); //$NON-NLS-1$ //$NON-NLS-2$ if (criteria != null) { query.setStringCustomParameter("sq", criteria); //$NON-NLS-1$ } } catch (MalformedURLException e) { throw new SpreadsheetOperationException("Error getting spreadsheet URL: " + e); } ListFeed listfeed = (ListFeed) getSpreadsheetFeedQuery(query, ListFeed.class); int counter=0; for(int i=listfeed.getEntries().size()-1;i>-1;i--) { ListEntry row=listfeed.getEntries().get(i); try { row.delete(); } catch (IOException e) { LogManager.logWarning(this.getClass().getName(), e,"Error occured when deleting spreadsheet row"); continue; } catch (ServiceException e2) { LogManager.logWarning(this.getClass().getName(), e2,"Error occured when deleting spreadsheet row"); continue; } counter++; } return new UpdateResult(listfeed.getEntries().size(), counter); } /** * Insert row into spreadsheet using listfeed * @param spreadsheetKey key that identifies spreadsheet * @param worksheetID key that identifies worksheet * @param pair name - value pair that should be inserted into spreadsheet * @return 1 if the row is successfully inserted */ public UpdateResult listFeedInsert(String spreadsheetKey, String worksheetID, Map<String, String> pair) { SpreadsheetQuery query = null; try { query = new SpreadsheetQuery(factory.getListFeedUrl(spreadsheetKey, worksheetID, "private", "full")); //$NON-NLS-1$ //$NON-NLS-2$ } catch (MalformedURLException e) { throw new SpreadsheetOperationException("Error getting spreadsheet URL: " + e); } ListEntry row = new ListEntry(); for (Entry<String, String> entry : pair.entrySet()) { row.getCustomElements().setValueLocal(entry.getKey(), entry.getValue()); } try { service.insert(query.getFeedUrl(), row); } catch (Exception e) { throw new SpreadsheetOperationException("Error inserting spreadsheet row: " + e); } return new UpdateResult(1, 1); } }