Skip to content
Snippets Groups Projects
Commit 5e33a1de authored by Shawn Pearce's avatar Shawn Pearce
Browse files

Simple dumb HTTP server for Git


This is a simple HTTP server that provides the minimum server side
support required for dumb (non-git aware) transport clients.

We produce the info/refs and objects/info/packs file on the fly
from the local repository state, but otherwise serve data as raw
files from the on-disk structure.

In the future we could better optimize the FileSender class and the
servlets that use it to take advantage of direct file to network
APIs in more advanced servlet containers like Jetty.

Our glue package borrows the idea of a micro embedded DSL from
Google Guice and uses it to configure a collection of Filters
and HttpServlets, all of which are matched against requests using
regular expressions.  If a subgroup exists in the pattern, it is
extracted and used for the path info component of the request.

Change-Id: Ia0f1a425d07d035e344ae54faf8aeb04763e7487
Signed-off-by: default avatarShawn O. Pearce <spearce@spearce.org>
parent 71b34847
No related branches found
No related tags found
No related merge requests found
Showing
with 1778 additions and 0 deletions
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
</classpath>
#FindBugs User Preferences
#Mon May 04 16:24:13 PDT 2009
detectorAppendingToAnObjectOutputStream=AppendingToAnObjectOutputStream|true
detectorBadAppletConstructor=BadAppletConstructor|false
detectorBadResultSetAccess=BadResultSetAccess|true
detectorBadSyntaxForRegularExpression=BadSyntaxForRegularExpression|true
detectorBadUseOfReturnValue=BadUseOfReturnValue|true
detectorBadlyOverriddenAdapter=BadlyOverriddenAdapter|true
detectorBooleanReturnNull=BooleanReturnNull|true
detectorCallToUnsupportedMethod=CallToUnsupportedMethod|true
detectorCheckImmutableAnnotation=CheckImmutableAnnotation|true
detectorCheckTypeQualifiers=CheckTypeQualifiers|true
detectorCloneIdiom=CloneIdiom|false
detectorComparatorIdiom=ComparatorIdiom|true
detectorConfusedInheritance=ConfusedInheritance|true
detectorConfusionBetweenInheritedAndOuterMethod=ConfusionBetweenInheritedAndOuterMethod|true
detectorCrossSiteScripting=CrossSiteScripting|true
detectorDoInsideDoPrivileged=DoInsideDoPrivileged|true
detectorDontCatchIllegalMonitorStateException=DontCatchIllegalMonitorStateException|true
detectorDontUseEnum=DontUseEnum|true
detectorDroppedException=DroppedException|true
detectorDumbMethodInvocations=DumbMethodInvocations|true
detectorDumbMethods=DumbMethods|true
detectorDuplicateBranches=DuplicateBranches|true
detectorEmptyZipFileEntry=EmptyZipFileEntry|true
detectorEqualsOperandShouldHaveClassCompatibleWithThis=EqualsOperandShouldHaveClassCompatibleWithThis|true
detectorFinalizerNullsFields=FinalizerNullsFields|true
detectorFindBadCast2=FindBadCast2|true
detectorFindBadForLoop=FindBadForLoop|true
detectorFindCircularDependencies=FindCircularDependencies|false
detectorFindDeadLocalStores=FindDeadLocalStores|true
detectorFindDoubleCheck=FindDoubleCheck|true
detectorFindEmptySynchronizedBlock=FindEmptySynchronizedBlock|true
detectorFindFieldSelfAssignment=FindFieldSelfAssignment|true
detectorFindFinalizeInvocations=FindFinalizeInvocations|true
detectorFindFloatEquality=FindFloatEquality|true
detectorFindHEmismatch=FindHEmismatch|true
detectorFindInconsistentSync2=FindInconsistentSync2|true
detectorFindJSR166LockMonitorenter=FindJSR166LockMonitorenter|true
detectorFindLocalSelfAssignment2=FindLocalSelfAssignment2|true
detectorFindMaskedFields=FindMaskedFields|true
detectorFindMismatchedWaitOrNotify=FindMismatchedWaitOrNotify|true
detectorFindNakedNotify=FindNakedNotify|true
detectorFindNonSerializableStoreIntoSession=FindNonSerializableStoreIntoSession|true
detectorFindNonSerializableValuePassedToWriteObject=FindNonSerializableValuePassedToWriteObject|true
detectorFindNonShortCircuit=FindNonShortCircuit|true
detectorFindNullDeref=FindNullDeref|true
detectorFindNullDerefsInvolvingNonShortCircuitEvaluation=FindNullDerefsInvolvingNonShortCircuitEvaluation|true
detectorFindOpenStream=FindOpenStream|true
detectorFindPuzzlers=FindPuzzlers|true
detectorFindRefComparison=FindRefComparison|true
detectorFindReturnRef=FindReturnRef|true
detectorFindRunInvocations=FindRunInvocations|true
detectorFindSelfComparison=FindSelfComparison|true
detectorFindSelfComparison2=FindSelfComparison2|true
detectorFindSleepWithLockHeld=FindSleepWithLockHeld|true
detectorFindSpinLoop=FindSpinLoop|true
detectorFindSqlInjection=FindSqlInjection|true
detectorFindTwoLockWait=FindTwoLockWait|true
detectorFindUncalledPrivateMethods=FindUncalledPrivateMethods|true
detectorFindUnconditionalWait=FindUnconditionalWait|true
detectorFindUninitializedGet=FindUninitializedGet|true
detectorFindUnrelatedTypesInGenericContainer=FindUnrelatedTypesInGenericContainer|true
detectorFindUnreleasedLock=FindUnreleasedLock|true
detectorFindUnsatisfiedObligation=FindUnsatisfiedObligation|true
detectorFindUnsyncGet=FindUnsyncGet|true
detectorFindUselessControlFlow=FindUselessControlFlow|true
detectorFormatStringChecker=FormatStringChecker|true
detectorHugeSharedStringConstants=HugeSharedStringConstants|true
detectorIDivResultCastToDouble=IDivResultCastToDouble|true
detectorIncompatMask=IncompatMask|true
detectorInconsistentAnnotations=InconsistentAnnotations|true
detectorInefficientMemberAccess=InefficientMemberAccess|false
detectorInefficientToArray=InefficientToArray|true
detectorInfiniteLoop=InfiniteLoop|true
detectorInfiniteRecursiveLoop=InfiniteRecursiveLoop|true
detectorInfiniteRecursiveLoop2=InfiniteRecursiveLoop2|false
detectorInheritanceUnsafeGetResource=InheritanceUnsafeGetResource|true
detectorInitializationChain=InitializationChain|true
detectorInstantiateStaticClass=InstantiateStaticClass|true
detectorInvalidJUnitTest=InvalidJUnitTest|true
detectorIteratorIdioms=IteratorIdioms|true
detectorLazyInit=LazyInit|true
detectorLoadOfKnownNullValue=LoadOfKnownNullValue|true
detectorMethodReturnCheck=MethodReturnCheck|true
detectorMultithreadedInstanceAccess=MultithreadedInstanceAccess|true
detectorMutableLock=MutableLock|true
detectorMutableStaticFields=MutableStaticFields|true
detectorNaming=Naming|true
detectorNumberConstructor=NumberConstructor|true
detectorOverridingEqualsNotSymmetrical=OverridingEqualsNotSymmetrical|true
detectorPreferZeroLengthArrays=PreferZeroLengthArrays|true
detectorPublicSemaphores=PublicSemaphores|false
detectorQuestionableBooleanAssignment=QuestionableBooleanAssignment|true
detectorReadReturnShouldBeChecked=ReadReturnShouldBeChecked|true
detectorRedundantInterfaces=RedundantInterfaces|true
detectorRepeatedConditionals=RepeatedConditionals|true
detectorRuntimeExceptionCapture=RuntimeExceptionCapture|true
detectorSerializableIdiom=SerializableIdiom|true
detectorStartInConstructor=StartInConstructor|true
detectorStaticCalendarDetector=StaticCalendarDetector|true
detectorStringConcatenation=StringConcatenation|true
detectorSuperfluousInstanceOf=SuperfluousInstanceOf|true
detectorSuspiciousThreadInterrupted=SuspiciousThreadInterrupted|true
detectorSwitchFallthrough=SwitchFallthrough|true
detectorSynchronizeAndNullCheckField=SynchronizeAndNullCheckField|true
detectorSynchronizeOnClassLiteralNotGetClass=SynchronizeOnClassLiteralNotGetClass|true
detectorSynchronizingOnContentsOfFieldToProtectField=SynchronizingOnContentsOfFieldToProtectField|true
detectorURLProblems=URLProblems|true
detectorUncallableMethodOfAnonymousClass=UncallableMethodOfAnonymousClass|true
detectorUnnecessaryMath=UnnecessaryMath|true
detectorUnreadFields=UnreadFields|true
detectorUseObjectEquals=UseObjectEquals|false
detectorUselessSubclassMethod=UselessSubclassMethod|false
detectorVarArgsProblems=VarArgsProblems|true
detectorVolatileUsage=VolatileUsage|true
detectorWaitInLoop=WaitInLoop|true
detectorWrongMapIterator=WrongMapIterator|true
detectorXMLFactoryBypass=XMLFactoryBypass|true
detector_threshold=2
effort=default
excludefilter0=findBugs/FindBugsExcludeFilter.xml
filter_settings=Medium|BAD_PRACTICE,CORRECTNESS,MT_CORRECTNESS,PERFORMANCE,STYLE|false
filter_settings_neg=MALICIOUS_CODE,NOISE,I18N,SECURITY,EXPERIMENTAL|
run_at_full_build=true
/bin
/target
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.eclipse.jgit.http.server</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.pde.PluginNature</nature>
</natures>
</projectDescription>
#Mon Aug 11 16:46:12 PDT 2008
eclipse.preferences.version=1
encoding/<project>=UTF-8
#Mon Mar 24 18:55:50 EDT 2008
eclipse.preferences.version=1
line.separator=\n
This diff is collapsed.
#Wed Jan 06 12:13:14 PST 2010
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
formatter_profile=_JGit Format
formatter_settings_version=11
org.eclipse.jdt.ui.ignorelowercasenames=true
org.eclipse.jdt.ui.importorder=java;javax;org;com;
org.eclipse.jdt.ui.ondemandthreshold=99
org.eclipse.jdt.ui.staticondemandthreshold=99
org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>
sp_cleanup.add_default_serial_version_id=true
sp_cleanup.add_generated_serial_version_id=false
sp_cleanup.add_missing_annotations=false
sp_cleanup.add_missing_deprecated_annotations=true
sp_cleanup.add_missing_methods=false
sp_cleanup.add_missing_nls_tags=false
sp_cleanup.add_missing_override_annotations=true
sp_cleanup.add_serial_version_id=false
sp_cleanup.always_use_blocks=true
sp_cleanup.always_use_parentheses_in_expressions=false
sp_cleanup.always_use_this_for_non_static_field_access=false
sp_cleanup.always_use_this_for_non_static_method_access=false
sp_cleanup.convert_to_enhanced_for_loop=false
sp_cleanup.correct_indentation=false
sp_cleanup.format_source_code=false
sp_cleanup.format_source_code_changes_only=false
sp_cleanup.make_local_variable_final=false
sp_cleanup.make_parameters_final=false
sp_cleanup.make_private_fields_final=true
sp_cleanup.make_type_abstract_if_missing_method=false
sp_cleanup.make_variable_declarations_final=false
sp_cleanup.never_use_blocks=false
sp_cleanup.never_use_parentheses_in_expressions=true
sp_cleanup.on_save_use_additional_actions=true
sp_cleanup.organize_imports=false
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
sp_cleanup.remove_private_constructors=true
sp_cleanup.remove_trailing_whitespaces=true
sp_cleanup.remove_trailing_whitespaces_all=true
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
sp_cleanup.remove_unnecessary_casts=false
sp_cleanup.remove_unnecessary_nls_tags=false
sp_cleanup.remove_unused_imports=false
sp_cleanup.remove_unused_local_variables=false
sp_cleanup.remove_unused_private_fields=true
sp_cleanup.remove_unused_private_members=false
sp_cleanup.remove_unused_private_methods=true
sp_cleanup.remove_unused_private_types=true
sp_cleanup.sort_members=false
sp_cleanup.sort_members_all=false
sp_cleanup.use_blocks=false
sp_cleanup.use_blocks_only_for_return_and_throw=false
sp_cleanup.use_parentheses_in_expressions=false
sp_cleanup.use_this_for_non_static_field_access=false
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
sp_cleanup.use_this_for_non_static_method_access=false
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %plugin_name
Bundle-SymbolicName: org.eclipse.jgit.http.server
Bundle-Version: 0.6.0.qualifier
Bundle-Localization: plugin
Bundle-Vendor: %provider_name
Export-Package:
org.eclipse.jgit.http.server;version="0.6.0",
org.eclipse.jgit.http.server.glue;version="0.6.0",
org.eclipse.jgit.http.server.resolver;version="0.6.0"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: javax.servlet;version="[2.5.0,3.0.0)",
javax.servlet.http;version="[2.5.0,3.0.0)",
org.eclipse.jgit.errors;version="0.6.0",
org.eclipse.jgit.lib;version="0.6.0",
org.eclipse.jgit.revwalk;version="0.6.0",
org.eclipse.jgit.transport;version="0.6.0",
org.eclipse.jgit.util;version="0.6.0",
org.eclipse.jgit.util.io;version="0.6.0"
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
plugin.properties
plugin_name=Java Git HTTP Server (Incubation)
provider_name=eclipse.org
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009-2010, Google Inc.
Copyright (C) 2008, Imran M Yousuf <imyousuf@smartitengineering.com>
and other copyright owners as documented in the project's IP log.
This program and the accompanying materials are made available
under the terms of the Eclipse Distribution License v1.0 which
accompanies this distribution, is reproduced below, and is
available at http://www.eclipse.org/org/documents/edl-v10.php
All rights reserved.
Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the following
conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
- Neither the name of the Eclipse Foundation, Inc. nor the
names of its contributors may be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
<version>0.6.0-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit.http.server</artifactId>
<name>JGit - HTTP Server</name>
<description>
Git aware HTTP server implementation.
</description>
<dependencies>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/</sourceDirectory>
<resources>
<resource>
<directory>.</directory>
<includes>
<include>plugin.properties</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.eclipse.jgit.http.server;
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
import static org.eclipse.jgit.http.server.ServletUtils.getRepository;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.http.server.resolver.AsIsFileService;
import org.eclipse.jgit.http.server.resolver.ServiceNotAuthorizedException;
import org.eclipse.jgit.http.server.resolver.ServiceNotEnabledException;
import org.eclipse.jgit.lib.Repository;
class AsIsFileFilter implements Filter {
private final AsIsFileService asIs;
AsIsFileFilter(final AsIsFileService getAnyFile) {
this.asIs = getAnyFile;
}
public void init(FilterConfig config) throws ServletException {
// Do nothing.
}
public void destroy() {
// Do nothing.
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
final Repository db = getRepository(request);
asIs.access((HttpServletRequest) request, db);
chain.doFilter(request, response);
} catch (ServiceNotAuthorizedException e) {
((HttpServletResponse) response).sendError(SC_UNAUTHORIZED);
} catch (ServiceNotEnabledException e) {
((HttpServletResponse) response).sendError(SC_FORBIDDEN);
}
}
}
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.eclipse.jgit.http.server;
import static javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT;
import static javax.servlet.http.HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE;
import static org.eclipse.jgit.util.HttpSupport.HDR_ACCEPT_RANGES;
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_LENGTH;
import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_RANGE;
import static org.eclipse.jgit.util.HttpSupport.HDR_IF_RANGE;
import static org.eclipse.jgit.util.HttpSupport.HDR_RANGE;
import java.io.EOFException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.util.IO;
/**
* Dumps a file over HTTP GET (or its information via HEAD).
* <p>
* Supports a single byte range requested via {@code Range} HTTP header. This
* feature supports a dumb client to resume download of a larger object file.
*/
final class FileSender {
private final File path;
private final RandomAccessFile source;
private final long lastModified;
private final long fileLen;
private long pos;
private long end;
FileSender(final File path) throws FileNotFoundException {
this.path = path;
this.source = new RandomAccessFile(path, "r");
try {
this.lastModified = path.lastModified();
this.fileLen = source.getChannel().size();
this.end = fileLen;
} catch (IOException e) {
try {
source.close();
} catch (IOException closeError) {
// Ignore any error closing the stream.
}
final FileNotFoundException r;
r = new FileNotFoundException("Cannot get length of " + path);
r.initCause(e);
throw r;
}
}
void close() {
try {
source.close();
} catch (IOException e) {
// Ignore close errors on a read-only stream.
}
}
long getLastModified() {
return lastModified;
}
String getTailChecksum() throws IOException {
final int n = 20;
final byte[] buf = new byte[n];
IO.readFully(source.getChannel(), fileLen - n, buf, 0, n);
return ObjectId.fromRaw(buf).getName();
}
void serve(final HttpServletRequest req, final HttpServletResponse rsp,
final boolean sendBody) throws IOException {
if (!initRangeRequest(req, rsp)) {
rsp.sendError(SC_REQUESTED_RANGE_NOT_SATISFIABLE);
return;
}
rsp.setHeader(HDR_ACCEPT_RANGES, "bytes");
rsp.setHeader(HDR_CONTENT_LENGTH, Long.toString(end - pos));
if (sendBody) {
final OutputStream out = rsp.getOutputStream();
try {
final byte[] buf = new byte[4096];
while (pos < end) {
final int r = (int) Math.min(buf.length, end - pos);
final int n = source.read(buf, 0, r);
if (n < 0) {
throw new EOFException("Unexpected EOF on " + path);
}
out.write(buf, 0, n);
pos += n;
}
out.flush();
} finally {
out.close();
}
}
}
private boolean initRangeRequest(final HttpServletRequest req,
final HttpServletResponse rsp) throws IOException {
final Enumeration<String> rangeHeaders = getRange(req);
if (!rangeHeaders.hasMoreElements()) {
// No range headers, the request is fine.
return true;
}
final String range = rangeHeaders.nextElement();
if (rangeHeaders.hasMoreElements()) {
// To simplify the code we support only one range.
return false;
}
final int eq = range.indexOf('=');
final int dash = range.indexOf('-');
if (eq < 0 || dash < 0 || !range.startsWith("bytes=")) {
return false;
}
final String ifRange = req.getHeader(HDR_IF_RANGE);
if (ifRange != null && !getTailChecksum().equals(ifRange)) {
// If the client asked us to verify the ETag and its not
// what they expected we need to send the entire content.
return true;
}
try {
if (eq + 1 == dash) {
// "bytes=-500" means last 500 bytes
pos = Long.parseLong(range.substring(dash + 1));
pos = fileLen - pos;
} else {
// "bytes=500-" (position 500 to end)
// "bytes=500-1000" (position 500 to 1000)
pos = Long.parseLong(range.substring(eq + 1, dash));
if (dash < range.length() - 1) {
end = Long.parseLong(range.substring(dash + 1));
end++; // range was inclusive, want exclusive
}
}
} catch (NumberFormatException e) {
// We probably hit here because of a non-digit such as
// "," appearing at the end of the first range telling
// us there is a second range following. To simplify
// the code we support only one range.
return false;
}
if (end > fileLen) {
end = fileLen;
}
if (pos >= end) {
return false;
}
rsp.setStatus(SC_PARTIAL_CONTENT);
rsp.setHeader(HDR_CONTENT_RANGE, "bytes " + pos + "-" + (end - 1) + "/"
+ fileLen);
source.seek(pos);
return true;
}
@SuppressWarnings("unchecked")
private static Enumeration<String> getRange(final HttpServletRequest req) {
return req.getHeaders(HDR_RANGE);
}
}
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.eclipse.jgit.http.server;
import java.io.File;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import org.eclipse.jgit.http.server.glue.MetaServlet;
import org.eclipse.jgit.http.server.glue.RegexGroupFilter;
import org.eclipse.jgit.http.server.glue.ServletBinder;
import org.eclipse.jgit.http.server.resolver.FileResolver;
import org.eclipse.jgit.http.server.resolver.AsIsFileService;
import org.eclipse.jgit.http.server.resolver.RepositoryResolver;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.util.StringUtils;
/**
* Handles Git repository access over HTTP.
* <p>
* Applications embedding this servlet should map a directory path within the
* application to this servlet, for example:
*
* <pre>
* &lt;servlet&gt;
* &lt;servlet-name&gt;GitServlet&lt;/servlet-name&gt;
* &lt;servlet-class&gt;org.eclipse.jgit.http.server.GitServlet&lt;/servlet-class&gt;
* &lt;init-param&gt;
* &lt;param-name&gt;base-path&lt;/param-name&gt;
* &lt;param-value&gt;/var/srv/git&lt;/param-value&gt;
* &lt;/init-param&gt;
* &lt;init-param&gt;
* &lt;param-name&gt;export-all&lt;/param-name&gt;
* &lt;param-value&gt;0&lt;/param-value&gt;
* &lt;/init-param&gt;
* &lt;/servlet&gt;
* &lt;servlet-mapping&gt;
* &lt;servlet-name&gt;GitServlet&lt;/servlet-name&gt;
* &lt;url-pattern&gt;/git/*&lt;/url-pattern&gt;
* &lt;/servlet-mapping&gt;
* </pre>
*
* <p>
* Applications may wish to add additional repository action URLs to this
* servlet by taking advantage of its extension from {@link MetaServlet}.
* Callers may register their own URL suffix translations through
* {@link #serve(String)}, or their regex translations through
* {@link #serveRegex(String)}. Each translation should contain a complete
* filter pipeline which ends with the HttpServlet that should handle the
* requested action.
*/
public class GitServlet extends MetaServlet {
private static final long serialVersionUID = 1L;
private volatile boolean initialized;
private RepositoryResolver resolver;
private AsIsFileService asIs = new AsIsFileService();
/**
* New servlet that will load its base directory from {@code web.xml}.
* <p>
* The required parameter {@code base-path} must be configured to point to
* the local filesystem directory where all served Git repositories reside.
*/
public GitServlet() {
// Initialized above by field declarations.
}
/**
* New servlet configured with a specific resolver.
*
* @param resolver
* the resolver to use when matching URL to Git repository. If
* null the {@code base-path} parameter will be looked for in the
* parameter table during init, which usually comes from the
* {@code web.xml} file of the web application.
*/
public void setRepositoryResolver(RepositoryResolver resolver) {
assertNotInitialized();
this.resolver = resolver;
}
/**
* @param f
* the filter to validate direct access to repository files
* through a dumb client. If {@code null} then dumb client
* support is completely disabled.
*/
public void setAsIsFileService(AsIsFileService f) {
assertNotInitialized();
this.asIs = f != null ? f : AsIsFileService.DISABLED;
}
private void assertNotInitialized() {
if (initialized)
throw new IllegalStateException("Already initialized by container");
}
@Override
public void init(final ServletConfig config) throws ServletException {
super.init(config);
if (resolver == null) {
final File root = getFile("base-path");
final boolean exportAll = getBoolean("export-all");
setRepositoryResolver(new FileResolver(root, exportAll));
}
initialized = true;
if (asIs != AsIsFileService.DISABLED) {
final IsLocalFilter mustBeLocal = new IsLocalFilter();
final AsIsFileFilter enabled = new AsIsFileFilter(asIs);
serve("*/" + Constants.INFO_REFS)//
.through(mustBeLocal)//
.through(enabled)//
.with(new InfoRefsServlet());
serve("*/" + Constants.HEAD)//
.through(mustBeLocal)//
.through(enabled)//
.with(new TextFileServlet(Constants.HEAD));
final String info_alternates = "objects/info/alternates";
serve("*/" + info_alternates)//
.through(mustBeLocal)//
.through(enabled)//
.with(new TextFileServlet(info_alternates));
final String http_alternates = "objects/info/http-alternates";
serve("*/" + http_alternates)//
.through(mustBeLocal)//
.through(enabled)//
.with(new TextFileServlet(http_alternates));
serve("*/objects/info/packs")//
.through(mustBeLocal)//
.through(enabled)//
.with(new InfoPacksServlet());
serveRegex("^/(.*)/objects/([0-9a-f]{2}/[0-9a-f]{38})$")//
.through(mustBeLocal)//
.through(enabled)//
.through(new RegexGroupFilter(2))//
.with(new ObjectFileServlet.Loose());
serveRegex("^/(.*)/objects/(pack/pack-[0-9a-f]{40}\\.pack)$")//
.through(mustBeLocal)//
.through(enabled)//
.through(new RegexGroupFilter(2))//
.with(new ObjectFileServlet.Pack());
serveRegex("^/(.*)/objects/(pack/pack-[0-9a-f]{40}\\.idx)$")//
.through(mustBeLocal)//
.through(enabled)//
.through(new RegexGroupFilter(2))//
.with(new ObjectFileServlet.PackIdx());
}
}
private File getFile(final String param) throws ServletException {
String n = getInitParameter(param);
if (n == null || "".equals(n))
throw new ServletException("Parameter " + param + " not set");
File path = new File(n);
if (!path.exists())
throw new ServletException(path + " (for " + param + ") not found");
return path;
}
private boolean getBoolean(String param) throws ServletException {
String n = getInitParameter(param);
if (n == null)
return false;
try {
return StringUtils.toBoolean(n);
} catch (IllegalArgumentException err) {
throw new ServletException("Invalid boolean " + param + " = " + n);
}
}
@Override
protected ServletBinder register(ServletBinder binder) {
if (resolver == null)
throw new IllegalStateException("No resolver available");
binder = binder.through(new NoCacheFilter());
binder = binder.through(new RepositoryFilter(resolver));
return binder;
}
}
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.eclipse.jgit.http.server;
import static org.eclipse.jgit.http.server.ServletUtils.getRepository;
import static org.eclipse.jgit.http.server.ServletUtils.sendPlainText;
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.lib.ObjectDatabase;
import org.eclipse.jgit.lib.ObjectDirectory;
import org.eclipse.jgit.lib.PackFile;
/** Sends the current list of pack files, sorted most recent first. */
class InfoPacksServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(final HttpServletRequest req,
final HttpServletResponse rsp) throws IOException {
sendPlainText(packList(req), req, rsp);
}
private static String packList(final HttpServletRequest req) {
final StringBuilder out = new StringBuilder();
final ObjectDatabase db = getRepository(req).getObjectDatabase();
if (db instanceof ObjectDirectory) {
for (PackFile pack : ((ObjectDirectory) db).getPacks()) {
out.append("P ");
out.append(pack.getPackFile().getName());
out.append('\n');
}
}
out.append('\n');
return out.toString();
}
}
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.eclipse.jgit.http.server;
import static org.eclipse.jgit.http.server.ServletUtils.getRepository;
import static org.eclipse.jgit.http.server.ServletUtils.send;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevFlag;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.RefAdvertiser;
import org.eclipse.jgit.util.HttpSupport;
/** Send a complete list of current refs, including peeled values for tags. */
class InfoRefsServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(final HttpServletRequest req,
final HttpServletResponse rsp) throws IOException {
// Assume a dumb client and send back the dumb client
// version of the info/refs file.
final byte[] raw = dumbHttp(req);
rsp.setContentType(HttpSupport.TEXT_PLAIN);
rsp.setCharacterEncoding(Constants.CHARACTER_ENCODING);
send(raw, req, rsp);
}
private byte[] dumbHttp(final HttpServletRequest req) throws IOException {
final Repository db = getRepository(req);
final RevWalk walk = new RevWalk(db);
final RevFlag ADVERTISED = walk.newFlag("ADVERTISED");
final StringBuilder out = new StringBuilder();
final RefAdvertiser adv = new RefAdvertiser() {
@Override
protected void writeOne(final CharSequence line) {
// Whoever decided that info/refs should use a different
// delimiter than the native git:// protocol shouldn't
// be allowed to design this sort of stuff. :-(
out.append(line.toString().replace(' ', '\t'));
}
@Override
protected void end() {
// No end marker required for info/refs format.
}
};
adv.init(walk, ADVERTISED);
adv.setDerefTags(true);
Map<String, Ref> refs = new HashMap<String, Ref>(db.getAllRefs());
refs.remove(Constants.HEAD);
adv.send(refs.values());
return out.toString().getBytes(Constants.CHARACTER_ENCODING);
}
}
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.eclipse.jgit.http.server;
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static org.eclipse.jgit.http.server.ServletUtils.getRepository;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.lib.ObjectDirectory;
import org.eclipse.jgit.lib.Repository;
/**
* Requires the target {@link Repository} to be available via local filesystem.
* <p>
* The target {@link Repository} must be using a {@link ObjectDirectory}, so the
* downstream servlet can directly access its contents on disk.
*/
class IsLocalFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
// Do nothing.
}
public void destroy() {
// Do nothing.
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (isLocal(getRepository(request)))
chain.doFilter(request, response);
else
((HttpServletResponse) response).sendError(SC_FORBIDDEN);
}
private static boolean isLocal(final Repository db) {
return db.getObjectDatabase() instanceof ObjectDirectory;
}
}
/*
* Copyright (C) 2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.eclipse.jgit.http.server;
import static org.eclipse.jgit.util.HttpSupport.HDR_CACHE_CONTROL;
import static org.eclipse.jgit.util.HttpSupport.HDR_EXPIRES;
import static org.eclipse.jgit.util.HttpSupport.HDR_PRAGMA;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
/** Adds HTTP response headers to prevent caching by proxies/browsers. */
class NoCacheFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
// Do nothing.
}
public void destroy() {
// Do nothing.
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse rsp = (HttpServletResponse) response;
rsp.setHeader(HDR_EXPIRES, "Fri, 01 Jan 1980 00:00:00 GMT");
rsp.setHeader(HDR_PRAGMA, "no-cache");
final String nocache = "no-cache, max-age=0, must-revalidate";
rsp.setHeader(HDR_CACHE_CONTROL, nocache);
chain.doFilter(request, response);
}
}
/*
* Copyright (C) 2009-2010, Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Distribution License v1.0 which
* accompanies this distribution, is reproduced below, and is
* available at http://www.eclipse.org/org/documents/edl-v10.php
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* - Neither the name of the Eclipse Foundation, Inc. nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.eclipse.jgit.http.server;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_NOT_MODIFIED;
import static org.eclipse.jgit.http.server.ServletUtils.getRepository;
import static org.eclipse.jgit.util.HttpSupport.HDR_ETAG;
import static org.eclipse.jgit.util.HttpSupport.HDR_IF_MODIFIED_SINCE;
import static org.eclipse.jgit.util.HttpSupport.HDR_IF_NONE_MATCH;
import static org.eclipse.jgit.util.HttpSupport.HDR_LAST_MODIFIED;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jgit.lib.ObjectDirectory;
import org.eclipse.jgit.lib.Repository;
/** Sends any object from {@code GIT_DIR/objects/??/0 38}, or any pack file. */
abstract class ObjectFileServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
static class Loose extends ObjectFileServlet {
private static final long serialVersionUID = 1L;
Loose() {
super("application/x-git-loose-object");
}
@Override
String etag(final FileSender sender) throws IOException {
return Long.toHexString(sender.getLastModified());
}
}
private static abstract class PackData extends ObjectFileServlet {
private static final long serialVersionUID = 1L;
PackData(String contentType) {
super(contentType);
}
@Override
String etag(final FileSender sender) throws IOException {
return sender.getTailChecksum();
}
}
static class Pack extends PackData {
private static final long serialVersionUID = 1L;
Pack() {
super("application/x-git-packed-objects");
}
}
static class PackIdx extends PackData {
private static final long serialVersionUID = 1L;
PackIdx() {
super("application/x-git-packed-objects-toc");
}
}
private final String contentType;
ObjectFileServlet(final String contentType) {
this.contentType = contentType;
}
abstract String etag(FileSender sender) throws IOException;
@Override
public void doGet(final HttpServletRequest req,
final HttpServletResponse rsp) throws IOException {
serve(req, rsp, true);
}
@Override
protected void doHead(final HttpServletRequest req,
final HttpServletResponse rsp) throws ServletException, IOException {
serve(req, rsp, false);
}
private void serve(final HttpServletRequest req,
final HttpServletResponse rsp, final boolean sendBody)
throws IOException {
final File obj = new File(objects(req), req.getPathInfo());
final FileSender sender;
try {
sender = new FileSender(obj);
} catch (FileNotFoundException e) {
rsp.sendError(SC_NOT_FOUND);
return;
}
try {
final String etag = etag(sender);
final long lastModified = (sender.getLastModified() / 1000) * 1000;
String ifNoneMatch = req.getHeader(HDR_IF_NONE_MATCH);
if (etag != null && etag.equals(ifNoneMatch)) {
rsp.sendError(SC_NOT_MODIFIED);
return;
}
long ifModifiedSince = req.getDateHeader(HDR_IF_MODIFIED_SINCE);
if (0 < lastModified && lastModified < ifModifiedSince) {
rsp.sendError(SC_NOT_MODIFIED);
return;
}
if (etag != null)
rsp.setHeader(HDR_ETAG, etag);
if (0 < lastModified)
rsp.setDateHeader(HDR_LAST_MODIFIED, lastModified);
rsp.setContentType(contentType);
sender.serve(req, rsp, sendBody);
} finally {
sender.close();
}
}
private static File objects(final HttpServletRequest req) {
final Repository db = getRepository(req);
return ((ObjectDirectory) db.getObjectDatabase()).getDirectory();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment