List of usage examples for java.sql Blob getBinaryStream
java.io.InputStream getBinaryStream() throws SQLException;
From source file:com.eryansky.common.utils.SysUtils.java
/** * Blobbyte[]/* ww w. j av a 2 s . c o m*/ * * @param blob * @return * @author &Eryan eryanwcp@gmail.com */ public static byte[] blobToBytes(Blob blob) { BufferedInputStream is = null; try { is = new BufferedInputStream(blob.getBinaryStream()); byte[] bytes = new byte[(int) blob.length()]; int len = bytes.length; int offset = 0; int read = 0; while (offset < len && (read = is.read(bytes, offset, len - offset)) >= 0) { offset += read; } return bytes; } catch (Exception e) { return null; } finally { try { is.close(); is = null; } catch (IOException e) { return null; } } }
From source file:org.bytesoft.openjtcc.supports.logger.DbTransactionLoggerImpl.java
private Map<XidImpl, CompensableArchive> loadNativeService(Connection connection) { Map<XidImpl, CompensableArchive> serviceMap = new HashMap<XidImpl, CompensableArchive>(); PreparedStatement stmt = null; ResultSet rs = null;/*from ww w .j av a 2s . co m*/ try { StringBuilder ber = new StringBuilder(); ber.append("select s.global_tx_id, s.branch_qualifier, s.coordinator, s.bean_name, s.variable"); ber.append(", s.try_committed, s.confirmed, s.cancelled, s.committed, s.rolledback "); ber.append("from tcc_compensable s "); ber.append("left join tcc_transaction t on ("); ber.append(" t.application = s.application "); ber.append(" and t.endpoint = s.endpoint "); ber.append(" and t.global_tx_id = s.global_tx_id "); ber.append(") where s.application = ? and s.endpoint = ? and t.deleted = ?"); stmt = connection.prepareStatement(ber.toString()); stmt.setString(1, this.instanceKey.getApplication()); stmt.setString(2, this.instanceKey.getEndpoint()); stmt.setBoolean(3, false); rs = stmt.executeQuery(); while (rs.next()) { String globalTransactionId = rs.getString("global_tx_id"); String branchQualifier = rs.getString("branch_qualifier"); boolean coordinator = rs.getBoolean("coordinator"); String beanName = rs.getString("bean_name"); CompensableArchive holder = new CompensableArchive(); holder.launchSvc = coordinator; byte[] globalBytes = ByteUtils.stringToByteArray(globalTransactionId); XidImpl globalXid = this.xidFactory.createGlobalXid(globalBytes); if (coordinator) { holder.branchXid = globalXid; } else { byte[] branchBytes = ByteUtils.stringToByteArray(branchQualifier); XidImpl branchXid = this.xidFactory.createBranchXid(globalXid, branchBytes); holder.branchXid = branchXid; } boolean tryCommitted = rs.getBoolean("try_committed"); boolean confirmed = rs.getBoolean("confirmed"); boolean cancelled = rs.getBoolean("cancelled"); boolean committed = rs.getBoolean("committed"); boolean rolledback = rs.getBoolean("rolledback"); holder.tryCommitted = tryCommitted; holder.confirmed = confirmed; holder.cancelled = cancelled; holder.committed = committed; holder.rolledback = rolledback; CompensableInfo info = new CompensableInfo(); info.setIdentifier(beanName); Compensable<Serializable> service = this.compensableMarshaller.unmarshallCompensable(info); holder.service = service; Blob blob = rs.getBlob("variable"); Serializable variable = null; if (blob != null) { InputStream input = blob.getBinaryStream(); if (input != null) { byte[] bytes = this.streamToByteArray(input); try { variable = (Serializable) this.serializer.deserialize(bytes); } catch (IOException e) { // ignore } } } holder.variable = variable; serviceMap.put(globalXid, holder); } } catch (Exception ex) { ex.printStackTrace(); } finally { closeResultSet(rs); closeStatement(stmt); } return serviceMap; }
From source file:it.greenvulcano.gvesb.datahandling.dbo.utils.StandardRowSetBuilder.java
public int build(Document doc, String id, ResultSet rs, Set<Integer> keyField, Map<String, FieldFormatter> fieldNameToFormatter, Map<String, FieldFormatter> fieldIdToFormatter) throws Exception { if (rs == null) { return 0; }// ww w . j ava2 s.com int rowCounter = 0; Element docRoot = doc.getDocumentElement(); ResultSetMetaData metadata = rs.getMetaData(); FieldFormatter[] fFormatters = buildFormatterArray(metadata, fieldNameToFormatter, fieldIdToFormatter); boolean noKey = ((keyField == null) || keyField.isEmpty()); //boolean isNull = false; Element data = null; Element row = null; Element col = null; Text text = null; String textVal = null; String precKey = null; String colKey = null; Map<String, String> keyAttr = new HashMap<String, String>(); while (rs.next()) { if (rowCounter % 10 == 0) { ThreadUtils.checkInterrupted(getClass().getSimpleName(), name, logger); } row = parser.createElement(doc, AbstractDBO.ROW_NAME); parser.setAttribute(row, AbstractDBO.ID_NAME, id); for (int j = 1; j <= metadata.getColumnCount(); j++) { FieldFormatter fF = fFormatters[j]; //isNull = false; col = parser.createElement(doc, AbstractDBO.COL_NAME); switch (metadata.getColumnType(j)) { case Types.DATE: { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.DATE_TYPE); java.sql.Date dateVal = rs.getDate(j); textVal = processDateTime(col, fF, dateVal, AbstractDBO.DEFAULT_DATE_FORMAT); } break; case Types.TIME: { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.TIME_TYPE); java.sql.Time dateVal = rs.getTime(j); textVal = processDateTime(col, fF, dateVal, AbstractDBO.DEFAULT_TIME_FORMAT); } break; case Types.TIMESTAMP: { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.TIMESTAMP_TYPE); Timestamp dateVal = rs.getTimestamp(j); textVal = processDateTime(col, fF, dateVal, AbstractDBO.DEFAULT_DATE_FORMAT); } break; case Types.DOUBLE: { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.FLOAT_TYPE); double numVal = rs.getDouble(j); textVal = processDouble(col, fF, numVal); } break; case Types.FLOAT: case Types.REAL: { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.FLOAT_TYPE); float numVal = rs.getFloat(j); textVal = processDouble(col, fF, numVal); } break; case Types.BIGINT: { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.BIGINT_TYPE); long numVal = rs.getLong(j); parser.setAttribute(col, AbstractDBO.NULL_NAME, "false"); textVal = String.valueOf(numVal); } break; case Types.INTEGER: { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.INTEGER_TYPE); int numVal = rs.getInt(j); parser.setAttribute(col, AbstractDBO.NULL_NAME, "false"); textVal = String.valueOf(numVal); } break; case Types.SMALLINT: case Types.TINYINT: { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.SMALLINT_TYPE); short numVal = rs.getShort(j); parser.setAttribute(col, AbstractDBO.NULL_NAME, "false"); textVal = String.valueOf(numVal); } break; case Types.NUMERIC: case Types.DECIMAL: { BigDecimal bigdecimal = rs.getBigDecimal(j); boolean isNull = bigdecimal == null; parser.setAttribute(col, AbstractDBO.NULL_NAME, String.valueOf(isNull)); if (isNull) { if (metadata.getScale(j) > 0) { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.DECIMAL_TYPE); } else { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.NUMERIC_TYPE); } textVal = ""; } else { if (fF != null) { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.DECIMAL_TYPE); parser.setAttribute(col, AbstractDBO.FORMAT_NAME, fF.getNumberFormat()); parser.setAttribute(col, AbstractDBO.GRP_SEPARATOR_NAME, fF.getGroupSeparator()); parser.setAttribute(col, AbstractDBO.DEC_SEPARATOR_NAME, fF.getDecSeparator()); textVal = fF.formatNumber(bigdecimal); } else if (metadata.getScale(j) > 0) { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.DECIMAL_TYPE); parser.setAttribute(col, AbstractDBO.FORMAT_NAME, numberFormat); parser.setAttribute(col, AbstractDBO.GRP_SEPARATOR_NAME, groupSeparator); parser.setAttribute(col, AbstractDBO.DEC_SEPARATOR_NAME, decSeparator); textVal = numberFormatter.format(bigdecimal); } else { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.NUMERIC_TYPE); textVal = bigdecimal.toString(); } } } break; case Types.BOOLEAN: { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.BOOLEAN_TYPE); boolean bVal = rs.getBoolean(j); parser.setAttribute(col, AbstractDBO.NULL_NAME, "false"); textVal = String.valueOf(bVal); } break; case Types.SQLXML: { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.XML_TYPE); SQLXML xml = rs.getSQLXML(j); boolean isNull = xml == null; parser.setAttribute(col, AbstractDBO.NULL_NAME, String.valueOf(isNull)); if (isNull) { textVal = ""; } else { textVal = xml.getString(); } } break; case Types.NCHAR: case Types.NVARCHAR: { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.NSTRING_TYPE); textVal = rs.getNString(j); if (textVal == null) { textVal = ""; } } break; case Types.CHAR: case Types.VARCHAR: { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.STRING_TYPE); textVal = rs.getString(j); boolean isNull = textVal == null; parser.setAttribute(col, AbstractDBO.NULL_NAME, String.valueOf(isNull)); if (isNull) { textVal = ""; } } break; case Types.NCLOB: { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.LONG_NSTRING_TYPE); NClob clob = rs.getNClob(j); if (clob != null) { Reader is = clob.getCharacterStream(); StringWriter str = new StringWriter(); IOUtils.copy(is, str); is.close(); textVal = str.toString(); } else { textVal = ""; } } break; case Types.CLOB: { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.LONG_STRING_TYPE); Clob clob = rs.getClob(j); if (clob != null) { Reader is = clob.getCharacterStream(); StringWriter str = new StringWriter(); IOUtils.copy(is, str); is.close(); textVal = str.toString(); } else { textVal = ""; } } break; case Types.BLOB: { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.BASE64_TYPE); Blob blob = rs.getBlob(j); boolean isNull = blob == null; parser.setAttribute(col, AbstractDBO.NULL_NAME, String.valueOf(isNull)); if (isNull) { textVal = ""; } else { InputStream is = blob.getBinaryStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); IOUtils.copy(is, baos); is.close(); try { byte[] buffer = Arrays.copyOf(baos.toByteArray(), (int) blob.length()); textVal = Base64.getEncoder().encodeToString(buffer); } catch (SQLFeatureNotSupportedException exc) { textVal = Base64.getEncoder().encodeToString(baos.toByteArray()); } } } break; default: { parser.setAttribute(col, AbstractDBO.TYPE_NAME, AbstractDBO.DEFAULT_TYPE); textVal = rs.getString(j); boolean isNull = textVal == null; parser.setAttribute(col, AbstractDBO.NULL_NAME, String.valueOf(isNull)); if (isNull) { textVal = ""; } } } if (textVal != null) { text = doc.createTextNode(textVal); col.appendChild(text); } if (!noKey && keyField.contains(new Integer(j))) { if (textVal != null) { if (colKey == null) { colKey = textVal; } else { colKey += "##" + textVal; } keyAttr.put("key_" + j, textVal); } } else { row.appendChild(col); } } if (noKey) { if (data == null) { data = parser.createElement(doc, AbstractDBO.DATA_NAME); parser.setAttribute(data, AbstractDBO.ID_NAME, id); } } else if ((colKey != null) && !colKey.equals(precKey)) { if (data != null) { docRoot.appendChild(data); } data = parser.createElement(doc, AbstractDBO.DATA_NAME); parser.setAttribute(data, AbstractDBO.ID_NAME, id); for (Entry<String, String> keyAttrEntry : keyAttr.entrySet()) { parser.setAttribute(data, keyAttrEntry.getKey(), keyAttrEntry.getValue()); } keyAttr.clear(); precKey = colKey; } colKey = null; data.appendChild(row); rowCounter++; } if (data != null) { docRoot.appendChild(data); } return rowCounter; }
From source file:info.raack.appliancelabeler.data.JDBCDatabase.java
public Map<String, Map<String, OAuthConsumerToken>> getOAuthTokensForAllUsers() { try {// www .ja v a 2 s . co m List<UserOAuthTokenCarrier> carriers = jdbcTemplate.query(queryForAllUserOAuthTokens, new RowMapper<UserOAuthTokenCarrier>() { public UserOAuthTokenCarrier mapRow(ResultSet rs, int arg1) throws SQLException { UserOAuthTokenCarrier token = new UserOAuthTokenCarrier(); token.userId = rs.getString("user_id"); Blob blob = rs.getBlob("spring_oauth_serialized_token_map"); Object tokenObject = SerializationUtils.deserialize(blob.getBinaryStream()); Map<String, OAuthConsumerToken> tokens = (Map<String, OAuthConsumerToken>) tokenObject; token.tokens = tokens; return token; } }); Map<String, Map<String, OAuthConsumerToken>> tokens = new HashMap<String, Map<String, OAuthConsumerToken>>(); for (UserOAuthTokenCarrier carrier : carriers) { tokens.put(carrier.userId, carrier.tokens); } return tokens; } catch (Exception e) { throw new RuntimeException("Error while getting user tokens", e); } }
From source file:info.raack.appliancelabeler.data.JDBCDatabase.java
@Override public Map<String, OAuthConsumerToken> getOAuthTokensForUserId(String userId) { Map<String, OAuthConsumerToken> tokens = new HashMap<String, OAuthConsumerToken>(); try {//from ww w . j a v a 2 s .c o m Blob blob = jdbcTemplate.queryForObject(getAccessTokensForUser, new Object[] { userId }, Blob.class); try { Object tokenObject = SerializationUtils.deserialize(blob.getBinaryStream()); tokens = (Map<String, OAuthConsumerToken>) tokenObject; } catch (Exception e) { throw new RuntimeException("Could not deserialize tokens for user id " + userId, e); } } catch (EmptyResultDataAccessException e) { logger.debug("No oauth tokens for " + userId); } return tokens; }
From source file:com.p5solutions.core.jpa.orm.oracle.ConversionUtilityImpl.java
/** * To blob.//from w w w .ja v a 2s. c om * * @param pb * the pb * @param value * the value * @param targetType * the target type * @return the object */ private Object toJavaBlob(ParameterBinder pb, Object value, Class<?> targetType) { if (value instanceof Blob) { boolean isBlob = ReflectionUtility.isBlob(targetType); boolean isInputStream = ReflectionUtility.isInputStream(targetType); boolean isByteArray = ReflectionUtility.isByteArray(targetType); boolean isString = ReflectionUtility.isStringClass(targetType); Blob blob = (Blob) value; // if the target entity->property is of blob, return quickly. if (isBlob) { return blob; } try { // if the target is a string, then convert the buffer if (isString) { // if the target entity->property is a string int length = (int) blob.length(); byte[] ba = blob.getBytes(0L, length); return new String(ba, charset); } else if (isByteArray) { // if the target entity->property is a byte array int length = (int) blob.length(); byte[] ba = blob.getBytes(0L, length); return ba; } else if (isInputStream) { return blob.getBinaryStream(); } else if (BlobStream.class.isAssignableFrom(targetType)) { BlobStream bs = new BlobStream(blob.getBinaryStream()); return bs; } } catch (Exception e) { logger.error("Unable to copy data from blob stream into target byte array on entity " + pb.getEntityClass() + " paramater " + pb.getBindingPath() + " and column " + pb.getColumnName()); } } return null; }
From source file:de.hska.ld.content.controller.DocumentController.java
/** * This resource allows downloading a file attachment. * <p>//from w w w . j a va2 s.c o m * <pre> * <b>Required roles:</b> ROLE_USER * <b>Path</b> GET /api/documents/{documentId}/download/{attachmentId} * </pre> * * @param documentId the ID of the document that contains the needed attachment * @param attachmentId the attachment id of the attachment that shall be retrieved * @param response <b>FILE DOWNLOAD INITIATED</b> if the attachment could be found, and the download is starting<br> * <b>400 BAD REQUEST</b><br> * <b>403 FORBIDDEN</b> if the access to this attachment has been denied<br> * <b>404 NOT FOUND</b> if no attachment has been found for the given document ID or attachment position<br> * <b>500 Internal Server Error</b> if there occurred any other server side issue */ @Secured(Core.ROLE_USER) @RequestMapping(method = RequestMethod.GET, value = "/{documentId}/download/{attachmentId}") @Transactional(readOnly = true) public Callable downloadFile(@PathVariable Long documentId, @PathVariable Long attachmentId, HttpServletResponse response) { return () -> { try { Attachment attachment = documentService.getAttachmentByAttachmentId(documentId, attachmentId); try { LoggingContext.put("user_email", EscapeUtil.escapeJsonForLogging(Core.currentUser().getEmail())); LoggingContext.put("attachmentId", EscapeUtil.escapeJsonForLogging(attachment.getId().toString())); Logger.trace("User downloads file (2)."); } catch (Exception e) { Logger.error(e); } finally { LoggingContext.clear(); } InputStream is = null; if (attachment.getFileBlobBean() != null && attachment.getFileBlobBean().getSourceBlob() != null) { Blob blob = attachment.getFileBlobBean().getSourceBlob(); is = blob.getBinaryStream(); response.setContentLength((int) blob.length()); } else { byte[] source = attachment.getSource(); if (source != null) { is = new ByteArrayInputStream(source); } else { throw new NotFoundException("source"); } } response.setContentType(attachment.getMimeType()); String fileName = URLEncoder.encode(attachment.getName(), "UTF-8"); fileName = URLDecoder.decode(fileName, "ISO8859_1"); //response.setContentType("application/x-msdownload"); response.setHeader("Content-disposition", "attachment; filename=" + fileName); OutputStream outputStream = response.getOutputStream(); IOUtils.copy(is, outputStream); } catch (IOException e) { response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } return null; }; }
From source file:DisplayBlobServlet.java
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { Blob photo = null; Connection conn = null;//from ww w . j av a2 s . com Statement stmt = null; ResultSet rs = null; String query = "select photo from MyPictures where id = '001'"; ServletOutputStream out = response.getOutputStream(); try { conn = getHSQLConnection(); } catch (Exception e) { response.setContentType("text/html"); out.println("<html><head><title>Person Photo</title></head>"); out.println("<body><h1>Database Connection Problem.</h1></body></html>"); return; } try { stmt = conn.createStatement(); rs = stmt.executeQuery(query); if (rs.next()) { photo = rs.getBlob(1); } else { response.setContentType("text/html"); out.println("<html><head><title>Person Photo</title></head>"); out.println("<body><h1>No photo found for id= 001 </h1></body></html>"); return; } response.setContentType("image/gif"); InputStream in = photo.getBinaryStream(); int length = (int) photo.length(); int bufferSize = 1024; byte[] buffer = new byte[bufferSize]; while ((length = in.read(buffer)) != -1) { System.out.println("writing " + length + " bytes"); out.write(buffer, 0, length); } in.close(); out.flush(); } catch (SQLException e) { response.setContentType("text/html"); out.println("<html><head><title>Error: Person Photo</title></head>"); out.println("<body><h1>Error=" + e.getMessage() + "</h1></body></html>"); return; } finally { try { rs.close(); stmt.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } }
From source file:com.streamsets.pipeline.lib.jdbc.JdbcUtil.java
private byte[] getBlobBytes(Blob data, int maxBlobSize) throws IOException, SQLException { if (data == null) { return null; }//from w ww . java 2 s .c o m ByteArrayOutputStream os = new ByteArrayOutputStream(); int bufLen = 1024; byte[] buf = new byte[bufLen]; // Read up to max blob length long maxRemaining = maxBlobSize; int count; try (InputStream is = data.getBinaryStream()) { while ((count = is.read(buf)) > -1 && maxRemaining > 0) { // If count is more then the remaining bytes we want to read, read only as many are available if (count > maxRemaining) { count = (int) maxRemaining; } os.write(buf, 0, count); // decrement available according to the number of bytes we've read maxRemaining -= count; } } return os.toByteArray(); }
From source file:gov.nih.nci.ncicb.cadsr.ocbrowser.struts.actions.ObjectClassAction.java
/** * * * @param mapping The ActionMapping used to select this instance. * @param form The optional ActionForm bean for this request. * @param request The HTTP Request we are processing. * @param response The HTTP Response we are processing. * * @return//from ww w .j av a 2 s .co m * * @throws IOException * @throws ServletException */ public ActionForward viewReferenceDocAttchment(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { OutputStream out = null; InputStream is = null; out = response.getOutputStream(); String attachmentName = request.getParameter(CaDSRConstants.REFERENCE_DOC_ATTACHMENT_NAME); response.addHeader("Content-Disposition", "inline;filename=" + attachmentName); response.addHeader("Pragma", "cache"); response.addHeader("Cache-Control", "private"); response.addHeader("Expires", "0"); // first find out if the attachment is new and saved in the session Map attMap = (Map) getSessionObject(request, CaDSRConstants.REFDOC_ATTACHMENT_MAP); Attachment attachment = getAttachmentFromSession(attMap, attachmentName); if (attachment != null) { FormFile attFile = (FormFile) attMap.get(attachment); is = attFile.getInputStream(); response.setContentType(attachment.getMimeType()); } else { Blob theBlob = null; Connection conn = null; ResultSet rs = null; PreparedStatement ps = null; try { DBUtil dbUtil = new DBUtil(); //String dsName = CDEBrowserParams.getInstance("cdebrowser").getSbrDSN(); dbUtil.getOracleConnectionFromContainer(); String sqlStmt = "SELECT blob_content, mime_type, doc_size from reference_blobs where name = ?"; log.info(sqlStmt); conn = dbUtil.getConnection(); ps = conn.prepareStatement(sqlStmt); ps.setString(1, attachmentName); rs = ps.executeQuery(); boolean exists = false; if (rs.next()) { exists = true; String mimeType = rs.getString(2); // (mimeType); response.setContentType(mimeType); //theBlob = ((OracleResultSet)rs).getBLOB(1); theBlob = rs.getBlob(1); is = theBlob.getBinaryStream(); response.setContentLength(rs.getInt(3)); response.setBufferSize(4 * 1024); //Writing to the OutputStream if (is != null) { byte[] buf = new byte[4 * 1024]; // 4K buffer int bytesRead; while ((bytesRead = is.read(buf)) != -1) { out.write(buf, 0, bytesRead); } } response.setStatus(HttpServletResponse.SC_OK); } } catch (Exception ex) { log.error("Exception Caught in ObjectClassAction.viewReferenceDocAttchment:", ex); } finally { try { if (is != null) is.close(); if (out != null) out.close(); try { if (ps != null) ps.close(); } catch (Exception e) { } try { if (rs != null) rs.close(); } catch (Exception e) { } try { if (conn != null) conn.close(); } catch (Exception e) { } //if (db != null) db.closeDB(); } catch (Exception ex) { log.error("Exception Caught in ObjectClassAction during cleaning up :", ex); } } } return null; }