Java tutorial
/* * Copyright (C) 2012-2013 University of Washington * * 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 org.opendatakit.aggregate.server; import static org.opendatakit.aggregate.server.FileInfoSortType.FILENAME; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.UriBuilder; import org.apache.commons.lang3.StringUtils; import org.opendatakit.aggregate.ContextFactory; import org.opendatakit.aggregate.client.exception.BadColumnNameExceptionClient; import org.opendatakit.aggregate.client.exception.ETagMismatchExceptionClient; import org.opendatakit.aggregate.client.exception.EntityNotFoundExceptionClient; import org.opendatakit.aggregate.client.exception.PermissionDeniedExceptionClient; import org.opendatakit.aggregate.client.exception.RequestFailureException; import org.opendatakit.aggregate.client.odktables.FileSummaryClient; import org.opendatakit.aggregate.client.odktables.RowClient; import org.opendatakit.aggregate.client.odktables.ServerDataService; import org.opendatakit.aggregate.client.odktables.TableContentsClient; import org.opendatakit.aggregate.client.odktables.TableContentsForFilesClient; import org.opendatakit.aggregate.constants.ServletConsts; import org.opendatakit.aggregate.odktables.DataManager; import org.opendatakit.aggregate.odktables.DataManager.WebsafeRows; import org.opendatakit.aggregate.odktables.FileManager; import org.opendatakit.aggregate.odktables.TableManager; import org.opendatakit.aggregate.odktables.api.FileService; import org.opendatakit.aggregate.odktables.api.InstanceFileService; import org.opendatakit.aggregate.odktables.api.OdkTables; import org.opendatakit.aggregate.odktables.api.RealizedTableService; import org.opendatakit.aggregate.odktables.api.TableService; import org.opendatakit.aggregate.odktables.entity.UtilTransforms; import org.opendatakit.aggregate.odktables.exception.BadColumnNameException; import org.opendatakit.aggregate.odktables.exception.ETagMismatchException; import org.opendatakit.aggregate.odktables.exception.InconsistentStateException; import org.opendatakit.aggregate.odktables.exception.PermissionDeniedException; import org.opendatakit.aggregate.odktables.relation.DbColumnDefinitions; import org.opendatakit.aggregate.odktables.relation.DbTableFileInfo; import org.opendatakit.aggregate.odktables.relation.DbTableFiles; import org.opendatakit.aggregate.odktables.relation.DbTableInstanceFiles; import org.opendatakit.aggregate.odktables.rest.entity.Row; import org.opendatakit.aggregate.odktables.rest.entity.TableEntry; import org.opendatakit.aggregate.odktables.rest.entity.TableRole.TablePermission; import org.opendatakit.aggregate.odktables.security.TablesUserPermissions; import org.opendatakit.aggregate.odktables.security.TablesUserPermissionsImpl; import org.opendatakit.common.datamodel.BinaryContent; import org.opendatakit.common.ermodel.BlobEntitySet; import org.opendatakit.common.persistence.DataField; import org.opendatakit.common.persistence.QueryResumePoint; import org.opendatakit.common.persistence.client.exception.DatastoreFailureException; import org.opendatakit.common.persistence.exception.ODKDatastoreException; import org.opendatakit.common.persistence.exception.ODKEntityNotFoundException; import org.opendatakit.common.persistence.exception.ODKTaskLockException; import org.opendatakit.common.security.client.exception.AccessDeniedException; import org.opendatakit.common.web.CallingContext; import org.opendatakit.common.web.constants.BasicConsts; import com.google.gwt.user.server.rpc.RemoteServiceServlet; /** * For ODKTables. * * @author sudar.sam@gmail.com * */ public class ServerDataServiceImpl extends RemoteServiceServlet implements ServerDataService { /** * */ private static final long serialVersionUID = -5051558217315955180L; private WebsafeRows getRows(String tableId, QueryResumePoint resumePoint, String sortColumn, boolean ascending, String officeId) throws AccessDeniedException, RequestFailureException, DatastoreFailureException, PermissionDeniedExceptionClient, EntityNotFoundExceptionClient, BadColumnNameExceptionClient { HttpServletRequest req = this.getThreadLocalRequest(); CallingContext cc = ContextFactory.getCallingContext(this, req); try { // Must use try so that you can catch the ODK specific errors. TablesUserPermissions userPermissions = new TablesUserPermissionsImpl(cc); String appId = ServerPreferencesProperties.getOdkTablesAppId(cc); DataManager dm = new DataManager(appId, tableId, userPermissions, cc); return dm.getRows(resumePoint, 100, sortColumn, ascending, null, officeId); } catch (ODKEntityNotFoundException e) { e.printStackTrace(); throw new EntityNotFoundExceptionClient(e); } catch (ODKDatastoreException e) { e.printStackTrace(); throw new DatastoreFailureException(e); } catch (BadColumnNameException e) { e.printStackTrace(); throw new BadColumnNameExceptionClient(e); } catch (InconsistentStateException e) { e.printStackTrace(); throw new RequestFailureException(e); } catch (ODKTaskLockException e) { e.printStackTrace(); throw new RequestFailureException(e); } catch (PermissionDeniedException e) { e.printStackTrace(); throw new PermissionDeniedExceptionClient(e); } } @Override public TableContentsClient getRow(String tableId, String rowId) throws AccessDeniedException, RequestFailureException, DatastoreFailureException, PermissionDeniedExceptionClient, EntityNotFoundExceptionClient, BadColumnNameExceptionClient { try { HttpServletRequest req = this.getThreadLocalRequest(); CallingContext cc = ContextFactory.getCallingContext(this, req); TablesUserPermissions userPermissions = new TablesUserPermissionsImpl(cc); String appId = ServerPreferencesProperties.getOdkTablesAppId(cc); DataManager dm = new DataManager(appId, tableId, userPermissions, cc); Row row = dm.getRow(rowId); TableContentsClient tcc = new TableContentsClient(); tcc.columnNames = this.getColumnNames(tableId); ArrayList<RowClient> rows = new ArrayList<RowClient>(); rows.add(UtilTransforms.transform(row)); tcc.rows = rows; tcc.websafeBackwardCursor = null; tcc.websafeRefetchCursor = null; tcc.websafeResumeCursor = null; tcc.hasMore = false; tcc.hasPrior = false; return tcc; } catch (ODKEntityNotFoundException e) { e.printStackTrace(); throw new EntityNotFoundExceptionClient(e); } catch (ODKDatastoreException e) { e.printStackTrace(); throw new DatastoreFailureException(e); } catch (InconsistentStateException e) { e.printStackTrace(); throw new RequestFailureException(e); } catch (ODKTaskLockException e) { e.printStackTrace(); throw new RequestFailureException(e); } catch (PermissionDeniedException e) { e.printStackTrace(); throw new PermissionDeniedExceptionClient(e); } catch (BadColumnNameException e) { e.printStackTrace(); throw new BadColumnNameExceptionClient(e); } } @Override public RowClient createOrUpdateRow(String tableId, String rowId, RowClient row) throws AccessDeniedException, RequestFailureException, DatastoreFailureException, ETagMismatchExceptionClient, PermissionDeniedExceptionClient, EntityNotFoundExceptionClient { HttpServletRequest req = this.getThreadLocalRequest(); CallingContext cc = ContextFactory.getCallingContext(this, req); TablesUserPermissions userPermissions; try { userPermissions = new TablesUserPermissionsImpl(cc); String appId = ServerPreferencesProperties.getOdkTablesAppId(cc); return ServerOdkTablesUtil.createOrUpdateRow(appId, tableId, rowId, row, userPermissions, cc); } catch (ODKDatastoreException e) { e.printStackTrace(); throw new DatastoreFailureException(e); } catch (PermissionDeniedException e) { e.printStackTrace(); throw new PermissionDeniedExceptionClient(e); } catch (ODKTaskLockException e) { e.printStackTrace(); throw new RequestFailureException(e); } catch (InconsistentStateException e) { e.printStackTrace(); throw new RequestFailureException(e); } } @Override public void deleteRow(String tableId, String rowId, String rowETag) throws AccessDeniedException, RequestFailureException, DatastoreFailureException, PermissionDeniedExceptionClient, EntityNotFoundExceptionClient, BadColumnNameExceptionClient { HttpServletRequest req = this.getThreadLocalRequest(); CallingContext cc = ContextFactory.getCallingContext(this, req); try { // Must use try so that you can catch the ODK specific errors. TablesUserPermissions userPermissions = new TablesUserPermissionsImpl(cc); String appId = ServerPreferencesProperties.getOdkTablesAppId(cc); DataManager dm = new DataManager(appId, tableId, userPermissions, cc); dm.deleteRow(rowId, rowETag); } catch (ODKEntityNotFoundException e) { e.printStackTrace(); throw new EntityNotFoundExceptionClient(e); } catch (ODKDatastoreException e) { e.printStackTrace(); throw new DatastoreFailureException(e); } catch (PermissionDeniedException e) { e.printStackTrace(); throw new PermissionDeniedExceptionClient(e); } catch (ODKTaskLockException e) { e.printStackTrace(); throw new RequestFailureException(e); } catch (InconsistentStateException e) { e.printStackTrace(); throw new RequestFailureException(e); } catch (BadColumnNameException e) { e.printStackTrace(); throw new BadColumnNameExceptionClient(e); } catch (ETagMismatchException e) { e.printStackTrace(); throw new RequestFailureException(e); } } /** * Gets the element_keys of the columns. The element_names are insufficient * for displaying the row contents. * * @return List<String> of the column names * @throws PermissionDeniedExceptionClient * @throws RequestFailureException */ @Override public ArrayList<String> getColumnNames(String tableId) throws DatastoreFailureException, EntityNotFoundExceptionClient, PermissionDeniedExceptionClient, RequestFailureException { HttpServletRequest req = this.getThreadLocalRequest(); CallingContext cc = ContextFactory.getCallingContext(this, req); try { TablesUserPermissions userPermissions = new TablesUserPermissionsImpl(cc); String appId = ServerPreferencesProperties.getOdkTablesAppId(cc); TableManager tm = new TableManager(appId, userPermissions, cc); TableEntry entry = tm.getTable(tableId); if (entry == null || entry.getSchemaETag() == null) { throw new ODKEntityNotFoundException(); } ArrayList<String> elementKeys = DbColumnDefinitions.queryForDbColumnNames(tableId, entry.getSchemaETag(), cc); return elementKeys; } catch (ODKEntityNotFoundException e) { e.printStackTrace(); throw new EntityNotFoundExceptionClient(e); } catch (ODKDatastoreException e) { e.printStackTrace(); throw new DatastoreFailureException(e); } catch (ODKTaskLockException e) { e.printStackTrace(); throw new RequestFailureException(e); } catch (PermissionDeniedException e) { e.printStackTrace(); throw new PermissionDeniedExceptionClient(e); } } /* * don't think i need this, but i'm keeping it so that i can use the code for * a reference later if i need to. * * /** Gets ALL the column names, keeping the user-defined ones pretty. * * @param rows * * @return */ /* * Uses the other getColumnNames, which gets the pretty ones. Gets all the * names, removes the "TABLE_UUID_.*" ones, and then adds them back in after * being translated to the pretty ones. * * @Override public List<String> getAllColumnNames(String tableId) throws * DatastoreFailureException { HttpServletRequest req = * this.getThreadLocalRequest(); CallingContext cc = * ContextFactory.getCallingContext(this, req); try { // Must use try so that * you can catch the ODK specific errors. DataManager dm = new * DataManager(tableId, cc); AuthFilter af = new AuthFilter(tableId, cc); * Set<DataField> dataFields = DbTable.getRelation(tableId, * cc).getDataFields(); * * // TODO: look into seeing if you need to have a scope on column names. // * TODO: see if there is a better way to remove the pretty ones, or make // * sure that you can't name a column TABLE_UUID_ List<String> columnNames = * getColumnNames(tableId); for (DataField df : dataFields) { // don't add if * it starts with this, as you'll add it later if (!df.getName().substring(0, * 11).equals("TABLE_UUID_")) { columnNames.add(df.getName()); } } * * return columnNames; } catch (ODKDatastoreException e) { * e.printStackTrace(); throw new DatastoreFailureException(e); } } */ private ArrayList<RowClient> transformRows(List<Row> rows) { ArrayList<RowClient> clientRows = new ArrayList<RowClient>(); for (Row row : rows) { clientRows.add(UtilTransforms.transform(row)); } return clientRows; } /** * Get the list of columns that are in the DbTableFileInfo table. This is * defined in server code and thus is never in danger of throwing * DatastoreExceptions. */ @Override public ArrayList<String> getFileRowInfoColumnNames() { List<DataField> exposedColumnNames = DbTableFileInfo.exposedColumnNames; ArrayList<String> columnNames = new ArrayList<String>(); for (DataField f : exposedColumnNames) { columnNames.add(f.getName()); } return columnNames; } @Override public TableContentsClient getTableContents(String tableId, String resumeCursor, String officeId) throws AccessDeniedException, RequestFailureException, DatastoreFailureException, PermissionDeniedExceptionClient, EntityNotFoundExceptionClient, BadColumnNameExceptionClient { return getSortedTableContents(tableId, resumeCursor, null, false, officeId); } @Override public TableContentsClient getSortedTableContents(String tableId, String resumeCursor, String sortColumn, boolean ascending, String officeId) throws AccessDeniedException, RequestFailureException, DatastoreFailureException, PermissionDeniedExceptionClient, EntityNotFoundExceptionClient, BadColumnNameExceptionClient { TableContentsClient tcc = new TableContentsClient(); WebsafeRows websafeResult = getRows(tableId, QueryResumePoint.fromWebsafeCursor(resumeCursor), sortColumn, ascending, officeId); List<Row> rows = websafeResult.rows; tcc.rows = transformRows(rows); tcc.columnNames = getColumnNames(tableId); tcc.websafeBackwardCursor = websafeResult.websafeBackwardCursor; tcc.websafeRefetchCursor = websafeResult.websafeRefetchCursor; tcc.websafeResumeCursor = websafeResult.websafeResumeCursor; tcc.hasMore = websafeResult.hasMore; tcc.hasPrior = websafeResult.hasPrior; return tcc; } /** * This method more or less gets the user-friendly data to be displayed. It * adds the correct filename and returns only the non-deleted rows. */ @Override public TableContentsForFilesClient getAppLevelFileInfoContents(String sortColumn, boolean ascending) throws AccessDeniedException, RequestFailureException, DatastoreFailureException, PermissionDeniedExceptionClient, EntityNotFoundExceptionClient { TableContentsForFilesClient tcc = new TableContentsForFilesClient(); HttpServletRequest req = this.getThreadLocalRequest(); CallingContext cc = ContextFactory.getCallingContext(this, req); try { TablesUserPermissions userPermissions = new TablesUserPermissionsImpl(cc); String appId = ServerPreferencesProperties.getOdkTablesAppId(cc); TableManager tm = new TableManager(appId, userPermissions, cc); List<DbTableFileInfo.DbTableFileInfoEntity> entities = DbTableFileInfo .queryForAllOdkClientVersionsOfAppLevelFiles(cc); DbTableFiles dbTableFiles = new DbTableFiles(cc); UriBuilder ub; try { ub = UriBuilder.fromUri(new URI( cc.getServerURL() + BasicConsts.FORWARDSLASH + ServletConsts.ODK_TABLES_SERVLET_BASE_PATH)); } catch (URISyntaxException e) { e.printStackTrace(); throw new RequestFailureException(e); } ub.path(OdkTables.class, "getFilesService"); ArrayList<FileSummaryClient> completedSummaries = new ArrayList<FileSummaryClient>(); for (DbTableFileInfo.DbTableFileInfoEntity entry : entities) { BlobEntitySet blobEntitySet = dbTableFiles.getBlobEntitySet(entry.getId(), cc); if (blobEntitySet.getAttachmentCount(cc) != 1) { continue; } String odkClientVersion = entry.getOdkClientVersion(); UriBuilder tmp = ub.clone().path(FileService.class, "getFile"); URI getFile = tmp.build(appId, odkClientVersion, entry.getPathToFile()); String downloadUrl; try { downloadUrl = getFile.toURL().toExternalForm() + "?" + FileService.PARAM_AS_ATTACHMENT + "=true"; } catch (MalformedURLException e) { e.printStackTrace(); throw new RequestFailureException("Unable to convert to URL"); } FileSummaryClient sum = new FileSummaryClient(entry.getPathToFile(), blobEntitySet.getContentType(1, cc), blobEntitySet.getContentLength(1, cc), entry.getId(), odkClientVersion, "", downloadUrl); completedSummaries.add(sum); } Comparator<FileSummaryClient> columnSorter = FILENAME.getAscendingSort(); if (StringUtils.isNotEmpty(sortColumn)) { FileInfoSortType columnType = FileInfoSortType.fromDbColumn(sortColumn); if (columnType != null) { if (ascending) { columnSorter = columnType.getAscendingSort(); } else { columnSorter = columnType.getDescendingSort(); } } } Collections.sort(completedSummaries, columnSorter); tcc.files = completedSummaries; return tcc; } catch (ODKEntityNotFoundException e) { e.printStackTrace(); throw new EntityNotFoundExceptionClient(e); } catch (ODKDatastoreException e) { e.printStackTrace(); throw new DatastoreFailureException(e); } catch (ODKTaskLockException e) { e.printStackTrace(); throw new RequestFailureException(e); } catch (PermissionDeniedException e) { e.printStackTrace(); throw new PermissionDeniedExceptionClient(e); } } /** * This method more or less gets the user-friendly data to be displayed. It * adds the correct filename and returns only the non-deleted rows. */ @Override public TableContentsForFilesClient getTableFileInfoContents(String tableId, String sortColumn, boolean ascending) throws AccessDeniedException, RequestFailureException, DatastoreFailureException, PermissionDeniedExceptionClient, EntityNotFoundExceptionClient { TableContentsForFilesClient tcc = new TableContentsForFilesClient(); HttpServletRequest req = this.getThreadLocalRequest(); CallingContext cc = ContextFactory.getCallingContext(this, req); try { TablesUserPermissions userPermissions = new TablesUserPermissionsImpl(cc); String appId = ServerPreferencesProperties.getOdkTablesAppId(cc); TableManager tm = new TableManager(appId, userPermissions, cc); TableEntry table = tm.getTable(tableId); if (table == null || table.getSchemaETag() == null) { // you couldn't find // the table throw new ODKEntityNotFoundException(); } List<DbTableFileInfo.DbTableFileInfoEntity> entities = DbTableFileInfo .queryForAllOdkClientVersionsOfTableIdFiles(table.getTableId(), cc); DbTableFiles dbTableFiles = new DbTableFiles(cc); UriBuilder ub; try { ub = UriBuilder.fromUri(new URI( cc.getServerURL() + BasicConsts.FORWARDSLASH + ServletConsts.ODK_TABLES_SERVLET_BASE_PATH)); } catch (URISyntaxException e) { e.printStackTrace(); throw new RequestFailureException(e); } ub.path(OdkTables.class, "getFilesService"); ArrayList<FileSummaryClient> completedSummaries = new ArrayList<FileSummaryClient>(); for (DbTableFileInfo.DbTableFileInfoEntity entry : entities) { BlobEntitySet blobEntitySet = dbTableFiles.getBlobEntitySet(entry.getId(), cc); if (blobEntitySet.getAttachmentCount(cc) != 1) { continue; } String odkClientVersion = entry.getOdkClientVersion(); UriBuilder tmp = ub.clone().path(FileService.class, "getFile"); URI getFile = tmp.build(appId, odkClientVersion, entry.getPathToFile()); String downloadUrl; try { downloadUrl = getFile.toURL().toExternalForm() + "?" + FileService.PARAM_AS_ATTACHMENT + "=true"; } catch (MalformedURLException e) { e.printStackTrace(); throw new RequestFailureException("Unable to convert to URL"); } FileSummaryClient sum = new FileSummaryClient(entry.getPathToFile(), blobEntitySet.getContentType(1, cc), blobEntitySet.getContentLength(1, cc), entry.getId(), odkClientVersion, tableId, downloadUrl); completedSummaries.add(sum); } Comparator<FileSummaryClient> columnSorter = FILENAME.getAscendingSort(); if (StringUtils.isNotEmpty(sortColumn)) { FileInfoSortType columnType = FileInfoSortType.fromDbColumn(sortColumn); if (columnType != null) { if (ascending) { columnSorter = columnType.getAscendingSort(); } else { columnSorter = columnType.getDescendingSort(); } } } Collections.sort(completedSummaries, columnSorter); tcc.files = completedSummaries; return tcc; } catch (ODKEntityNotFoundException e) { e.printStackTrace(); throw new EntityNotFoundExceptionClient(e); } catch (ODKDatastoreException e) { e.printStackTrace(); throw new DatastoreFailureException(e); } catch (ODKTaskLockException e) { e.printStackTrace(); throw new RequestFailureException(e); } catch (PermissionDeniedException e) { e.printStackTrace(); throw new PermissionDeniedExceptionClient(e); } } /** * This method more or less gets the user-friendly data to be displayed. It * adds the correct filename and returns only the non-deleted rows. */ @Override public TableContentsForFilesClient getInstanceFileInfoContents(String tableId, String sortColumn, boolean ascending) throws AccessDeniedException, RequestFailureException, DatastoreFailureException, PermissionDeniedExceptionClient, EntityNotFoundExceptionClient { TableContentsForFilesClient tcc = new TableContentsForFilesClient(); HttpServletRequest req = this.getThreadLocalRequest(); CallingContext cc = ContextFactory.getCallingContext(this, req); try { TablesUserPermissions userPermissions = new TablesUserPermissionsImpl(cc); String appId = ServerPreferencesProperties.getOdkTablesAppId(cc); TableManager tm = new TableManager(appId, userPermissions, cc); TableEntry table = tm.getTable(tableId); if (table == null || table.getSchemaETag() == null) { // you couldn't find // the table throw new ODKEntityNotFoundException(); } String schemaETag = table.getSchemaETag(); DbTableInstanceFiles blobStore = new DbTableInstanceFiles(tableId, cc); List<BinaryContent> contents = blobStore.getAllBinaryContents(cc); UriBuilder ub; try { ub = UriBuilder.fromUri(new URI( cc.getServerURL() + BasicConsts.FORWARDSLASH + ServletConsts.ODK_TABLES_SERVLET_BASE_PATH)); } catch (URISyntaxException e) { e.printStackTrace(); throw new RequestFailureException(e); } ub.path(OdkTables.class, "getTablesService"); ArrayList<FileSummaryClient> completedSummaries = new ArrayList<FileSummaryClient>(); for (BinaryContent entry : contents) { if (entry.getUnrootedFilePath() == null) { continue; } // the rowId is the top-level auri for this record String rowId = entry.getTopLevelAuri(); UriBuilder tmp = ub.clone().path(TableService.class, "getRealizedTable") .path(RealizedTableService.class, "getInstanceFiles") .path(InstanceFileService.class, "getFile"); URI getFile = tmp.build(appId, tableId, schemaETag, rowId, entry.getUnrootedFilePath()); String downloadUrl = getFile.toASCIIString() + "?" + FileService.PARAM_AS_ATTACHMENT + "=true"; FileSummaryClient sum = new FileSummaryClient(entry.getUnrootedFilePath(), entry.getContentType(), entry.getContentLength(), entry.getUri(), null, tableId, downloadUrl); sum.setInstanceId(entry.getTopLevelAuri()); completedSummaries.add(sum); } Comparator<FileSummaryClient> columnSorter = FILENAME.getAscendingSort(); if (StringUtils.isNotEmpty(sortColumn)) { FileInfoSortType columnType = FileInfoSortType.fromDbColumn(sortColumn); if (columnType != null) { if (ascending) { columnSorter = columnType.getAscendingSort(); } else { columnSorter = columnType.getDescendingSort(); } } } Collections.sort(completedSummaries, columnSorter); tcc.files = completedSummaries; return tcc; } catch (ODKEntityNotFoundException e) { e.printStackTrace(); throw new EntityNotFoundExceptionClient(e); } catch (ODKDatastoreException e) { e.printStackTrace(); throw new DatastoreFailureException(e); } catch (ODKTaskLockException e) { e.printStackTrace(); throw new RequestFailureException(e); } catch (PermissionDeniedException e) { e.printStackTrace(); throw new PermissionDeniedExceptionClient(e); } } @Override public void deleteAppLevelFile(String odkClientApiVersion, String filepath) throws AccessDeniedException, RequestFailureException, DatastoreFailureException, PermissionDeniedExceptionClient, EntityNotFoundExceptionClient { HttpServletRequest req = this.getThreadLocalRequest(); CallingContext cc = ContextFactory.getCallingContext(this, req); try { TablesUserPermissions userPermissions = new TablesUserPermissionsImpl(cc); String appId = ServerPreferencesProperties.getOdkTablesAppId(cc); FileManager fm = new FileManager(appId, cc); fm.deleteFile(odkClientApiVersion, DbTableFileInfo.NO_TABLE_ID, filepath); return; } catch (ODKEntityNotFoundException e) { e.printStackTrace(); throw new EntityNotFoundExceptionClient(e); } catch (ODKDatastoreException e) { e.printStackTrace(); throw new DatastoreFailureException(e); } catch (ODKTaskLockException e) { e.printStackTrace(); throw new RequestFailureException(e); } catch (PermissionDeniedException e) { e.printStackTrace(); throw new PermissionDeniedExceptionClient(e); } } @Override public void deleteTableFile(String odkClientApiVersion, String tableId, String filepath) throws AccessDeniedException, RequestFailureException, DatastoreFailureException, PermissionDeniedExceptionClient, EntityNotFoundExceptionClient { HttpServletRequest req = this.getThreadLocalRequest(); CallingContext cc = ContextFactory.getCallingContext(this, req); try { TablesUserPermissions userPermissions = new TablesUserPermissionsImpl(cc); String appId = ServerPreferencesProperties.getOdkTablesAppId(cc); userPermissions.checkPermission(appId, tableId, TablePermission.WRITE_PROPERTIES); FileManager fm = new FileManager(appId, cc); fm.deleteFile(odkClientApiVersion, tableId, filepath); return; } catch (ODKEntityNotFoundException e) { e.printStackTrace(); throw new EntityNotFoundExceptionClient(e); } catch (ODKDatastoreException e) { e.printStackTrace(); throw new DatastoreFailureException(e); } catch (ODKTaskLockException e) { e.printStackTrace(); throw new RequestFailureException(e); } catch (PermissionDeniedException e) { e.printStackTrace(); throw new PermissionDeniedExceptionClient(e); } } @Override public void deleteInstanceFile(String tableId, String instanceId, String filepath) throws AccessDeniedException, RequestFailureException, DatastoreFailureException, PermissionDeniedExceptionClient, EntityNotFoundExceptionClient { TableContentsForFilesClient tcc = new TableContentsForFilesClient(); HttpServletRequest req = this.getThreadLocalRequest(); CallingContext cc = ContextFactory.getCallingContext(this, req); try { TablesUserPermissions userPermissions = new TablesUserPermissionsImpl(cc); String appId = ServerPreferencesProperties.getOdkTablesAppId(cc); TableManager tm = new TableManager(appId, userPermissions, cc); TableEntry table = tm.getTable(tableId); if (table == null || table.getSchemaETag() == null) { // you couldn't find // the table throw new ODKEntityNotFoundException(); } DbTableInstanceFiles blobStore = new DbTableInstanceFiles(tableId, cc); BlobEntitySet blobEntitySet = blobStore.getBlobEntitySet(instanceId, cc); if (blobEntitySet.getAttachmentCount(cc) < 1) { return; } blobEntitySet.remove(cc); return; } catch (ODKEntityNotFoundException e) { e.printStackTrace(); throw new EntityNotFoundExceptionClient(e); } catch (ODKDatastoreException e) { e.printStackTrace(); throw new DatastoreFailureException(e); } catch (ODKTaskLockException e) { e.printStackTrace(); throw new RequestFailureException(e); } catch (PermissionDeniedException e) { e.printStackTrace(); throw new PermissionDeniedExceptionClient(e); } } }