public void testDecompressException() throws IOException { // build 5k array byte[] uncompressedData = new byte[5 * 1024]; for (int i = 0; i < uncompressedData.length; i++) { uncompressedData[i] = 1; } byte[] compressedData = doCompress(uncompressedData); Bucket inBucket = new ArrayBucket(compressedData); NullBucket outBucket = new NullBucket(); InputStream decompressorInput = null; OutputStream decompressorOutput = null; try { decompressorInput = inBucket.getInputStream(); decompressorOutput = outBucket.getOutputStream(); Compressor.COMPRESSOR_TYPE.GZIP.decompress( decompressorInput, decompressorOutput, 4096 + 10, 4096 + 20); decompressorInput.close(); decompressorOutput.close(); } catch (CompressionOutputSizeException e) { // expect this return; } finally { Closer.close(decompressorInput); Closer.close(decompressorOutput); inBucket.free(); outBucket.free(); } fail("did not throw expected CompressionOutputSizeException"); }
@Override public void onGeneratedMetadata( Bucket metadata, BaseClientPutter state, ObjectContainer container) { Logger.error( this, "Bogus onGeneratedMetadata() on " + this + " from " + state, new Exception("error")); metadata.free(); }
public void freeData(ObjectContainer container, boolean persistForever) { if (data != null) { if (persistForever) container.activate(data, 1); data.free(); if (persistForever) data.removeFrom(container); data = null; } if (persistForever) container.delete(this); }
@Override protected void freeData(ObjectContainer container) { Bucket data; synchronized (this) { data = returnBucket; returnBucket = null; } if (data != null) { if (persistenceType == PERSIST_FOREVER) container.activate(data, 5); data.free(); if (persistenceType == PERSIST_FOREVER) data.removeFrom(container); if (persistenceType == PERSIST_FOREVER) container.store(this); } }
@Override public void onSuccess(Object keyNum, ObjectContainer container, ClientContext context) { if (logMINOR) Logger.minor(this, "Succeeded (" + this + "): " + token); if (persistent) container.activate(parent, 1); if (parent.isCancelled()) { fail(new InsertException(InsertException.CANCELLED), container, context); return; } synchronized (this) { if (extraInserts > 0) { if (++completedInserts <= extraInserts) { if (logMINOR) Logger.minor( this, "Completed inserts " + completedInserts + " of extra inserts " + extraInserts + " on " + this); if (persistent) container.store(this); return; // Let it repeat until we've done enough inserts. It hasn't been unregistered yet. } } if (finished) { // Normal with persistence. Logger.normal(this, "Block already completed: " + this); return; } finished = true; } if (persistent) { container.store(this); container.activate(sourceData, 1); } if (freeData) { sourceData.free(); if (persistent) sourceData.removeFrom(container); sourceData = null; if (persistent) container.store(this); } parent.completedBlock(false, container, context); unregister(container, context, getPriorityClass(container)); if (persistent) container.activate(cb, 1); if (logMINOR) Logger.minor(this, "Calling onSuccess for " + cb); cb.onSuccess(this, container, context); if (persistent) container.deactivate(cb, 1); }
/** * Must be called just after construction, but within a transaction. * * @throws IdentifierCollisionException If the identifier is already in use. */ @Override void register(ObjectContainer container, boolean noTags) throws IdentifierCollisionException { if (client != null) assert (this.persistenceType == client.persistenceType); if (persistenceType != PERSIST_CONNECTION) try { client.register(this, container); } catch (IdentifierCollisionException e) { returnBucket.free(); if (persistenceType == PERSIST_FOREVER) returnBucket.removeFrom(container); throw e; } if (persistenceType != PERSIST_CONNECTION && !noTags) { FCPMessage msg = persistentTagMessage(container); client.queueClientRequestMessage(msg, 0, container); } }
/** * process the bucket containing the main index file * * @param bucket */ private void processRequests(Bucket bucket) { try { InputStream is = bucket.getInputStream(); parse(is); is.close(); fetchStatus = FetchStatus.FETCHED; for (FindRequest req : waitingOnMainIndex) setdependencies(req); waitingOnMainIndex.clear(); } catch (Exception e) { fetchStatus = FetchStatus.FAILED; for (FindRequest findRequest : waitingOnMainIndex) { findRequest.setError(new TaskAbortException("Failure parsing " + toString(), e)); } Logger.error(this, indexuri, e); } finally { bucket.free(); } }
private void fail( InsertException e, boolean forceFatal, ObjectContainer container, ClientContext context) { synchronized (this) { if (finished) return; finished = true; } if (persistent) container.store(this); if (e.isFatal() || forceFatal) parent.fatallyFailedBlock(container, context); else parent.failedBlock(container, context); unregister(container, context, getPriorityClass(container)); if (freeData) { if (persistent) container.activate(sourceData, 1); sourceData.free(); if (persistent) sourceData.removeFrom(container); sourceData = null; if (persistent) container.store(this); } if (persistent) container.activate(cb, 1); cb.onFailure(e, this, container, context); }
protected void onSuccess( Bucket data, boolean fromStore, Integer token, int blockNo, ClientKeyBlock block, ObjectContainer container, ClientContext context) { if (persistent) { container.activate(this, 1); container.activate(segment, 1); container.activate(parent, 1); } if (parent.isCancelled()) { data.free(); if (persistent) data.removeFrom(container); onFailure(new FetchException(FetchException.CANCELLED), token, container, context); return; } segment.onSuccess(data, blockNo, block, container, context, this); }
public void cancel(ObjectContainer container, ClientContext context) { synchronized (this) { if (finished) return; finished = true; } boolean wasActive = true; if (persistent) { container.store(this); wasActive = container.ext().isActive(cb); if (!wasActive) container.activate(cb, 1); container.activate(sourceData, 1); } if (freeData) { sourceData.free(); if (persistent) sourceData.removeFrom(container); sourceData = null; if (persistent) container.store(this); } super.unregister(container, context, getPriorityClass(container)); cb.onFailure(new InsertException(InsertException.CANCELLED), this, container, context); if (!wasActive) container.deactivate(cb, 1); }
/** * You have to synchronize on this <code>WoTMessageListInserter</code> and then on the <code> * WoTMessageManager</code> when using this function. */ private void insertMessageList(WoTOwnMessageList list) throws TransformerException, ParserConfigurationException, NoSuchMessageException, IOException, InsertException { Bucket tempB = mTBF.makeBucket(4096); /* TODO: set to a reasonable value */ OutputStream os = null; try { os = tempB.getOutputStream(); // This is what requires synchronization on the WoTMessageManager: While being marked as // "being inserted", message lists cannot be modified anymore, // so it must be guranteed that the "being inserted" mark does not change while we encode the // XML etc. mMessageManager.onMessageListInsertStarted(list); mXML.encode(mMessageManager, list, os); os.close(); os = null; tempB.setReadOnly(); /* We do not specifiy a ClientMetaData with mimetype because that would result in the insertion of an additional CHK */ InsertBlock ib = new InsertBlock(tempB, null, list.getInsertURI()); InsertContext ictx = mClient.getInsertContext(true); ClientPutter pu = mClient.insert( ib, false, null, false, ictx, this, RequestStarter.INTERACTIVE_PRIORITY_CLASS); addInsert(pu); tempB = null; if (logDEBUG) Logger.debug(this, "Started insert of WoTOwnMessageList at request URI " + list.getURI()); } finally { if (tempB != null) tempB.free(); Closer.close(os); } }
@Override public void onGeneratedMetadata( Bucket metadata, BaseClientPutter state, ObjectContainer container) { metadata.free(); throw new UnsupportedOperationException(); }
@Override public void free() { underlying.free(); }
private void handleZIPArchive( ArchiveStoreContext ctx, FreenetURI key, InputStream data, String element, ArchiveExtractCallback callback, MutableBoolean gotElement, boolean throwAtExit, ClientContext context) throws ArchiveFailureException, ArchiveRestartException { if (logMINOR) Logger.minor(this, "Handling a ZIP Archive"); ZipInputStream zis = null; try { zis = new ZipInputStream(data); // MINOR: Assumes the first entry in the zip is a directory. ZipEntry entry; byte[] buf = new byte[32768]; HashSet<String> names = new HashSet<String>(); boolean gotMetadata = false; outerZIP: while (true) { entry = zis.getNextEntry(); if (entry == null) break; if (entry.isDirectory()) continue; String name = stripLeadingSlashes(entry.getName()); if (names.contains(name)) { Logger.error(this, "Duplicate key " + name + " in archive " + key); continue; } long size = entry.getSize(); if (name.equals(".metadata")) gotMetadata = true; if (size > maxArchivedFileSize && !name.equals(element)) { addErrorElement( ctx, key, name, "File too big: " + maxArchivedFileSize + " greater than current archived file size limit " + maxArchivedFileSize, true); } else { // Read the element long realLen = 0; Bucket output = tempBucketFactory.makeBucket(size); OutputStream out = output.getOutputStream(); try { int readBytes; while ((readBytes = zis.read(buf)) > 0) { out.write(buf, 0, readBytes); readBytes += realLen; if (readBytes > maxArchivedFileSize) { addErrorElement( ctx, key, name, "File too big: " + maxArchivedFileSize + " greater than current archived file size limit " + maxArchivedFileSize, true); out.close(); out = null; output.free(); continue outerZIP; } } } finally { if (out != null) out.close(); } if (size <= maxArchivedFileSize) { addStoreElement(ctx, key, name, output, gotElement, element, callback, context); names.add(name); trimStoredData(); } else { // We are here because they asked for this file. callback.gotBucket(output, context); gotElement.value = true; addErrorElement( ctx, key, name, "File too big: " + size + " greater than current archived file size limit " + maxArchivedFileSize, true); } } } // If no metadata, generate some if (!gotMetadata) { generateMetadata(ctx, key, names, gotElement, element, callback, context); trimStoredData(); } if (throwAtExit) throw new ArchiveRestartException("Archive changed on re-fetch"); if ((!gotElement.value) && element != null) callback.notInArchive(context); } catch (IOException e) { throw new ArchiveFailureException("Error reading archive: " + e.getMessage(), e); } finally { if (zis != null) { try { zis.close(); } catch (IOException e) { Logger.error(this, "Failed to close stream: " + e, e); } } } }
/** Handle an incoming connection. Blocking, obviously. */ public static void handle(Socket sock, ToadletContainer container, PageMaker pageMaker) { try { InputStream is = new BufferedInputStream(sock.getInputStream(), 4096); LineReadingInputStream lis = new LineReadingInputStream(is); while (true) { String firstLine = lis.readLine(32768, 128, false); // ISO-8859-1 or US-ASCII, _not_ UTF-8 if (firstLine == null) { sock.close(); return; } else if (firstLine.equals("")) { continue; } boolean logMINOR = Logger.shouldLog(Logger.MINOR, ToadletContextImpl.class); if (logMINOR) Logger.minor(ToadletContextImpl.class, "first line: " + firstLine); String[] split = firstLine.split(" "); if (split.length != 3) throw new ParseException( "Could not parse request line (split.length=" + split.length + "): " + firstLine); if (!split[2].startsWith("HTTP/1.")) throw new ParseException("Unrecognized protocol " + split[2]); URI uri; try { uri = URIPreEncoder.encodeURI(split[1]).normalize(); if (logMINOR) Logger.minor( ToadletContextImpl.class, "URI: " + uri + " path " + uri.getPath() + " host " + uri.getHost() + " frag " + uri.getFragment() + " port " + uri.getPort() + " query " + uri.getQuery() + " scheme " + uri.getScheme()); } catch (URISyntaxException e) { sendURIParseError(sock.getOutputStream(), true, e); return; } String method = split[0]; MultiValueTable<String, String> headers = new MultiValueTable<String, String>(); while (true) { String line = lis.readLine(32768, 128, false); // ISO-8859 or US-ASCII, not UTF-8 if (line == null) { sock.close(); return; } // System.out.println("Length="+line.length()+": "+line); if (line.length() == 0) break; int index = line.indexOf(':'); if (index < 0) { throw new ParseException("Missing ':' in request header field"); } String before = line.substring(0, index).toLowerCase(); String after = line.substring(index + 1); after = after.trim(); headers.put(before, after); } boolean disconnect = shouldDisconnectAfterHandled(split[2].equals("HTTP/1.0"), headers) || !container.enablePersistentConnections(); boolean allowPost = container.allowPosts(); BucketFactory bf = container.getBucketFactory(); ToadletContextImpl ctx = new ToadletContextImpl(sock, headers, bf, pageMaker, container); ctx.shouldDisconnect = disconnect; /* * if we're handling a POST, copy the data into a bucket now, * before we go into the redirect loop */ Bucket data; if (method.equals("POST")) { String slen = headers.get("content-length"); if (slen == null) { sendError( sock.getOutputStream(), 400, "Bad Request", l10n("noContentLengthInPOST"), true, null); return; } long len; try { len = Integer.parseInt(slen); if (len < 0) throw new NumberFormatException("content-length less than 0"); } catch (NumberFormatException e) { sendError( sock.getOutputStream(), 400, "Bad Request", l10n("cannotParseContentLengthWithError", "error", e.toString()), true, null); return; } if (allowPost && ((!container.publicGatewayMode()) || ctx.isAllowedFullAccess())) { data = bf.makeBucket(len); BucketTools.copyFrom(data, is, len); } else { FileUtil.skipFully(is, len); ctx.sendMethodNotAllowed("POST", true); ctx.close(); return; } } else { // we're not doing to use it, but we have to keep // the compiler happy data = null; } // Handle it. try { boolean redirect = true; while (redirect) { // don't go around the loop unless set explicitly redirect = false; Toadlet t; try { t = container.findToadlet(uri); } catch (PermanentRedirectException e) { Toadlet.writePermanentRedirect(ctx, "Found elsewhere", e.newuri.toASCIIString()); break; } if (t == null) { ctx.sendNoToadletError(ctx.shouldDisconnect); break; } HTTPRequestImpl req = new HTTPRequestImpl(uri, data, ctx, method); try { if (method.equals("GET")) { ctx.setActiveToadlet(t); t.handleGet(uri, req, ctx); ctx.close(); } else if (method.equals("POST")) { ctx.setActiveToadlet(t); t.handlePost(uri, req, ctx); } else { ctx.sendMethodNotAllowed(method, ctx.shouldDisconnect); ctx.close(); } } catch (RedirectException re) { uri = re.newuri; redirect = true; } finally { req.freeParts(); } } if (ctx.shouldDisconnect) { sock.close(); return; } } finally { if (data != null) data.free(); } } } catch (ParseException e) { try { sendError( sock.getOutputStream(), 400, "Bad Request", l10n("parseErrorWithError", "error", e.getMessage()), true, null); } catch (IOException e1) { // Ignore } } catch (TooLongException e) { try { sendError( sock.getOutputStream(), 400, "Bad Request", l10n("headersLineTooLong"), true, null); } catch (IOException e1) { // Ignore } } catch (IOException e) { // ignore and return } catch (ToadletContextClosedException e) { Logger.error( ToadletContextImpl.class, "ToadletContextClosedException while handling connection!"); } catch (Throwable t) { Logger.error(ToadletContextImpl.class, "Caught error: " + t + " handling socket", t); try { sendError(sock.getOutputStream(), 500, "Internal Error", t.toString(), true, null); } catch (IOException e1) { // ignore and return } } }
public void onSuccess(FetchResult result, ClientGetter state, ObjectContainer container) { Logger.minor(this, "Succeeded: " + identifier); Bucket data = result.asBucket(); if (persistenceType == PERSIST_FOREVER) { if (data != null) container.activate(data, 5); if (returnBucket != null) container.activate(returnBucket, 5); container.activate(client, 1); if (tempFile != null) container.activate(tempFile, 5); if (targetFile != null) container.activate(targetFile, 5); } if (returnBucket != data && !binaryBlob) { boolean failed = true; synchronized (this) { if (finished) { Logger.error( this, "Already finished but onSuccess() for " + this + " data = " + data, new Exception("debug")); data.free(); if (persistenceType == PERSIST_FOREVER) data.removeFrom(container); return; // Already failed - bucket error maybe?? } if (returnType == ClientGetMessage.RETURN_TYPE_DIRECT && returnBucket == null) { // Lost bucket for some reason e.g. bucket error (caused by IOException) on previous try?? // Recover... returnBucket = data; failed = false; } } if (failed && persistenceType == PERSIST_FOREVER) { if (container.ext().getID(returnBucket) == container.ext().getID(data)) { Logger.error( this, "DB4O BUG DETECTED WITHOUT ARRAY HANDLING! EVIL HORRIBLE BUG! UID(returnBucket)=" + container.ext().getID(returnBucket) + " for " + returnBucket + " active=" + container.ext().isActive(returnBucket) + " stored = " + container.ext().isStored(returnBucket) + " but UID(data)=" + container.ext().getID(data) + " for " + data + " active = " + container.ext().isActive(data) + " stored = " + container.ext().isStored(data)); // Succeed anyway, hope that the returned bucket is consistent... returnBucket = data; failed = false; } } if (failed) { Logger.error( this, "returnBucket = " + returnBucket + " but onSuccess() data = " + data, new Exception("debug")); // Caller guarantees that data == returnBucket onFailure( new FetchException(FetchException.INTERNAL_ERROR, "Data != returnBucket"), null, container); return; } } boolean dontFree = false; // FIXME I don't think this is a problem in this case...? (Disk write while locked..) AllDataMessage adm = null; synchronized (this) { if (succeeded) { Logger.error(this, "onSuccess called twice for " + this + " (" + identifier + ')'); return; // We might be called twice; ignore it if so. } started = true; if (!binaryBlob) this.foundDataMimeType = result.getMimeType(); else this.foundDataMimeType = BinaryBlob.MIME_TYPE; if (returnType == ClientGetMessage.RETURN_TYPE_DIRECT) { // Send all the data at once // FIXME there should be other options // FIXME: CompletionTime is set on finish() : we need to give it current time here // but it means we won't always return the same value to clients... Does it matter ? adm = new AllDataMessage( returnBucket, identifier, global, startupTime, System.currentTimeMillis(), this.foundDataMimeType); if (persistenceType == PERSIST_CONNECTION) adm.setFreeOnSent(); dontFree = true; /* * } else if(returnType == ClientGetMessage.RETURN_TYPE_NONE) { // Do nothing */ } else if (returnType == ClientGetMessage.RETURN_TYPE_DISK) { // Write to temp file, then rename over filename if (!FileUtil.renameTo(tempFile, targetFile)) { postFetchProtocolErrorMessage = new ProtocolErrorMessage( ProtocolErrorMessage.COULD_NOT_RENAME_FILE, false, null, identifier, global); // Don't delete temp file, user might want it. } returnBucket = new FileBucket(targetFile, false, true, false, false, false); } if (persistenceType == PERSIST_FOREVER && progressPending != null) { container.activate(progressPending, 1); progressPending.removeFrom(container); } progressPending = null; this.foundDataLength = returnBucket.size(); this.succeeded = true; finished = true; } trySendDataFoundOrGetFailed(null, container); if (adm != null) trySendAllDataMessage(adm, null, container); if (!dontFree) { data.free(); } if (persistenceType == PERSIST_FOREVER) { returnBucket.storeTo(container); container.store(this); } finish(container); if (client != null) client.notifySuccess(this, container); }
@Override public void close() throws IOException { in.close(); data.free(); }
public void dump() { copyBucket.free(); }
/** Handle an incoming connection. Blocking, obviously. */ public static void handle(Socket sock, ToadletContainer container, PageMaker pageMaker) { try { InputStream is = new BufferedInputStream(sock.getInputStream(), 4096); LineReadingInputStream lis = new LineReadingInputStream(is); while (true) { String firstLine = lis.readLine(32768, 128, false); // ISO-8859-1 or US-ASCII, _not_ UTF-8 if (firstLine == null) { sock.close(); return; } else if (firstLine.equals("")) { continue; } boolean logMINOR = Logger.shouldLog(Logger.MINOR, ToadletContextImpl.class); if (logMINOR) Logger.minor(ToadletContextImpl.class, "first line: " + firstLine); String[] split = firstLine.split(" "); if (split.length != 3) throw new ParseException( "Could not parse request line (split.length=" + split.length + "): " + firstLine); if (!split[2].startsWith("HTTP/1.")) throw new ParseException("Unrecognized protocol " + split[2]); URI uri; try { uri = URIPreEncoder.encodeURI(split[1]).normalize(); if (logMINOR) Logger.minor( ToadletContextImpl.class, "URI: " + uri + " path " + uri.getPath() + " host " + uri.getHost() + " frag " + uri.getFragment() + " port " + uri.getPort() + " query " + uri.getQuery() + " scheme " + uri.getScheme()); } catch (URISyntaxException e) { sendURIParseError(sock.getOutputStream(), true, e); return; } String method = split[0]; MultiValueTable<String, String> headers = new MultiValueTable<String, String>(); while (true) { String line = lis.readLine(32768, 128, false); // ISO-8859 or US-ASCII, not UTF-8 if (line == null) { sock.close(); return; } // System.out.println("Length="+line.length()+": "+line); if (line.length() == 0) break; int index = line.indexOf(':'); if (index < 0) { throw new ParseException("Missing ':' in request header field"); } String before = line.substring(0, index).toLowerCase(); String after = line.substring(index + 1); after = after.trim(); headers.put(before, after); } boolean disconnect = shouldDisconnectAfterHandled(split[2].equals("HTTP/1.0"), headers) || !container.enablePersistentConnections(); boolean allowPost = container.allowPosts(); BucketFactory bf = container.getBucketFactory(); ToadletContextImpl ctx = new ToadletContextImpl(sock, headers, bf, pageMaker, container); ctx.shouldDisconnect = disconnect; /* * copy the data into a bucket now, * before we go into the redirect loop */ Bucket data; boolean methodIsConfigurable = true; String slen = headers.get("content-length"); if (METHODS_MUST_HAVE_DATA.contains(method)) { // <method> must have data methodIsConfigurable = false; if (slen == null) { ctx.shouldDisconnect = true; ctx.sendReplyHeaders(400, "Bad Request", null, null, -1); return; } } else if (METHODS_CANNOT_HAVE_DATA.contains(method)) { // <method> can not have data methodIsConfigurable = false; if (slen != null) { ctx.shouldDisconnect = true; ctx.sendReplyHeaders(400, "Bad Request", null, null, -1); return; } } if (slen != null) { long len; try { len = Integer.parseInt(slen); if (len < 0) throw new NumberFormatException("content-length less than 0"); } catch (NumberFormatException e) { ctx.shouldDisconnect = true; ctx.sendReplyHeaders(400, "Bad Request", null, null, -1); return; } if (allowPost && ((!container.publicGatewayMode()) || ctx.isAllowedFullAccess())) { data = bf.makeBucket(len); BucketTools.copyFrom(data, is, len); } else { FileUtil.skipFully(is, len); if (method.equals("POST")) { ctx.sendMethodNotAllowed("POST", true); } else { sendError( sock.getOutputStream(), 403, "Forbidden", "Content not allowed in this configuration", true, null); } ctx.close(); return; } } else { // we're not doing to use it, but we have to keep // the compiler happy data = null; } if (!container.enableExtendedMethodHandling()) { if (!METHODS_RESTRICTED_MODE.contains(method)) { sendError( sock.getOutputStream(), 403, "Forbidden", "Method not allowed in this configuration", true, null); return; } } // Handle it. try { boolean redirect = true; while (redirect) { // don't go around the loop unless set explicitly redirect = false; Toadlet t; try { t = container.findToadlet(uri); } catch (PermanentRedirectException e) { Toadlet.writePermanentRedirect(ctx, "Found elsewhere", e.newuri.toASCIIString()); break; } if (t == null) { ctx.sendNoToadletError(ctx.shouldDisconnect); break; } // if the Toadlet does not support the method, we don't need to parse the data // also due this pre check a 'NoSuchMethodException' should never appear if (!(t.findSupportedMethods().contains(method))) { ctx.sendMethodNotAllowed(method, ctx.shouldDisconnect); break; } HTTPRequestImpl req = new HTTPRequestImpl(uri, data, ctx, method); try { String methodName = "handleMethod" + method; try { Class<? extends Toadlet> c = t.getClass(); Method m = c.getMethod(methodName, HANDLE_PARAMETERS); if (methodIsConfigurable) { AllowData anno = m.getAnnotation(AllowData.class); if (anno == null) { if (data != null) { sendError( sock.getOutputStream(), 400, "Bad Request", "Content not allowed", true, null); ctx.close(); return; } } else if (anno.value()) { if (data == null) { sendError( sock.getOutputStream(), 400, "Bad Request", "Missing Content", true, null); ctx.close(); return; } } } ctx.setActiveToadlet(t); Object arglist[] = new Object[] {uri, req, ctx}; m.invoke(t, arglist); } catch (InvocationTargetException ite) { throw ite.getCause(); } } catch (RedirectException re) { uri = re.newuri; redirect = true; } finally { req.freeParts(); } } if (ctx.shouldDisconnect) { sock.close(); return; } } finally { if (data != null) data.free(); } } } catch (ParseException e) { try { sendError( sock.getOutputStream(), 400, "Bad Request", l10n("parseErrorWithError", "error", e.getMessage()), true, null); } catch (IOException e1) { // Ignore } } catch (TooLongException e) { try { sendError( sock.getOutputStream(), 400, "Bad Request", l10n("headersLineTooLong"), true, null); } catch (IOException e1) { // Ignore } } catch (IOException e) { // ignore and return } catch (ToadletContextClosedException e) { Logger.error( ToadletContextImpl.class, "ToadletContextClosedException while handling connection!"); } catch (Throwable t) { Logger.error(ToadletContextImpl.class, "Caught error: " + t + " handling socket", t); try { sendError(sock.getOutputStream(), 500, "Internal Error", t.toString(), true, null); } catch (IOException e1) { // ignore and return } } }
public void realFree() { bucket.free(); }